Uigaji wa kiwango cha juu katika Tarantool DBMS

Hujambo, ninaunda programu za DBMS Tarantool ni jukwaa lililotengenezwa na Mail.ru Group ambalo linachanganya DBMS ya utendaji wa juu na seva ya programu katika lugha ya Lua. Kasi ya juu ya ufumbuzi kulingana na Tarantool inafanikiwa, hasa, kutokana na usaidizi wa hali ya kumbukumbu ya DBMS na uwezo wa kutekeleza mantiki ya biashara ya maombi katika nafasi moja ya anwani na data. Wakati huo huo, kuendelea kwa data kunahakikishwa kwa kutumia shughuli za ACID (logi ya WAL inadumishwa kwenye diski). Tarantool ina usaidizi wa ndani wa urudufishaji na ugawaji. Kuanzia toleo la 2.1, maswali katika lugha ya SQL yanaauniwa. Tarantool ni chanzo huria na imepewa leseni chini ya leseni ya BSD Iliyorahisishwa. Pia kuna toleo la Biashara la Biashara.

Uigaji wa kiwango cha juu katika Tarantool DBMS
Kuhisi nguvu! (…aka furahia utendaji)

Yote haya hapo juu hufanya Tarantool kuwa jukwaa la kuvutia la kuunda programu zenye mzigo mkubwa zinazofanya kazi na hifadhidata. Katika programu kama hizi, mara nyingi kuna haja ya kurudia data.

Kama ilivyoelezwa hapo juu, Tarantool ina replication ya data iliyojengwa ndani. Kanuni ya uendeshaji wake ni kutekeleza kwa mfuatano kwenye nakala za shughuli zote zilizomo kwenye kumbukumbu kuu (WAL). Kawaida replication kama hiyo (tutaiita zaidi kiwango cha chini) hutumika kuhakikisha uvumilivu wa kosa la programu na/au kusambaza mzigo wa kusoma kati ya nodi za nguzo.

Uigaji wa kiwango cha juu katika Tarantool DBMS
Mchele. 1. Kuiga ndani ya nguzo

Mfano wa hali mbadala itakuwa ni kuhamisha data iliyoundwa katika hifadhidata moja hadi hifadhidata nyingine kwa ajili ya kuchakata/kufuatilia. Katika kesi ya mwisho, suluhisho rahisi zaidi inaweza kuwa kutumia ngazi ya juu replication - data replication katika kiwango cha mantiki ya biashara ya maombi. Wale. Hatutumii suluhu iliyotengenezwa tayari iliyojengwa ndani ya DBMS, lakini tunatekeleza urudufishaji wenyewe ndani ya programu tunayotengeneza. Njia hii ina faida na hasara zote mbili. Hebu tuorodhe faida.

1. Akiba ya trafiki:

  • Huwezi kuhamisha data zote, lakini sehemu yake tu (kwa mfano, unaweza kuhamisha baadhi ya meza tu, baadhi ya safu zao au rekodi zinazofikia kigezo fulani);
  • Tofauti na urudufishaji wa kiwango cha chini, ambao unafanywa mfululizo kwa njia isiyolingana (inayotekelezwa katika toleo la sasa la Tarantool - 1.10) au synchronous (kutekelezwa katika matoleo yajayo ya hali ya Tarantool), urudufishaji wa kiwango cha juu unaweza kufanywa katika vikao (yaani. maombi kwanza inasawazisha data - data ya kikao cha kubadilishana, kisha kuna pause katika kurudia, baada ya ambayo kikao cha kubadilishana kinachofuata kinatokea, nk);
  • ikiwa rekodi imebadilika mara kadhaa, unaweza kuhamisha toleo lake la hivi karibuni tu (tofauti na uigaji wa kiwango cha chini, ambapo mabadiliko yote yaliyofanywa kwa bwana yatachezwa kwa mfululizo kwenye nakala).

2. Hakuna matatizo katika kutekeleza ubadilishanaji wa HTTP, ambayo inakuwezesha kusawazisha hifadhidata za mbali.

Uigaji wa kiwango cha juu katika Tarantool DBMS
Mchele. 2. Urudufishaji kupitia HTTP

3. Miundo ya hifadhidata kati ya ambayo data huhamishwa sio lazima iwe sawa (zaidi ya hayo, kwa ujumla, inawezekana hata kutumia DBMS tofauti, lugha za programu, majukwaa, nk).

