Wani lokaci da ya wuce mun fuskanci matsalar tsaftace tuples a cikin sarari
Kyakkyawan misali a gare mu shine tsarin tarantool da ake kira
Description
Takardun don tarantool yana da kyau sosai
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.
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
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
source: www.habr.com