Kikọ module ipari ipari ti ara wa fun tarantool

Kikọ module ipari ipari ti ara wa fun tarantool

Ni akoko diẹ sẹyin a dojuko pẹlu iṣoro ti mimọ tuples ni awọn aaye tarantool. Ninu ni lati bẹrẹ kii ṣe nigbati tarantool ti nṣiṣẹ tẹlẹ ti iranti, ṣugbọn ni ilosiwaju ati ni igbohunsafẹfẹ kan. Fun iṣẹ ṣiṣe yii, tarantool ni module ti a kọ si Lua ti a pe ipari. Lẹhin lilo module yii fun igba diẹ, a rii pe ko dara fun wa: nitori mimọ nigbagbogbo ti awọn oye nla ti data, Lua fikọ sinu GC. Nitorinaa, a ronu nipa idagbasoke module ipari ipari ti ara wa, nireti pe koodu ti a kọ sinu ede siseto abinibi yoo yanju awọn iṣoro wa ni ọna ti o dara julọ.

Apẹẹrẹ ti o dara fun wa ni module tarantool ti a pe memcached. Ọna ti a lo ninu rẹ da lori otitọ pe a ṣẹda aaye ọtọtọ ni aaye, eyiti o tọka si igbesi aye tuple, ni awọn ọrọ miiran, ttl. Awọn module ni abẹlẹ léraléra awọn aaye, safiwe TTL pẹlu awọn ti isiyi akoko ati pinnu boya lati pa awọn tuple tabi ko. Awọn memcached module koodu ni o rọrun ati ki o yangan, sugbon ju jeneriki. Ni akọkọ, ko ṣe akiyesi iru atọka ti o npa ati paarẹ. Ẹlẹẹkeji, lori kọọkan kọja gbogbo tuples ti wa ni ti ṣayẹwo, awọn nọmba ti eyi ti o le jẹ ohun ti o tobi. Ati pe ti o ba wa ninu module ipari ti iṣoro akọkọ ti yanju (atọka igi ti yapa si kilasi lọtọ), lẹhinna keji ko tun gba akiyesi eyikeyi. Awọn aaye mẹta wọnyi ti pinnu yiyan ni ojurere ti kikọ koodu ti ara mi.

Apejuwe

Awọn iwe fun tarantool ni o dara pupọ ikẹkọ nipa bi o ṣe le kọ awọn ilana ti o fipamọ ni C. Ni akọkọ, Mo daba pe ki o mọ ara rẹ pẹlu rẹ lati ni oye awọn ifibọ wọnyẹn pẹlu awọn aṣẹ ati koodu ti yoo han ni isalẹ. O tun tọ lati san ifojusi si itọkasi si awọn ohun ti o wa nigba kikọ ara rẹ capped module, eyun apoti, okun, Ìwé и txn.

Jẹ ki a bẹrẹ lati ọna jijin ki o wo kini module ipari ipari ti o dabi lati ita:

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)

Fun ayedero, a ṣe ifilọlẹ tarantool ninu itọsọna nibiti ile-ikawe libcapped-expirationd.so wa. Meji awọn iṣẹ ti wa ni okeere lati awọn ìkàwé: bẹrẹ ati ki o pa. Igbesẹ akọkọ ni lati jẹ ki awọn iṣẹ wọnyi wa lati Lua nipa lilo box.schema.func.create ati box.schema.user.grant. Lẹhinna ṣẹda aaye ti awọn tuples yoo ni awọn aaye mẹta nikan: akọkọ jẹ idanimọ alailẹgbẹ, ekeji jẹ imeeli, ati ẹkẹta ni igbesi aye tuple naa. A kọ atọka igi lori oke aaye akọkọ ati pe o ni akọkọ. Nigbamii ti a gba nkan asopọ si ile-ikawe abinibi wa.

Lẹhin iṣẹ igbaradi, mu iṣẹ ibẹrẹ ṣiṣẹ:

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