Uigaji wa kiwango cha juu katika Tarantool DBMS
Mchele. 3. Kuiga katika mifumo tofauti

Upande wa chini ni kwamba, kwa wastani, programu ni ngumu zaidi / ya gharama kubwa kuliko usanidi, na badala ya kubinafsisha utendakazi uliojengwa ndani, utalazimika kutekeleza yako mwenyewe.

Ikiwa katika hali yako faida zilizo hapo juu ni muhimu (au ni hali ya lazima), basi inafanya akili kutumia urudufishaji wa hali ya juu. Hebu tuangalie njia kadhaa za kutekeleza urudiaji wa data wa kiwango cha juu katika Tarantool DBMS.

Kupunguza trafiki

Kwa hivyo, moja ya faida za uigaji wa kiwango cha juu ni akiba ya trafiki. Ili faida hii ipatikane kikamilifu, ni muhimu kupunguza kiasi cha data iliyohamishwa wakati wa kila kikao cha kubadilishana. Bila shaka, hatupaswi kusahau kwamba mwishoni mwa kipindi, kipokea data lazima kisawazishwe na chanzo (angalau kwa sehemu hiyo ya data inayohusika katika urudufishaji).

Jinsi ya kupunguza kiasi cha data iliyohamishwa wakati wa uigaji wa kiwango cha juu? Suluhisho la moja kwa moja linaweza kuwa kuchagua data kwa tarehe na wakati. Ili kufanya hivyo, unaweza kutumia uga wa tarehe ambao tayari upo kwenye jedwali (ikiwa upo). Kwa mfano, hati ya "agizo" inaweza kuwa na sehemu "muda unaohitajika wa kutekeleza agizo" - delivery_time. Shida ya suluhisho hili ni kwamba maadili katika uwanja huu sio lazima yawe katika mlolongo unaolingana na uundaji wa maagizo. Kwa hivyo hatuwezi kukumbuka kiwango cha juu cha thamani ya uga delivery_time, iliyotumwa wakati wa kipindi cha awali cha ubadilishanaji, na wakati wa kipindi kijacho cha kubadilishana chagua rekodi zote zilizo na thamani ya juu ya uga delivery_time. Rekodi zilizo na thamani ya chini ya uga zinaweza kuwa zimeongezwa kati ya vipindi vya kubadilishana delivery_time. Pia, agizo hilo lingeweza kufanyiwa mabadiliko, ambayo hata hivyo hayakuathiri uwanja delivery_time. Katika visa vyote viwili, mabadiliko hayatahamishwa kutoka kwa chanzo hadi lengwa. Ili kutatua matatizo haya, tutahitaji kuhamisha data "kuingiliana". Wale. katika kila kipindi cha kubadilishana tutahamisha data yote yenye thamani ya sehemu delivery_time, kupita hatua fulani huko nyuma (kwa mfano, saa N kutoka wakati wa sasa). Hata hivyo, ni dhahiri kwamba kwa mifumo mikubwa mbinu hii ni ya ziada sana na inaweza kupunguza akiba ya trafiki ambayo tunajitahidi bure. Kwa kuongeza, jedwali linalohamishwa huenda lisiwe na sehemu inayohusishwa na muda wa tarehe.

Suluhisho lingine, ngumu zaidi katika suala la utekelezaji, ni kukiri upokeaji wa data. Katika kesi hii, wakati wa kila kikao cha kubadilishana, data yote hupitishwa, risiti ambayo haijathibitishwa na mpokeaji. Ili kutekeleza hili, utahitaji kuongeza safu wima ya Boolean kwenye jedwali la chanzo (kwa mfano, is_transferred) Ikiwa mpokeaji anakubali kupokea rekodi, sehemu inayolingana inachukua thamani true, baada ya hapo kuingia haishiriki tena katika kubadilishana. Chaguo hili la utekelezaji lina hasara zifuatazo. Kwanza, kwa kila rekodi iliyohamishwa, kibali lazima kitolewe na kutumwa. Kwa kusema, hii inaweza kulinganishwa na kuongeza maradufu kiasi cha data iliyohamishwa na kusababisha kuongezeka kwa idadi ya kurudi na kurudi. Pili, hakuna uwezekano wa kutuma rekodi sawa kwa wapokeaji kadhaa (mpokeaji wa kwanza kupokea atathibitisha risiti kwa ajili yake mwenyewe na kwa wengine wote).

