Ukubhala eyethu imojula ephelelwe yisikhathi ene-capped ye-tarantool

Ukubhala eyethu imojula ephelelwe yisikhathi ene-capped ye-tarantool

Esikhathini esidlule sasibhekene nenkinga yokuhlanza ama-tuples ezindaweni i-tarantool. Ukuhlanza kwakudingeka kuqalwe hhayi lapho i-tarantool isivele iphelelwa yinkumbulo, kodwa kusenesikhathi nangemvamisa ethile. Kulo msebenzi, i-tarantool inemojula ebhalwe ngesiLua ebizwa ngokuthi ukuphelelwa yisikhathi. Ngemva kokusebenzisa le moduli isikhathi esifushane, saqaphela ukuthi yayingasifanele: ngenxa yokuhlanza njalo inani elikhulu ledatha, uLua walenga ku-GC. Ngakho-ke, sicabange ngokwakha imojuli yethu ephelelwe yisikhathi, sithemba ukuthi ikhodi ebhalwe ngolimi lomdabu lokuhlela izoxazulula izinkinga zethu ngendlela engcono kakhulu.

Isibonelo esihle kithi kwakuyimodyuli ye-tarantool ebizwa i-memcached. Indlela esetshenziswa kuyo isekelwe eqinisweni lokuthi insimu ehlukile idalwe esikhaleni, ebonisa isikhathi sokuphila se-tuple, ngamanye amazwi, i-ttl. Imojula engemuva iskena isikhala, iqhathanise i-TTL nesikhathi samanje bese inquma ukuthi iyisuse yini i-tuple noma cha. Ikhodi yemojuli ye-memcached ilula futhi inhle, kodwa ijwayelekile kakhulu. Okokuqala, akunaki uhlobo lwenkomba ekhaswayo nesusiwe. Okwesibili, kuphasishi ngalinye wonke ama-tuples askeniwe, inani lawo elingase libe likhulu impela. Futhi uma kumojula ephelelwe yisikhathi inkinga yokuqala yaxazululwa (inkomba yesihlahla yahlukaniswa yaba ikilasi elihlukile), khona-ke elesibili alizange lithole ukunakwa. Lawa maphuzu amathathu anqume kusengaphambili ukukhetha okuvuna ukubhala ikhodi yami.

Incazelo

Imibhalo ye-tarantool inokuhle kakhulu okokufundisa mayelana nendlela yokubhala izinqubo zakho ezigciniwe ku-C. Okokuqala, ngiphakamisa ukuthi uzijwayeze ngakho ukuze uqonde lokho okufakwayo ngemiyalo nekhodi ezovela ngezansi. Kuyafaneleka futhi ukunaka ireferensi ezintweni ezitholakalayo uma ubhala eyakho imojula ene-capped, okungukuthi ibhokisi, fiber, Inkomba ΠΈ txn.

Ake siqale kude futhi sibheke ukuthi imojuli ephelelwe yisikhathi ibukeka kanjani ngaphandle:

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)

Ukwenza kube lula, sethula i-tarantool kumkhombandlela lapho umtapo wethu we-libcapped-expirationd.so utholakala khona. Imisebenzi emibili ithunyelwa kusuka kulabhulali: qala futhi ubulale. Isinyathelo sokuqala ukwenza le misebenzi itholakale ku-Lua usebenzisa i-box.schema.func.create kanye ne-box.schema.user.grant. Bese udala isikhala lapho ama-tuples azoqukatha izinkambu ezintathu kuphela: eyokuqala iyinkomba ehlukile, eyesibili i-imeyili, futhi eyesithathu impilo yonke ye-tuple. Sakha inkomba yesihlahla phezu kwensimu yokuqala futhi siyibiza ngokuthi eyinhloko. Okulandelayo sithola into yokuxhuma kulabhulali yethu yomdabu.

Ngemva komsebenzi wokulungiselela, qalisa umsebenzi wokuqalisa:

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})

Lesi sibonelo sizosebenza ngesikhathi sokuskena ngokufana ncamashi nemojuli ephelelwe yisikhathi, ebhalwe ngesi-Lua. I-agumenti yokuqala kumsebenzi wokuqala yigama eliyingqayizivele lomsebenzi. Okwesibili yisihlonzi sesikhala. Eyesithathu inkomba eyingqayizivele lapho ama-tuples azosuswa khona. Okwesine inkomba okuzodalulwa ngayo ama-tuples. Eyesihlanu inombolo yenkundla ye-tuple ngesikhathi sokuphila (izinombolo ziqala ku-1, hhayi ku-0!). Eyesithupha neyesikhombisa izilungiselelo zokuskena. 1024 inombolo enkulu yama-tuples angabukwa kumsebenzi owodwa. 3600 β€” isikhathi sokuskena esigcwele ngemizuzwana.

Qaphela ukuthi isibonelo sisebenzisa inkomba efanayo yokukhasa nokususa. Uma lokhu kuyinkomba yesihlahla, khona-ke ukunqamula kwenziwa kusuka kukhiye omncane kuya komkhulu. Uma kukhona enye, isibonelo, inkomba ye-hash, khona-ke ukuvuthwa kwe-traversal kwenziwa, njengomthetho, ngokulandelana okungahleliwe. Wonke ama-tuples wesikhala askeniwe kuskena esisodwa.

Masifake ama-tuple ambalwa esikhaleni ngempilo yonke yamasekhondi angu-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}

Ake sihlole ukuthi ukufaka kube yimpumelelo:

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

Ake siphinde okukhethiwe ngemva kwemizuzwana engu-60+ (sibala kusukela ekuqaleni kokufakwa kwe-tuple yokuqala) futhi sibone ukuthi imojuli ephelelwe yisikhathi enesiphetho isicubunguliwe:

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