Apeere yii yoo ṣiṣẹ lakoko ṣiṣe ayẹwo ni pato gẹgẹbi module ipari, eyiti a kọ ni Lua. Ariyanjiyan akọkọ si iṣẹ ibẹrẹ jẹ orukọ alailẹgbẹ ti iṣẹ-ṣiṣe naa. Èkejì jẹ́ ìdánimọ̀ àlàfo. Ẹkẹta jẹ atọka alailẹgbẹ nipasẹ eyiti awọn tuples yoo paarẹ. Ẹkẹrin ni atọka nipasẹ eyiti awọn tuples yoo wa kọja. Karun jẹ nọmba ti aaye tuple pẹlu igbesi aye (nọmba bẹrẹ lati 1, kii ṣe 0!). Ẹkẹfa ati keje jẹ awọn eto ọlọjẹ. 1024 jẹ nọmba ti o pọju ti awọn tuples ti o le wo ni idunadura kan. 3600 - akoko ọlọjẹ ni kikun ni iṣẹju-aaya.

Ṣe akiyesi pe apẹẹrẹ nlo atọka kanna fun jijoko ati piparẹ. Ti eyi ba jẹ atọka igi, lẹhinna a ti gbe irin-ajo naa lati bọtini kekere si eyi ti o tobi julọ. Ti o ba wa diẹ ninu awọn miiran, fun apẹẹrẹ, atọka hash, lẹhinna iṣipopada naa ni a ṣe, gẹgẹbi ofin, ni aṣẹ laileto. Gbogbo awọn tuples aaye ti ṣayẹwo ni ọlọjẹ kan.

Jẹ ki a fi ọpọlọpọ awọn tuples sinu aaye pẹlu igbesi aye ti awọn aaya 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}

Jẹ ki a ṣayẹwo pe fifi sii jẹ aṣeyọri:

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

Jẹ ki a tun yan lẹhin awọn aaya 60+ (kika lati ibẹrẹ fifi sii ti tuple akọkọ) ki o rii pe module ipari ipari ti ni ilọsiwaju tẹlẹ:

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

Jẹ ki a da iṣẹ naa duro:

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

Jẹ ki a wo apẹẹrẹ keji nibiti a ti lo atọka ọtọtọ fun jijoko:

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)

Ohun gbogbo nibi jẹ kanna bi ninu apẹẹrẹ akọkọ, pẹlu awọn imukuro diẹ. A kọ atọka igi lori oke aaye kẹta ati pe o exp. Atọka yii ko ni lati jẹ alailẹgbẹ, ko dabi atọka ti a pe ni akọkọ. Traversal yoo ṣee ṣe nipasẹ atọka exp, ati piparẹ nipasẹ akọkọ. A ranti pe ni iṣaaju awọn mejeeji ni a ṣe nikan ni lilo atọka akọkọ.

Lẹhin iṣẹ igbaradi, a ṣiṣẹ iṣẹ ibẹrẹ pẹlu awọn ariyanjiyan tuntun:

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

Jẹ ki a fi ọpọlọpọ awọn tuples sinu aaye lẹẹkansii pẹlu igbesi aye awọn aaya 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}

Lẹhin awọn aaya 30, nipasẹ afiwe, a yoo ṣafikun awọn tuple diẹ diẹ sii:

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}

Jẹ ki a ṣayẹwo pe fifi sii jẹ aṣeyọri:

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

Jẹ ki a tun yan lẹhin awọn aaya 60+ (kika lati ibẹrẹ fifi sii ti tuple akọkọ) ki o rii pe module ipari ipari ti ni ilọsiwaju tẹlẹ:

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

Awọn tuples kan tun wa ni aaye ti yoo ni bii ọgbọn iṣẹju diẹ sii lati gbe. Pẹlupẹlu, ọlọjẹ naa duro nigbati o ba nlọ lati tuple kan pẹlu ID ti 30 ati igbesi aye 2 si tuple kan pẹlu ID ti 1576421257 ati igbesi aye 3. Tuples pẹlu igbesi aye 1576421287 tabi diẹ sii ko ṣe ayẹwo nitori aṣẹ ti aṣẹ. awọn bọtini atọka exp. Eyi ni awọn ifowopamọ ti a fẹ lati ṣaṣeyọri ni ibẹrẹ akọkọ.