Njia ambayo haina hasara zilizotolewa hapo juu ni kuongeza safu kwenye jedwali lililotumwa ili kufuatilia mabadiliko katika safu mlalo zake. Safu kama hiyo inaweza kuwa ya aina ya tarehe na lazima iwekwe/isasishwe na programu hadi wakati wa sasa kila wakati rekodi zinapoongezwa/kubadilishwa (kiotomatiki kwa nyongeza/mabadiliko). Kwa mfano, wacha tuite safu update_time. Kwa kuhifadhi kiwango cha juu cha dhamana ya uga ya safuwima hii kwa rekodi zilizohamishwa, tunaweza kuanza kipindi kijacho cha ubadilishaji na thamani hii (chagua rekodi zilizo na thamani ya sehemu. update_time, kupita thamani iliyohifadhiwa hapo awali). Shida ya mbinu ya mwisho ni kwamba mabadiliko ya data yanaweza kutokea katika vikundi. Kama matokeo ya maadili ya uwanja kwenye safu update_time inaweza isiwe ya kipekee. Kwa hivyo, safu wima hii haiwezi kutumika kwa matokeo yaliyogawanywa (ukurasa kwa ukurasa) data. Ili kuonyesha ukurasa wa data kwa ukurasa, utalazimika kuvumbua njia za ziada ambazo zitakuwa na ufanisi mdogo sana (kwa mfano, kupata kutoka kwa hifadhidata rekodi zote zilizo na thamani. update_time ya juu kuliko ile iliyotolewa na kutoa idadi fulani ya rekodi, kuanzia urekebishaji fulani tangu mwanzo wa sampuli).

Unaweza kuboresha ufanisi wa uhamisho wa data kwa kuboresha kidogo mbinu ya awali. Ili kufanya hivyo, tutatumia aina kamili (nambari kamili) kama maadili ya sehemu ya safu wima kwa mabadiliko ya ufuatiliaji. Hebu tutaje safu row_ver. Thamani ya sehemu ya safu wima hii bado lazima iwekwe/isasishwe kila wakati rekodi inapoundwa/kurekebishwa. Lakini katika kesi hii, uwanja hautapewa wakati wa sasa wa tarehe, lakini thamani ya counter fulani, imeongezeka kwa moja. Matokeo yake, safu row_ver itakuwa na maadili ya kipekee na inaweza kutumika sio tu kuonyesha data ya "delta" (data iliyoongezwa / iliyobadilishwa tangu mwisho wa kipindi cha awali cha kubadilishana), lakini pia kwa urahisi na kwa ufanisi kuigawanya katika kurasa.

Mbinu ya mwisho iliyopendekezwa ya kupunguza kiasi cha data iliyohamishwa ndani ya mfumo wa urudufishaji wa hali ya juu inaonekana kwangu kuwa bora zaidi na wa jumla. Hebu tuangalie kwa undani zaidi.

Kupitisha Data Kwa Kutumia Kihesabu cha Toleo la Safu

Utekelezaji wa seva/sehemu kuu

Katika Seva ya MS SQL, kuna aina maalum ya safu ya kutekeleza mbinu hii - rowversion. Kila hifadhidata ina kihesabu ambacho huongezeka kwa moja kila wakati rekodi inapoongezwa/kubadilishwa kwenye jedwali ambalo lina safu kama rowversion. Thamani ya kaunta hii inatolewa kiotomatiki kwa sehemu ya safu wima hii katika rekodi iliyoongezwa/iliyobadilishwa. Tarantool DBMS haina utaratibu sawa wa kujengwa. Hata hivyo, katika Tarantool si vigumu kutekeleza kwa manually. Hebu tuangalie jinsi hii inafanywa.

Kwanza, istilahi kidogo: meza katika Tarantool huitwa nafasi, na rekodi huitwa tuples. Katika Tarantool unaweza kuunda mlolongo. Mfuatano sio chochote zaidi ya jenereta zilizotajwa za maadili kamili yaliyoagizwa. Wale. hiki ndicho hasa tunachohitaji kwa madhumuni yetu. Hapo chini tutaunda mlolongo kama huo.

Kabla ya kufanya operesheni yoyote ya hifadhidata katika Tarantool, unahitaji kuendesha amri ifuatayo:

box.cfg{}

