Rubutun namu wanda ya ƙare ƙarewa don tarantool

Rubutun namu wanda ya ƙare ƙarewa don tarantool

Wani lokaci da ya wuce mun fuskanci matsalar tsaftace tuples a cikin sarari tarantool. Dole ne a fara tsaftacewa ba lokacin da tarantool ya riga ya ƙare ba, amma a gaba kuma a wani mitar. Don wannan aikin, tarantool yana da tsarin da aka rubuta a cikin Lua da ake kira karewa. Bayan amfani da wannan tsarin na ɗan gajeren lokaci, mun gane cewa bai dace da mu ba: saboda yawan tsaftacewar bayanai akai-akai, Lua ya rataye a cikin GC. Saboda haka, mun yi tunani game da haɓaka tsarin namu wanda ya ƙare, muna fatan cewa lambar da aka rubuta a cikin yaren shirye-shirye na asali zai magance matsalolinmu ta hanya mafi kyau.

Kyakkyawan misali a gare mu shine tsarin tarantool da ake kira memori. Hanyar da aka yi amfani da ita a cikinta ta dogara ne akan gaskiyar cewa an halicci filin daban a cikin sararin samaniya, wanda ke nuna rayuwar tuple, a wasu kalmomi, ttl. Tsarin da ke bango yana duba sararin samaniya, yana kwatanta TTL tare da lokacin yanzu kuma ya yanke shawarar ko za a share tuple ko a'a. Lambar memcached ɗin yana da sauƙi kuma kyakkyawa, amma kuma ya cika yawa. Na farko, baya la'akari da nau'in fihirisar da ake rarrafe da gogewa. Abu na biyu, akan kowane fasinja ana bincika duk tuples, adadin wanda zai iya zama babba. Kuma idan a cikin tsarin ƙarewa an warware matsalar farko (an raba alamar bishiyar zuwa wani nau'i daban-daban), to, na biyu har yanzu bai sami kulawa ba. Waɗannan maki uku sun ƙaddara zaɓi don neman rubuta lambar kaina.

Description

Takardun don tarantool yana da kyau sosai koyawa game da yadda ake rubuta hanyoyin da aka adana a cikin C. Da farko, ina ba da shawarar ku san kanku da shi don fahimtar waɗannan abubuwan da aka saka tare da umarni da lambar da za su bayyana a ƙasa. Har ila yau yana da daraja a kula da shi tunani zuwa abubuwan da suke samuwa lokacin rubuta naku kundin tsarin, wato akwatin, fiber, index и txn.

Bari mu fara daga nesa mu kalli yadda tsarin karewa da aka rufe yake kama da shi daga waje:

fiber = require('fiber')
net_box = require('net.box')
box.cfg{listen = 3300}
box.schema.func.create('libcapped-expirationd.start', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.start')
box.schema.func.create('libcapped-expirationd.kill', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.kill')
box.schema.space.create('tester')
box.space.tester:create_index('primary', {unique = true, parts = {1, 'unsigned'}})
capped_connection = net_box:new(3300)

Don sauƙi, muna ƙaddamar da tarantool a cikin kundin adireshi inda ɗakin karatun mu na libcapped-expirationd.so yake. Ana fitar da ayyuka biyu daga ɗakin karatu: farawa da kashe. Mataki na farko shine samar da waɗannan ayyuka daga Lua ta amfani da box.schema.func.create da box.schema.user.grant. Sannan ƙirƙirar sarari wanda tuples zai ƙunshi filayen guda uku kawai: na farko shine mai ganowa na musamman, na biyu shine imel, na uku shine rayuwar tuple. Muna gina alamar bishiyar a saman filin farko kuma mu kira shi na farko. Na gaba muna samun abin haɗin kai zuwa ɗakin karatu na ƙasarmu.

Bayan aikin shiri, gudanar da aikin farawa:

capped_connection:call('libcapped-expirationd.start', {'non-indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.primary, 3, 1024, 3600})

Wannan misalin zai yi aiki yayin dubawa daidai da tsarin da ya ƙare, wanda aka rubuta cikin Lua. Hujja ta farko zuwa aikin farawa shine sunan musamman na aikin. Na biyu shine mai gano sarari. Na uku shine fihirisa na musamman wanda za'a goge tuples. Na hudu shine ma'aunin da za a bi ta hanyar tuples. Na biyar shine adadin filin tuple tare da rayuwa (lambobi yana farawa daga 1, ba 0!). Na shida da na bakwai sune saitunan dubawa. 1024 shine matsakaicin adadin tuples waɗanda za'a iya gani a cikin ma'amala ɗaya. 3600 - cikakken lokacin dubawa a cikin daƙiƙa.

Lura cewa misalin yana amfani da fihirisa iri ɗaya don rarrafe da sharewa. Idan wannan ma'aunin bishiya ce, to ana yin tazarar ne daga ƙaramin maɓalli zuwa babba. Idan akwai wasu, alal misali, alamar zanta, to, ana aiwatar da zirga-zirga, a matsayin mai mulkin, a cikin tsari bazuwar. Ana duba duk tuples a sarari a cikin dubawa ɗaya.

Bari mu saka tuples da yawa cikin sararin samaniya tare da tsawon daƙiƙa 60:

box.space.tester:insert{0, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, '[email protected]', math.floor(fiber.time()) + 60}

Mu duba cewa shigar ya yi nasara:

tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576418976]
  - [1, '[email protected]', 1576418976]
  - [2, '[email protected]', 1576418976]
...

Bari mu maimaita zaɓin bayan daƙiƙa 60+ (ƙidaya daga farkon shigar tuple na farko) kuma mu ga cewa ƙirar da aka rufe ta riga an sarrafa ta:

tarantool> box.space.tester.index.primary:select()
---
  - []
...

Mu dakatar da aikin:

capped_connection:call('libcapped-expirationd.kill', {'non-indexed'})

Bari mu kalli misali na biyu inda aka yi amfani da fihirisa daban don rarrafe:

fiber = require('fiber')
net_box = require('net.box')
box.cfg{listen = 3300}
box.schema.func.create('libcapped-expirationd.start', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.start')
box.schema.func.create('libcapped-expirationd.kill', {language = 'C'})
box.schema.user.grant('guest', 'execute', 'function', 'libcapped-expirationd.kill')
box.schema.space.create('tester')
box.space.tester:create_index('primary', {unique = true, parts = {1, 'unsigned'}})
box.space.tester:create_index('exp', {unique = false, parts = {3, 'unsigned'}})
capped_connection = net_box:new(3300)

Duk abin da ke nan daidai yake da a cikin misali na farko, tare da wasu kaɗan. Muna gina alamar bishiyar a saman filin na uku kuma mu kira shi exp. Wannan fihirisa ba dole ba ne ya zama na musamman, sabanin ma'aunin da ake kira firamare. Za a gudanar da zirga-zirga ta hanyar index, da kuma sharewa ta firamare. Mun tuna cewa a baya duka an yi su ne kawai ta amfani da fihirisar farko.

Bayan aikin shiri, muna gudanar da aikin farawa tare da sababbin muhawara:

capped_connection:call('libcapped-expirationd.start', {'indexed', box.space.tester.id, box.space.tester.index.primary, box.space.tester.index.exp, 3, 1024, 3600})

Bari mu sake shigar da tuples da yawa cikin sarari tare da tsawon daƙiƙa 60:

box.space.tester:insert{0, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{1, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{2, '[email protected]', math.floor(fiber.time()) + 60}

Bayan daƙiƙa 30, ta hanyar kwatance, za mu ƙara wasu ƙarin tuples:

box.space.tester:insert{3, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{4, '[email protected]', math.floor(fiber.time()) + 60}
box.space.tester:insert{5, '[email protected]', math.floor(fiber.time()) + 60}

Mu duba cewa shigar ya yi nasara:

tarantool> box.space.tester.index.primary:select()
---
- - [0, '[email protected]', 1576421257]
  - [1, '[email protected]', 1576421257]
  - [2, '[email protected]', 1576421257]
  - [3, '[email protected]', 1576421287]
  - [4, '[email protected]', 1576421287]
  - [5, '[email protected]', 1576421287]
...

Bari mu maimaita zaɓin bayan daƙiƙa 60+ (ƙidaya daga farkon shigar tuple na farko) kuma mu ga cewa ƙirar da aka rufe ta riga an sarrafa ta:

tarantool> box.space.tester.index.primary:select()
---
- - [3, '[email protected]', 1576421287]
  - [4, '[email protected]', 1576421287]
  - [5, '[email protected]', 1576421287]
...

Har yanzu akwai wasu tuples da suka rage a sararin samaniya waɗanda za su sami ƙarin daƙiƙa 30 don rayuwa. Haka kuma, da scan tsaya a lokacin da motsi daga wani tuple tare da wani ID na 2 da kuma rayuwa na 1576421257 zuwa tuple tare da wani ID na 3 da kuma rayuwa na 1576421287. maɓallan index index. Wannan shi ne tanadin da muke so mu samu tun da farko.

Mu dakatar da aikin:

capped_connection:call('libcapped-expirationd.kill', {'indexed'})

Aiwatarwa

Hanya mafi kyau don faɗi game da duk fasalulluka na aikin shine asalin sa. lambar! A matsayin wani ɓangare na ɗaba'ar, za mu mai da hankali ne kawai akan mahimman mahimman bayanai, wato, sararin samaniya algorithms.

Ana adana muhawarar da muka wuce zuwa hanyar farawa a cikin tsarin da ake kira expirationd_task:

struct expirationd_task
{
  char name[256];
  uint32_t space_id;
  uint32_t rm_index_id;
  uint32_t it_index_id;
  uint32_t it_index_type; 
  uint32_t field_no;
  uint32_t scan_size;
  uint32_t scan_time;
};

Sifarin sunan shine sunan aikin. Siffar space_id ita ce mai gano sarari. Siffar rm_index_id ita ce mai gano keɓaɓɓen fihirisar da za a share tuples. Siffar it_index_id ita ce mai gano ma'anar da za a bi ta hanyar tuples. Siffar it_index_type shine nau'in fihirisar da za a bi ta hanyar tuples. Siffar filed_no ita ce adadin filin tuple tare da tsawon rayuwa. Siffar scan_size ita ce matsakaicin adadin tuples waɗanda aka bincika a cikin ciniki ɗaya. Siffar scan_time shine cikakken lokacin dubawa a cikin daƙiƙa.

Ba za mu yi la'akari da rarraba muhawara ba. Wannan aiki ne mai wahala amma mai sauƙi, wanda ɗakin karatu zai taimake ku da shi msgpuck. Matsaloli na iya tasowa tare da fihirisar da aka wuce daga Lua a matsayin hadadden tsarin bayanai tare da nau'in mp_map, kuma ba amfani da sauƙaƙan nau'ikan mp_bool, mp_double, mp_int, mp_uint da mp_array. Amma babu buƙatar rarraba duka fihirisar. Kawai kawai kuna buƙatar bincika bambancinsa, ƙididdige nau'in kuma cire mai ganowa.

Mun jera samfuran duk ayyukan da ake amfani da su don tantancewa:

bool expirationd_parse_name(struct expirationd_task *task, const char **pos);
bool expirationd_parse_space_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index_unique(struct expirationd_task *task, const char **pos);
bool expirationd_parse_rm_index(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index_id(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index_type(struct expirationd_task *task, const char **pos);
bool expirationd_parse_it_index(struct expirationd_task *task, const char **pos);
bool expirationd_parse_field_no(struct expirationd_task *task, const char **pos);
bool expirationd_parse_scan_size(struct expirationd_task *task, const char **pos);
bool expirationd_parse_scan_time(struct expirationd_task *task, const char **pos);

Yanzu bari mu matsa zuwa mafi muhimmanci - dabaru na kewaye sarari da kuma share tuples. Kowane tubalan tuples da bai fi girman scan_size ba ana duba su kuma an gyara su ƙarƙashin ma'amala guda ɗaya. Idan an yi nasara, ana yin wannan ciniki; idan kuskure ya faru, ana juya shi baya. Hujja ta ƙarshe zuwa aikin expirationd_iterate ita ce mai nuni ga mai ƙira daga inda ake farawa ko ci gaba da dubawa. Ana ƙara wannan mai maimaitawa a ciki har sai an sami kuskure, sararin samaniya ya ƙare, ko kuma ba zai yiwu a dakatar da aikin a gaba ba. Aikin expirationd_expired yana duba tsawon rayuwar tuple, expirationd_delete yana goge tuple, expirationd_breakable cak ko muna buƙatar ci gaba.

Expirated_iterate code aiki:

static bool
expirationd_iterate(struct expirationd_task *task, box_iterator_t **iterp)
{
  box_iterator_t *iter = *iterp;
  box_txn_begin();
  for (uint32_t i = 0; i < task->scan_size; ++i) {
    box_tuple_t *tuple = NULL;
    if (box_iterator_next(iter, &tuple) < 0) {
      box_iterator_free(iter);
      *iterp = NULL;
      box_txn_rollback();
      return false;
    }
    if (!tuple) {
      box_iterator_free(iter);
      *iterp = NULL;
      box_txn_commit();
      return true;
    }
    if (expirationd_expired(task, tuple))
      expirationd_delete(task, tuple);
    else if (expirationd_breakable(task))
      break;
  }
  box_txn_commit();
  return true;
}

Lambar aiki ta ƙare_ ƙarewa:

static bool
expirationd_expired(struct expirationd_task *task, box_tuple_t *tuple)
{
  const char *buf = box_tuple_field(tuple, task->field_no - 1);
  if (!buf || mp_typeof(*buf) != MP_UINT)
    return false;
  uint64_t val = mp_decode_uint(&buf);
  if (val > fiber_time64() / 1000000)
    return false;
  return true;
}

Expirationd_delete code aiki:

static void
expirationd_delete(struct expirationd_task *task, box_tuple_t *tuple)
{
  uint32_t len;
  const char *str = box_tuple_extract_key(tuple, task->space_id, task->rm_index_id, &len);
  box_delete(task->space_id, task->rm_index_id, str, str + len, NULL);
}

Karewa lambar aiki_breakable:

static bool
expirationd_breakable(struct expirationd_task *task)
{
  return task->it_index_id != task->rm_index_id && task->it_index_type == ITER_GT;
}

Aikace-aikacen

Kuna iya duba lambar tushe a a nan!

source: www.habr.com

Add a comment