Masiwumise umsebenzi:

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

Ake sibheke isibonelo sesibili lapho kusetshenziswa khona inkomba ehlukile yokukhasa:

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)

Yonke into lapha iyafana nesesibonelweni sokuqala, ngaphandle kwezimbalwa ezimbalwa. Sakha inkomba yesihlahla phezulu kwenkundla yesithathu futhi siyibiza ngokuthi i-exp. Le nkomba akudingeki ihluke, ngokungafani nenkomba ebizwa ngokuthi i-primary. I-Traversal izokwenziwa nge-exp index, futhi isuswe ngokuyinhloko. Siyakhumbula ukuthi ngaphambilini zombili zazenziwa kusetshenziswa inkomba yokuqala.

Ngemva komsebenzi wokulungiselela, senza umsebenzi wokuqalisa ngezimpikiswano ezintsha:

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

Ake sifake ama-tuple ambalwa esikhaleni futhi ngempilo yamasekhondi angu-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}

Ngemuva kwemizuzwana engama-30, ngokufanisa, sizofaka amanye ama-tuples ambalwa:

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}

Ake sihlole ukuthi ukufaka kube yimpumelelo:

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]
...

Ake siphinde okukhethiwe ngemva kwemizuzwana engu-60+ (sibala kusukela ekuqaleni kokufakwa kwe-tuple yokuqala) futhi sibone ukuthi imojuli ephelelwe yisikhathi enesiphetho isicubunguliwe:

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

Kusenamanye ama-tuples asele esikhaleni azoba nemizuzwana engama-30 ngaphezulu ukuze aphile. Ngaphezu kwalokho, ukuskena kumile lapho usuka ku-tuple ene-ID engu-2 nempilo yakho yonke engu-1576421257 ukuya ku-tuple ene-ID engu-3 nempilo yonke engu-1576421287. Ama-Tuples anesikhathi sokuphila esingu-1576421287 noma ngaphezulu awazange askenwe ngenxa yoku-oda okhiye be-exp index. Lena imali ebesifuna ukuyizuza ekuqaleni.

Masiwumise umsebenzi:

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

Ukuqaliswa

Indlela engcono kakhulu yokusho ngazo zonke izici zephrojekthi umthombo wayo wangempela. ikhodi! Njengengxenye yokushicilelwa, sizogxila kuphela kumaphuzu abaluleke kakhulu, okungukuthi, ama-algorithms we-space bypass.

Izimpikiswano esizidlulisela endleleni yokuqala zigcinwa esakhiweni esibizwa ngokuthi 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;
};

Igama lesichasiso yigama lomsebenzi. Isibaluli_se-id yesikhala yisihlonzi sesikhala. Isibaluli se-rm_index_id siyinkomba yenkomba eyingqayizivele okuzosuswa ngayo ama-tuples. Isibaluli se-it_index_id siyisihlonzi senkomba lapho ama-tuples azokwelulwa khona. Isibaluli se-it_index_type siwuhlobo lwenkomba lapho ama-tuples azodalulwa khona. Isibaluli se-filed_no yinombolo yenkambu ye-tuple enokuphila konke. Isibaluli_sikasayizi we-scan inombolo enkulu yama-tuples askeniwe kumsebenzi owodwa. Isibaluli_sesikhathi sokuskena yisikhathi sokuskena esigcwele ngamasekhondi.

Ngeke sicabangele ukuhlukanisa izimpikiswano. Lona umsebenzi onzima kodwa olula, umtapo wolwazi ozokusiza ngawo msgpuck. Ubunzima bungavela kuphela ngezinkomba ezidluliswa ku-Lua njengesakhiwo sedatha esiyinkimbinkimbi ngohlobo lwe-mp_map, futhi singasebenzisi izinhlobo ezilula ze-mp_bool, mp_double, mp_int, mp_uint kanye ne-mp_array. Kodwa asikho isidingo sokuhlaziya yonke inkomba. Udinga nje ukuhlola ukuhluka kwayo, ubale uhlobo bese ukhipha isihlonzi.

Sibala ama-prototypes ayo yonke imisebenzi esetshenziselwa ukuhlukanisa:

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);

Manje ake siqhubekele entweni ebaluleke kakhulu - i-logic yokudlula isikhala nokususa ama-tuples. Ibhulokhi ngayinye yama-tuples angenkulu kunosayizi we-scan_size iyaskenwa futhi ilungiswe ngaphansi kokwenziwe okukodwa. Uma kuphumelele, lokhu kuthenga kuyenziwa, uma kwenzeka iphutha, kuyabuyiselwa emuva. I-agumenti yokugcina yomsebenzi we-expirationd_iterate iyisikhombi esiya ku-iterator lapho ukuskena kuqala khona noma okuqhubekayo. Lesi siphindaphinda sinyuswa ngaphakathi kuze kube yilapho kwenzeka iphutha, isikhala siphela, noma akwenzeki ukumisa inqubo kusenesikhathi. Umsebenzi expirationd_expired uhlola impilo ye-tuple, expirationd_delete isusa i-tuple, expirationd_breakable ihlola ukuthi sidinga ukuqhubeka yini.

Ikhodi yokusebenza ephelelwe yisikhathi:

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;
}

Ikhodi yomsebenzi iphelelwe yisikhathi_iphelelwe yisikhathi:

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 ikhodi yokusebenza:

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);
}

Ikhodi yomsebenzi expiration_breakable:

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

Uhlelo lokusebenza

Ungabuka ikhodi yomthombo ku lapha!

Source: www.habr.com

Engeza amazwana