Kama matokeo, Tarantool itaanza kuandika vijisehemu vya hifadhidata na kumbukumbu za shughuli kwenye saraka ya sasa.

Hebu tutengeneze mlolongo row_version:

box.schema.sequence.create('row_version',
    { if_not_exists = true })

Chaguo if_not_exists inaruhusu hati ya uundaji kutekelezwa mara nyingi: ikiwa kitu kipo, Tarantool haitajaribu kuunda tena. Chaguo hili litatumika katika amri zote zinazofuata za DDL.

Wacha tutengeneze nafasi kama mfano.

box.schema.space.create('goods', {
    format = {
        {
            name = 'id',
            type = 'unsigned'

        },
        {
            name = 'name',
            type = 'string'

        },
        {
            name = 'code',
            type = 'unsigned'

        },
        {
            name = 'row_ver',
            type = 'unsigned'

        }
    },
    if_not_exists = true
})

Hapa tunaweka jina la nafasi (goods), majina ya uwanja na aina zao.

Sehemu za kuongeza kiotomatiki katika Tarantool pia huundwa kwa kutumia mfuatano. Hebu tuunde ufunguo msingi wa kuongeza kiotomatiki kulingana na sehemu id:

box.schema.sequence.create('goods_id',
    { if_not_exists = true })
box.space.goods:create_index('primary', {
    parts = { 'id' },
    sequence = 'goods_id',
    unique = true,
    type = 'HASH',
    if_not_exists = true
})

Tarantool inasaidia aina kadhaa za faharisi. Faharasa zinazotumika sana ni aina za TREE na HASH, ambazo zinatokana na miundo inayolingana na jina. TREE ndio aina ya faharasa inayotumika sana. Inakuruhusu kupata data kwa njia iliyopangwa. Lakini kwa uteuzi wa usawa, HASH inafaa zaidi. Ipasavyo, inashauriwa kutumia HASH kwa ufunguo wa msingi (ambayo ndiyo tulifanya).

Ili kutumia safu row_ver ili kuhamisha data iliyobadilishwa, unahitaji kufunga maadili ya mlolongo kwenye sehemu za safu wima hii row_ver. Lakini tofauti na ufunguo wa msingi, thamani ya uwanja wa safu row_ver inapaswa kuongezeka kwa moja sio tu wakati wa kuongeza rekodi mpya, lakini pia wakati wa kubadilisha zilizopo. Unaweza kutumia vichochezi kwa hili. Tarantool ina aina mbili za vichochezi vya nafasi: before_replace ΠΈ on_replace. Vichochezi hutupwa wakati wowote data katika nafasi inabadilika (kwa kila tuple iliyoathiriwa na mabadiliko, kitendaji cha kichochezi kinazinduliwa). Tofauti on_replace, before_replace-vichochezi hukuruhusu kurekebisha data ya nakala ambayo kichocheo kinatekelezwa. Ipasavyo, aina ya mwisho ya vichochezi inafaa sisi.

box.space.goods:before_replace(function(old, new)
    return box.tuple.new({new[1], new[2], new[3],
        box.sequence.row_version:next()})
end)

Kichochezi kifuatacho kinachukua nafasi ya thamani ya uga row_ver tuple iliyohifadhiwa kwa thamani inayofuata ya mlolongo row_version.

Ili kuweza kutoa data kutoka angani goods kwa safu row_ver, wacha tuunde faharisi:

box.space.goods:create_index('row_ver', {
    parts = { 'row_ver' },
    unique = true,
    type = 'TREE',
    if_not_exists = true
})

Aina ya index - mti (TREE), kwa sababu tutahitaji kutoa data kwa mpangilio wa kupanda wa maadili kwenye safu row_ver.

Wacha tuongeze data kwenye nafasi:

box.space.goods:insert{nil, 'pen', 123}
box.space.goods:insert{nil, 'pencil', 321}
box.space.goods:insert{nil, 'brush', 100}
box.space.goods:insert{nil, 'watercolour', 456}
box.space.goods:insert{nil, 'album', 101}
box.space.goods:insert{nil, 'notebook', 800}
box.space.goods:insert{nil, 'rubber', 531}
box.space.goods:insert{nil, 'ruler', 135}