Jẹ ki a da iṣẹ naa duro:

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

Imuse

Ọna ti o dara julọ lati sọ nipa gbogbo awọn ẹya ti iṣẹ akanṣe jẹ orisun atilẹba rẹ. koodu! Gẹgẹbi apakan ti ikede, a yoo dojukọ nikan lori awọn aaye pataki julọ, eyun, awọn algorithms fori aaye.

Awọn ariyanjiyan ti a kọja si ọna ibẹrẹ ti wa ni ipamọ sinu eto ti a pe ni 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;
};

Ẹya orukọ jẹ orukọ iṣẹ-ṣiṣe naa. Iwa space_id jẹ idanimọ aaye. Iwa rm_index_id jẹ idamọ ti atọka alailẹgbẹ nipasẹ eyiti awọn tuples yoo paarẹ. Ẹya it_index_id jẹ idamọ atọka nipasẹ eyiti awọn tuples yoo gba kọja. Ẹya it_index_type jẹ iru atọka nipasẹ eyiti awọn tuples yoo gba kọja. Ẹya filed_no jẹ nọmba ti aaye tuple pẹlu igbesi aye. Ẹya scan_size jẹ nọmba ti o pọju ti awọn tuples ti a ṣayẹwo ni idunadura kan. Iwa scan_time jẹ akoko ọlọjẹ kikun ni iṣẹju-aaya.

A kii yoo gbero awọn ariyanjiyan itọye. Eyi jẹ irora ṣugbọn iṣẹ ti o rọrun, pẹlu eyiti ile-ikawe yoo ṣe iranlọwọ fun ọ msgpuck. Awọn iṣoro le dide nikan pẹlu awọn atọka ti o kọja lati Lua gẹgẹbi igbekalẹ data eka pẹlu iru mp_map, ati pe kii ṣe lilo awọn oriṣi ti o rọrun mp_bool, mp_double, mp_int, mp_uint ati mp_array. Ṣugbọn ko si iwulo lati sọ gbogbo itọka naa. O kan nilo lati ṣayẹwo iyasọtọ rẹ, ṣe iṣiro iru ati jade idamo naa.

A ṣe atokọ awọn apẹẹrẹ ti gbogbo awọn iṣẹ ti a lo fun sisọ:

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

Nisisiyi ẹ ​​​​jẹ ki a lọ si ohun pataki julọ - imọran ti aaye ti o kọja ati piparẹ awọn tuples. Kọọkan Àkọsílẹ ti tuples ko tobi ju scan_size ti wa ni ti ṣayẹwo ati ki o títúnṣe labẹ kan nikan idunadura. Ti o ba ṣaṣeyọri, iṣowo yii ti ṣe; ti aṣiṣe ba waye, o ti yiyi pada. Awọn ti o kẹhin ariyanjiyan to expirationd_iterate iṣẹ ni a ijuboluwole si awọn iterator lati eyi ti Antivirus bẹrẹ tabi tẹsiwaju. Yi iterator ti wa ni afikun ti abẹnu titi ti aṣiṣe yoo waye, awọn aaye gbalaye jade, tabi o jẹ ko ṣee ṣe lati da awọn ilana ni ilosiwaju. Awọn iṣẹ expirationd_expired sọwedowo awọn s'aiye ti a tuple, expirationd_delete npa a tuple, expirationd_breakable sọwedowo boya a nilo lati gbe lori.

Expirationd_iterate koodu iṣẹ:

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

Koodu iṣẹ expired_expired:

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 koodu iṣẹ:

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

Koodu iṣẹ ipari_breakable:

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

Ohun elo

O le wo koodu orisun ni nibi!

orisun: www.habr.com

Fi ọrọìwòye kun