Kwa sababu Sehemu ya kwanza ni kaunta ya kuongeza kiotomatiki; badala yake tunapita hakuna. Tarantool itabadilisha thamani inayofuata kiotomatiki. Vile vile, kama thamani ya sehemu za safu wima row_ver unaweza kupita nil - au usielezee thamani kabisa, kwa sababu safu hii inachukua nafasi ya mwisho katika nafasi.

Wacha tuangalie matokeo ya kuingiza:

tarantool> box.space.goods:select()
---
- - [1, 'pen', 123, 1]
  - [2, 'pencil', 321, 2]
  - [3, 'brush', 100, 3]
  - [4, 'watercolour', 456, 4]
  - [5, 'album', 101, 5]
  - [6, 'notebook', 800, 6]
  - [7, 'rubber', 531, 7]
  - [8, 'ruler', 135, 8]
...

Kama unaweza kuona, sehemu za kwanza na za mwisho hujazwa kiotomatiki. Sasa itakuwa rahisi kuandika kitendakazi cha upakiaji wa ukurasa kwa ukurasa wa mabadiliko ya nafasi goods:

local page_size = 5
local function get_goods(row_ver)
    local index = box.space.goods.index.row_ver
    local goods = {}
    local counter = 0
    for _, tuple in index:pairs(row_ver, {
        iterator = 'GT' }) do
        local obj = tuple:tomap({ names_only = true })
        table.insert(goods, obj)
        counter = counter + 1
        if counter >= page_size then
            break
        end
    end
    return goods
end

Chaguo za kukokotoa huchukua kama kigezo thamani row_ver, kuanzia ambayo ni muhimu kupakua mabadiliko, na kurejesha sehemu ya data iliyobadilishwa.

Sampuli za data katika Tarantool hufanywa kupitia faharisi. Kazi get_goods hutumia kirudia kwa faharasa row_ver kupokea data iliyobadilishwa. Aina ya kiboreshaji ni GT (Kubwa Kuliko, kubwa kuliko). Hii inamaanisha kuwa kiboreshaji kitapita kwa mtiririko maadili ya faharisi kuanzia kitufe kilichopitishwa (thamani ya uwanja. row_ver).

Kirudia hurudisha nakala. Ili baadaye kuweza kuhamisha data kupitia HTTP, ni muhimu kubadilisha nakala hadi muundo unaofaa kwa ufuataji ufuatao. Mfano hutumia kazi ya kawaida kwa hili tomap. Badala ya kutumia tomap unaweza kuandika kazi yako mwenyewe. Kwa mfano, tunaweza kutaka kubadilisha jina la uga name, usipite uwanja code na kuongeza shamba comment:

local function unflatten_goods(tuple)
    local obj = {}
    obj.id = tuple.id
    obj.goods_name = tuple.name
    obj.comment = 'some comment'
    obj.row_ver = tuple.row_ver
    return obj
end

Ukubwa wa ukurasa wa data ya pato (idadi ya rekodi katika sehemu moja) imedhamiriwa na kutofautiana page_size. Katika mfano thamani page_size ni 5. Katika programu halisi, ukubwa wa ukurasa kwa kawaida ni muhimu zaidi. Inategemea saizi ya wastani ya tuple ya nafasi. Ukubwa bora wa ukurasa unaweza kubainishwa kwa nguvu kwa kupima muda wa kuhamisha data. Kadiri ukubwa wa ukurasa unavyokuwa mkubwa, ndivyo idadi ya safari za kurudi na kurudi inavyopungua kati ya pande zinazotuma na kupokea. Kwa njia hii unaweza kupunguza muda wa jumla wa kupakua mabadiliko. Hata hivyo, ikiwa ukubwa wa ukurasa ni mkubwa sana, tutatumia muda mrefu sana kwenye seva kutayarisha sampuli. Kwa hivyo, kunaweza kuwa na ucheleweshaji katika kuchakata maombi mengine yanayokuja kwa seva. Kigezo page_size inaweza kupakiwa kutoka kwa faili ya usanidi. Kwa kila nafasi iliyopitishwa, unaweza kuweka thamani yake mwenyewe. Hata hivyo, kwa nafasi nyingi thamani ya chaguo-msingi (kwa mfano, 100) inaweza kufaa.

Hebu tutekeleze kazi get_goods:

tarantool> get_goods(0)

---
- - row_ver: 1
    code: 123
    name: pen
    id: 1
  - row_ver: 2
    code: 321
    name: pencil
    id: 2
  - row_ver: 3
    code: 100
    name: brush
    id: 3
  - row_ver: 4
    code: 456
    name: watercolour
    id: 4
  - row_ver: 5
    code: 101
    name: album
    id: 5
...

Hebu tuchukue thamani ya shamba row_ver kutoka kwa mstari wa mwisho na piga kazi tena:

tarantool> get_goods(5)

---
- - row_ver: 6
    code: 800
    name: notebook
    id: 6
  - row_ver: 7
    code: 531
    name: rubber
    id: 7
  - row_ver: 8
    code: 135
    name: ruler
    id: 8
...

Tena:

tarantool> get_goods(8)
---
- []
...

Kama unavyoona, inapotumiwa kwa njia hii, chaguo la kukokotoa hurejesha rekodi zote za nafasi ukurasa kwa ukurasa goods. Ukurasa wa mwisho unafuatwa na chaguo tupu.

Wacha tufanye mabadiliko kwenye nafasi:

box.space.goods:update(4, {{'=', 6, 'copybook'}})
box.space.goods:insert{nil, 'clip', 234}
box.space.goods:insert{nil, 'folder', 432}

Tumebadilisha thamani ya uwanja name kwa kiingilio kimoja na kuongeza maingizo mawili mapya.

Wacha turudie simu ya mwisho ya kazi:

tarantool> get_goods(8)
---



- - row_ver: 9
    code: 800
    name: copybook
    id: 6
  - row_ver: 10
    code: 234
    name: clip
    id: 9
  - row_ver: 11
    code: 432
    name: folder
    id: 10
...

Chaguo la kukokotoa lilirejesha rekodi zilizobadilishwa na zilizoongezwa. Hivyo kazi get_goods hukuruhusu kupokea data ambayo imebadilika tangu simu yake ya mwisho, ambayo ni msingi wa njia ya kurudia inayozingatiwa.

Tutaacha utoaji wa matokeo kupitia HTTP katika mfumo wa JSON nje ya upeo wa makala haya. Unaweza kusoma kuhusu hili hapa: https://habr.com/ru/company/mailru/blog/272141/

Utekelezaji wa sehemu ya mteja/mtumwa

Wacha tuangalie utekelezaji wa upande unaopokea unaonekanaje. Hebu tuunde nafasi kwenye upande wa kupokea ili kuhifadhi data iliyopakuliwa:

box.schema.space.create('goods', {
    format = {
        {
            name = 'id',
            type = 'unsigned'

        },
        {
            name = 'name',
            type = 'string'

        },
        {
            name = 'code',
            type = 'unsigned'

        }
    },
    if_not_exists = true
})

box.space.goods:create_index('primary', {
    parts = { 'id' },
    sequence = 'goods_id',
    unique = true,
    type = 'HASH',
    if_not_exists = true
})

Muundo wa nafasi unafanana na muundo wa nafasi katika chanzo. Lakini kwa kuwa hatutapitisha data iliyopokelewa mahali pengine popote, safu row_ver haipo kwenye nafasi ya mpokeaji. Katika shamba id vitambulisho vya chanzo vitarekodiwa. Kwa hiyo, kwa upande wa mpokeaji hakuna haja ya kuifanya auto-incrementing.

Kwa kuongeza, tunahitaji nafasi ili kuhifadhi maadili row_ver:

box.schema.space.create('row_ver', {
    format = {
        {
            name = 'space_name',
            type = 'string'

        },
        {
            name = 'value',
            type = 'string'

        }
    },
    if_not_exists = true
})

box.space.row_ver:create_index('primary', {
    parts = { 'space_name' },
    unique = true,
    type = 'HASH',
    if_not_exists = true
})

Kwa kila nafasi iliyopakiwa (uwanja space_name) tutahifadhi thamani ya mwisho iliyopakiwa hapa row_ver (uwanja value) Safu hufanya kama ufunguo msingi space_name.

Hebu tuunde kitendakazi cha kupakia data ya nafasi goods kupitia HTTP. Ili kufanya hivyo, tunahitaji maktaba inayotumia mteja wa HTTP. Mstari ufuatao hupakia maktaba na kusisitiza mteja wa HTTP:

local http_client = require('http.client').new()

Tunahitaji pia maktaba ya json deserialization:

local json = require('json')

Hii inatosha kuunda kitendakazi cha upakiaji data:

local function load_data(url, row_ver)
    local url = ('%s?rowVer=%s'):format(url,
        tostring(row_ver))
    local body = nil
    local data = http_client:request('GET', url, body, {
        keepalive_idle =  1,
        keepalive_interval = 1
    })
    return json.decode(data.body)
end

Chaguo za kukokotoa hutekeleza ombi la HTTP kwa anwani ya url na kuituma row_ver kama kigezo na inarudisha matokeo yaliyokataliwa ya ombi.

Kazi ya kuhifadhi data iliyopokelewa inaonekana kama hii:

local function save_goods(goods)
    local n = #goods
    box.atomic(function()
        for i = 1, n do
            local obj = goods[i]
            box.space.goods:put(
                obj.id, obj.name, obj.code)
        end
    end)
end

Mzunguko wa kuhifadhi data kwenye nafasi goods kuwekwa katika shughuli (kazi inatumika kwa hili box.atomic) kupunguza idadi ya shughuli za diski.

Hatimaye, kazi ya ulandanishi wa nafasi ya ndani goods na chanzo unaweza kuitekeleza kama hii:

local function sync_goods()
    local tuple = box.space.row_ver:get('goods')
    local row_ver = tuple and tuple.value or 0

    β€”β€” set your url here:
    local url = 'http://127.0.0.1:81/test/goods/list'

    while true do
        local goods = load_goods(url, row_ver)

        local count = #goods
        if count == 0 then
            return
        end

        save_goods(goods)

        row_ver = goods[count].rowVer
        box.space.row_ver:put({'goods', row_ver})
    end
end

Kwanza tunasoma thamani iliyohifadhiwa hapo awali row_ver kwa nafasi goods. Ikiwa haipo (kipindi cha kwanza cha kubadilishana), basi tunaichukua kama row_ver sufuri. Ifuatayo katika mzunguko tunapakua ukurasa kwa ukurasa wa data iliyobadilishwa kutoka kwa chanzo kwenye url maalum. Katika kila marudio, tunahifadhi data iliyopokelewa kwenye nafasi inayofaa ya ndani na kusasisha thamani row_ver (katika nafasi row_ver na katika kutofautiana row_ver) - chukua thamani row_ver kutoka kwa mstari wa mwisho wa data iliyopakiwa.

Ili kulinda dhidi ya kitanzi cha bahati mbaya (ikiwa kuna hitilafu katika programu), kitanzi while inaweza kubadilishwa na for:

for _ = 1, max_req do ...

Kama matokeo ya kutekeleza kazi sync_goods nafasi goods mpokeaji atakuwa na matoleo ya hivi punde ya rekodi zote za anga goods katika chanzo.

Kwa wazi, ufutaji wa data hauwezi kutangazwa kwa njia hii. Ikiwa hitaji kama hilo lipo, unaweza kutumia alama ya kufuta. Ongeza kwenye nafasi goods uwanja wa boolean is_deleted na badala ya kufuta rekodi kimwili, tunatumia ufutaji wa kimantiki - tunaweka thamani ya shamba is_deleted kwenye maana true. Wakati mwingine badala ya uwanja wa boolean is_deleted ni rahisi zaidi kutumia shamba deleted, ambayo huhifadhi tarehe ya kufutwa kwa rekodi. Baada ya kufanya ufutaji wa kimantiki, rekodi iliyowekwa alama ya kufutwa itahamishwa kutoka chanzo hadi lengwa (kulingana na mantiki iliyojadiliwa hapo juu).

Mlolongo row_ver inaweza kutumika kusambaza data kutoka kwa nafasi nyingine: hakuna haja ya kuunda mlolongo tofauti kwa kila nafasi iliyopitishwa.

Tuliangalia njia bora ya urudufishaji wa data wa kiwango cha juu katika programu kwa kutumia Tarantool DBMS.

Matokeo

  1. Tarantool DBMS ni bidhaa ya kuvutia, yenye kuahidi kwa kuunda programu zenye mzigo mkubwa.
  2. Urudufu wa data wa kiwango cha juu una faida kadhaa juu ya urudufishaji wa kiwango cha chini.
  3. Mbinu ya urudufishaji wa hali ya juu iliyojadiliwa katika makala inakuwezesha kupunguza kiasi cha data iliyohamishwa kwa kuhamisha rekodi hizo pekee ambazo zimebadilika tangu kipindi cha mwisho cha kubadilishana.

Chanzo: mapenzi.com

Kuongeza maoni