Sveiki, veidoju lietojumprogrammas DBVS
SajÅ«ti spÄku! (...aka izbaudiet priekÅ”nesumu)
Viss iepriekÅ” minÄtais padara Tarantool par pievilcÄ«gu platformu lielas slodzes lietojumprogrammu izveidei, kas darbojas ar datu bÄzÄm. Å ÄdÄs lietojumprogrammÄs bieži vien ir nepiecieÅ”ama datu replikÄcija.
KÄ minÄts iepriekÅ”, Tarantool ir iebÅ«vÄta datu replikÄcija. TÄs darbÄ«bas princips ir secÄ«gi izpildÄ«t visas galvenajÄ Å¾urnÄlÄ (WAL) ietvertÄs transakcijas replikÄs. Parasti Å”Äda replikÄcija (mÄs to turpmÄk sauksim zems lÄ«menis) tiek izmantots, lai nodroÅ”inÄtu lietojumprogrammas kļūdu toleranci un/vai lai sadalÄ«tu lasÄ«Å”anas slodzi starp klastera mezgliem.
RÄ«si. 1. ReplikÄcija klasterÄ«
AlternatÄ«va scenÄrija piemÄrs varÄtu bÅ«t vienÄ datubÄzÄ izveidoto datu pÄrsÅ«tÄ«Å”ana uz citu datu bÄzi apstrÄdei/uzraudzÄ«bai. PÄdÄjÄ gadÄ«jumÄ ÄrtÄks risinÄjums var bÅ«t izmantoÅ”ana augsts lÄ«menis replikÄcija ā datu replikÄcija lietojumprogrammas biznesa loÄ£ikas lÄ«menÄ«. Tie. MÄs neizmantojam gatavu risinÄjumu, kas iebÅ«vÄts DBVS, bet paÅ”i Ä«stenojam replikÄciju lietojumprogrammÄ, kuru izstrÄdÄjam. Å ai pieejai ir gan priekÅ”rocÄ«bas, gan trÅ«kumi. UzskaitÄ«sim priekÅ”rocÄ«bas.
1. Satiksmes ietaupījumi:
- JÅ«s nevarat pÄrsÅ«tÄ«t visus datus, bet tikai daļu no tiem (piemÄram, varat pÄrsÅ«tÄ«t tikai dažas tabulas, dažas to kolonnas vai ierakstus, kas atbilst noteiktam kritÄrijam);
- AtŔķirÄ«bÄ no zema lÄ«meÅa replikÄcijas, kas tiek veikta nepÄrtraukti asinhronÄ (ieviesta paÅ”reizÄjÄ Tarantool versijÄ - 1.10) vai sinhronÄ (jÄievieÅ” nÄkamajÄs Tarantool versijÄs) režīmÄ, augsta lÄ«meÅa replikÄciju var veikt sesijÄs (t.i., lietojumprogramma vispirms sinhronizÄ datus - apmaiÅas sesijas datus, pÄc tam notiek replikÄcijas pauze, pÄc kuras notiek nÄkamÄ apmaiÅas sesija utt.);
- ja ieraksts ir mainÄ«ts vairÄkas reizes, varat pÄrsÅ«tÄ«t tikai tÄ jaunÄko versiju (atŔķirÄ«bÄ no zema lÄ«meÅa replikÄcijas, kurÄ visas izmaiÅas, kas veiktas galvenajÄ versijÄ, tiks atskaÅotas secÄ«gi replikÄs).
2. Nav nekÄdu grÅ«tÄ«bu ar HTTP apmaiÅas ievieÅ”anu, kas ļauj sinhronizÄt attÄlÄs datu bÄzes.
RÄ«si. 2. ReplikÄcija, izmantojot HTTP
3. Datu bÄzes struktÅ«rÄm, starp kurÄm tiek pÄrsÅ«tÄ«ti dati, nav jÄbÅ«t vienÄdÄm (turklÄt vispÄrÄ«gÄ gadÄ«jumÄ pat iespÄjams izmantot dažÄdas DBVS, programmÄÅ”anas valodas, platformas utt.).
RÄ«si. 3. ReplikÄcija neviendabÄ«gÄs sistÄmÄs
MÄ«nuss ir tÄds, ka vidÄji programmÄÅ”ana ir grÅ«tÄka/dÄrgÄka nekÄ konfigurÄÅ”ana, un tÄ vietÄ, lai pielÄgotu iebÅ«vÄto funkcionalitÄti, nÄksies ieviest savu.
Ja jÅ«su situÄcijÄ iepriekÅ” minÄtÄs priekÅ”rocÄ«bas ir izŔķiroÅ”as (vai ir nepiecieÅ”ams nosacÄ«jums), tad ir lietderÄ«gi izmantot augsta lÄ«meÅa replikÄciju. ApskatÄ«sim vairÄkus veidus, kÄ ieviest augsta lÄ«meÅa datu replikÄciju Tarantool DBVS.
Satiksmes samazinÄÅ”ana
TÄtad viena no augsta lÄ«meÅa replikÄcijas priekÅ”rocÄ«bÄm ir satiksmes ietaupÄ«jumi. Lai Ŕī priekÅ”rocÄ«ba tiktu pilnÄ«bÄ realizÄta, katras apmaiÅas sesijas laikÄ ir jÄsamazina pÄrsÅ«tÄ«to datu apjoms. Protams, nevajadzÄtu aizmirst, ka sesijas beigÄs datu uztvÄrÄjam ir jÄbÅ«t sinhronizÄtam ar avotu (vismaz tai datu daļai, kas ir iesaistÄ«ta replikÄcijÄ).
KÄ samazinÄt pÄrsÅ«tÄ«to datu apjomu augsta lÄ«meÅa replikÄcijas laikÄ? VienkÄrÅ”s risinÄjums varÄtu bÅ«t datu atlase pÄc datuma un laika. Lai to izdarÄ«tu, varat izmantot tabulÄ jau esoÅ”o datuma un laika lauku (ja tÄds ir). PiemÄram, āpasÅ«tÄ«jumaā dokumentÄ var bÅ«t lauks ānepiecieÅ”amais pasÅ«tÄ«juma izpildes laiksā - delivery_time
. ProblÄma ar Å”o risinÄjumu ir tÄda, ka vÄrtÄ«bÄm Å”ajÄ laukÄ nav jÄbÅ«t tÄdÄ secÄ«bÄ, kas atbilst pasÅ«tÄ«jumu izveidei. TÄpÄc mÄs nevaram atcerÄties maksimÄlo lauka vÄrtÄ«bu delivery_time
, kas pÄrsÅ«tÄ«ts iepriekÅ”ÄjÄs apmaiÅas sesijas laikÄ, un nÄkamÄs apmaiÅas sesijas laikÄ atlasiet visus ierakstus ar lielÄku lauka vÄrtÄ«bu delivery_time
. Ieraksti ar zemÄku lauka vÄrtÄ«bu, iespÄjams, ir pievienoti starp apmaiÅas sesijÄm delivery_time
. TÄpat pasÅ«tÄ«jumÄ varÄja bÅ«t izmaiÅas, kas tomÄr laukumu neietekmÄja delivery_time
. Abos gadÄ«jumos izmaiÅas netiks pÄrsÅ«tÄ«tas no avota uz galamÄrÄ·i. Lai atrisinÄtu Ŕīs problÄmas, mums bÅ«s jÄpÄrsÅ«ta dati "pÄrklÄjoties". Tie. katrÄ apmaiÅas sesijÄ mÄs pÄrsÅ«tÄ«sim visus datus ar lauka vÄrtÄ«bu delivery_time
, pÄrsniedzot kÄdu punktu pagÄtnÄ (piemÄram, N stundas no paÅ”reizÄjÄ brīža). TomÄr ir acÄ«mredzams, ka lielÄm sistÄmÄm Ŕī pieeja ir ļoti lieka un var samazinÄt trafika ietaupÄ«jumus, uz kuriem mÄs tiecamies. TurklÄt pÄrsÅ«tÄmajÄ tabulÄ var nebÅ«t lauka, kas saistÄ«ts ar datumu un laiku.
VÄl viens risinÄjums, kas ir sarežģītÄks ievieÅ”anas ziÅÄ, ir apstiprinÄt datu saÅemÅ”anu. Å ajÄ gadÄ«jumÄ katras apmaiÅas sesijas laikÄ tiek pÄrsÅ«tÄ«ti visi dati, kuru saÅemÅ”anu saÅÄmÄjs nav apstiprinÄjis. Lai to Ä«stenotu, avota tabulai bÅ«s jÄpievieno BÅ«la kolonna (piemÄram, is_transferred
). Ja saÅÄmÄjs apstiprina ieraksta saÅemÅ”anu, attiecÄ«gajÄ laukÄ tiek iegÅ«ta vÄrtÄ«ba true
, pÄc kura ieraksts vairs nav iesaistÄ«ts apmaiÅÄ. Å ai ievieÅ”anas iespÄjai ir Å”Ädi trÅ«kumi. PirmkÄrt, katram pÄrsÅ«tÄ«tajam ierakstam ir jÄÄ£enerÄ un jÄnosÅ«ta apstiprinÄjums. Aptuveni runÄjot, tas varÄtu bÅ«t salÄ«dzinÄms ar pÄrsÅ«tÄ«to datu apjoma dubultoÅ”anu un divkÄrÅ”ot reisu skaitu turp un atpakaļ. OtrkÄrt, nav iespÄjas nosÅ«tÄ«t vienu un to paÅ”u ierakstu vairÄkiem saÅÄmÄjiem (pirmais saÅÄmÄjs apstiprinÄs saÅemÅ”anu sev un visiem pÄrÄjiem).
Metode, kurai nav iepriekÅ” minÄto trÅ«kumu, ir pievienot kolonnu nosÅ«tÄ«tajai tabulai, lai izsekotu izmaiÅÄm tÄs rindÄs. Å Äda kolonna var bÅ«t datuma-laika tipa, un lietojumprogrammai tÄ ir jÄiestata/jÄatjaunina lÄ«dz paÅ”reizÄjam laikam ikreiz, kad ieraksti tiek pievienoti/mainÄ«ti (ar pievienoÅ”anu/maiÅu atomiski). KÄ piemÄru nosauksim kolonnu update_time
. SaglabÄjot Ŕīs kolonnas maksimÄlo lauka vÄrtÄ«bu pÄrsÅ«tÄ«tajiem ierakstiem, mÄs varam sÄkt nÄkamo apmaiÅas sesiju ar Å”o vÄrtÄ«bu (atlasiet ierakstus ar lauka vÄrtÄ«bu update_time
, pÄrsniedzot iepriekÅ” saglabÄto vÄrtÄ«bu). ProblÄma ar pÄdÄjo pieeju ir tÄda, ka datu izmaiÅas var notikt partijÄs. Kolonnas lauka vÄrtÄ«bu rezultÄtÄ update_time
var nebÅ«t unikÄla. TÄdÄjÄdi Å”o kolonnu nevar izmantot dalÄ«tu (lapu pa lappusei) datu izvadei. Lai parÄdÄ«tu datus pa lappusei, jums bÅ«s jÄizgudro papildu mehÄnismi, kuriem, visticamÄk, bÅ«s ļoti zema efektivitÄte (piemÄram, izgÅ«t no datu bÄzes visus ierakstus ar vÄrtÄ«bu update_time
augstÄks par doto un rada noteiktu ierakstu skaitu, sÄkot ar noteiktu nobÄ«di no izlases sÄkuma).
JÅ«s varat uzlabot datu pÄrsÅ«tÄ«Å”anas efektivitÄti, nedaudz uzlabojot iepriekÅ”Äjo pieeju. Lai to izdarÄ«tu, mÄs izmantosim vesela skaitļa tipu (garu veselu skaitli) kÄ kolonnas lauka vÄrtÄ«bas izmaiÅu izsekoÅ”anai. Nosauksim kolonnu row_ver
. Å Ä«s kolonnas lauka vÄrtÄ«ba joprojÄm ir jÄiestata/atjaunina katru reizi, kad tiek izveidots/mainÄ«ts ieraksts. Bet Å”ajÄ gadÄ«jumÄ laukam tiks pieŔķirts nevis paÅ”reizÄjais datums-laiks, bet gan kÄda skaitÄ«tÄja vÄrtÄ«ba, kas palielinÄta par vienu. RezultÄtÄ kolonna row_ver
satur unikÄlas vÄrtÄ«bas, un tos var izmantot ne tikai, lai parÄdÄ«tu ādeltaā datus (dati, kas pievienoti/mainÄ«ti kopÅ” iepriekÅ”ÄjÄs apmaiÅas sesijas beigÄm), bet arÄ« vienkÄrÅ”i un efektÄ«vi sadalÄ«t tos lapÄs.
PÄdÄjÄ piedÄvÄtÄ metode augsta lÄ«meÅa replikÄcijas ietvaros pÄrsÅ«tÄ«to datu apjoma samazinÄÅ”anai man Ŕķiet visoptimÄlÄkÄ un universÄlÄkÄ. ApskatÄ«sim to sÄ«kÄk.
Datu nodoÅ”ana, izmantojot rindu versiju skaitÄ«tÄju
Servera/master daļas ievieŔana
MS SQL Server Ŕīs pieejas ievieŔanai ir īpaŔs kolonnu veids - rowversion
. Katrai datu bÄzei ir skaitÄ«tÄjs, kas palielinÄs par vienu katru reizi, kad ieraksts tiek pievienots/mainÄ«ts tabulÄ, kurÄ ir lÄ«dzÄ«ga kolonna rowversion
. Å Ä« skaitÄ«tÄja vÄrtÄ«ba tiek automÄtiski pieŔķirta Ŕīs kolonnas laukam pievienotajÄ/mainÄ«tajÄ ierakstÄ. Tarantool DBVS nav lÄ«dzÄ«ga iebÅ«vÄta mehÄnisma. TomÄr Tarantool to nav grÅ«ti ieviest manuÄli. ApskatÄ«sim, kÄ tas tiek darÄ«ts.
PirmkÄrt, nedaudz terminoloÄ£ijas: Tarantool tabulas sauc par atstarpÄm, bet ierakstus sauc par korežiem. Tarantool varat izveidot secÄ«bas. SecÄ«bas ir nekas vairÄk kÄ nosaukti sakÄrtotu veselu skaitļu vÄrtÄ«bu Ä£eneratori. Tie. tas ir tieÅ”i tas, kas mums vajadzÄ«gs mÅ«su mÄrÄ·iem. ZemÄk mÄs izveidosim Å”Ädu secÄ«bu.
Pirms jebkÄdas datu bÄzes darbÄ«bas veikÅ”anas Tarantool, jums ir jÄpalaiž Å”Äda komanda:
box.cfg{}
TÄ rezultÄtÄ Tarantool sÄks rakstÄ«t datu bÄzes momentuzÅÄmumus un darÄ«jumu žurnÄlus paÅ”reizÄjÄ direktorijÄ.
Izveidosim secību row_version
:
box.schema.sequence.create('row_version',
{ if_not_exists = true })
Opcija if_not_exists
ļauj vairÄkas reizes izpildÄ«t izveides skriptu: ja objekts pastÄv, Tarantool nemÄÄ£inÄs to izveidot vÄlreiz. Å Ä« opcija tiks izmantota visÄs turpmÄkajÄs DDL komandÄs.
Izveidosim telpu kÄ piemÄru.
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
})
Å eit mÄs iestatÄm telpas nosaukumu (goods
), lauku nosaukumi un to veidi.
AutomÄtiski pieaugoÅ”ie lauki programmÄ Tarantool tiek izveidoti arÄ«, izmantojot secÄ«bas. Izveidosim automÄtiski pieaugoÅ”u primÄro atslÄgu pa laukiem 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 atbalsta vairÄku veidu indeksus. VisbiežÄk izmantotie indeksi ir TREE un HASH tipi, kuru pamatÄ ir nosaukumam atbilstoÅ”as āāstruktÅ«ras. TREE ir daudzpusÄ«gÄkais indeksa veids. Tas ļauj izgÅ«t datus organizÄtÄ veidÄ. Bet vienlÄ«dzÄ«gai atlasei HASH ir piemÄrotÄks. AttiecÄ«gi primÄrajai atslÄgai ir ieteicams izmantot HASH (to mÄs arÄ« darÄ«jÄm).
Lai izmantotu kolonnu row_ver
lai pÄrsÅ«tÄ«tu mainÄ«tos datus, Ŕīs kolonnas laukiem ir jÄsaista secÄ«bas vÄrtÄ«bas row_ver
. Bet atŔķirÄ«bÄ no primÄrÄs atslÄgas, kolonnas lauka vÄrtÄ«ba row_ver
jÄpalielina par vienu ne tikai pievienojot jaunus ierakstus, bet arÄ« mainot esoÅ”os. Å im nolÅ«kam varat izmantot trigerus. Tarantool ir divu veidu kosmosa izraisÄ«tÄji: before_replace
Šø on_replace
. Trigeri tiek aktivizÄti ikreiz, kad mainÄs dati telpÄ (katrai izmaiÅu ietekmÄtajai kortei tiek palaista trigera funkcija). AtŔķirÄ«bÄ no on_replace
, before_replace
-trigeri ļauj modificÄt kortedža, kurai tiek izpildÄ«ts trigeris, datus. AttiecÄ«gi mums der pÄdÄjais trigeru veids.
box.space.goods:before_replace(function(old, new)
return box.tuple.new({new[1], new[2], new[3],
box.sequence.row_version:next()})
end)
Å is trigeris aizstÄj lauka vÄrtÄ«bu row_ver
saglabÄta virkne lÄ«dz nÄkamajai secÄ«bas vÄrtÄ«bai row_version
.
Lai varÄtu iegÅ«t datus no kosmosa goods
pÄc kolonnas row_ver
, izveidosim indeksu:
box.space.goods:create_index('row_ver', {
parts = { 'row_ver' },
unique = true,
type = 'TREE',
if_not_exists = true
})
Indeksa veids - koks (TREE
), jo mums bÅ«s jÄizÅem dati kolonnas vÄrtÄ«bu augoÅ”Ä secÄ«bÄ row_ver
.
Pievienosim telpai dažus datus:
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}
Jo Pirmais lauks ir automÄtiski augoÅ”s skaitÄ«tÄjs; tÄ vietÄ mÄs atstÄjam nulli. Tarantool automÄtiski aizstÄs nÄkamo vÄrtÄ«bu. LÄ«dzÄ«gi kÄ kolonnas lauku vÄrtÄ«ba row_ver
jÅ«s varat atstÄt nulli - vai nenorÄdÄ«t vÄrtÄ«bu vispÄr, jo Ŕī kolonna aizÅem pÄdÄjo vietu telpÄ.
PÄrbaudÄ«sim ievietoÅ”anas rezultÄtu:
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]
...
KÄ redzat, pirmais un pÄdÄjais lauks tiek aizpildÄ«ts automÄtiski. Tagad bÅ«s viegli uzrakstÄ«t funkciju vietas izmaiÅu augÅ”upielÄdei pa lappusei 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
Funkcija kÄ parametru izmanto vÄrtÄ«bu row_ver
, no kura ir nepiecieÅ”ams izlÄdÄt izmaiÅas, un atgriež daļu no mainÄ«tajiem datiem.
Datu paraugu ÅemÅ”ana programmÄ Tarantool tiek veikta, izmantojot indeksus. Funkcija get_goods
izmanto iteratoru pÄc indeksa row_ver
lai saÅemtu mainÄ«tos datus. Iteratora veids ir GT (lielÄks par, lielÄks par). Tas nozÄ«mÄ, ka iterators secÄ«gi ŔķÄrsos indeksa vÄrtÄ«bas, sÄkot no nodotÄs atslÄgas (lauka vÄrtÄ«ba row_ver
).
Iterators atgriež korteÅus. Lai pÄc tam varÄtu pÄrsÅ«tÄ«t datus, izmantojot HTTP, korteži ir jÄpÄrvÄrÅ” struktÅ«rÄ, kas ir Ärta turpmÄkai serializÄcijai. PiemÄrÄ Å”im nolÅ«kam tiek izmantota standarta funkcija tomap
. TÄ vietÄ, lai izmantotu tomap
jÅ«s varat uzrakstÄ«t savu funkciju. PiemÄram, mÄs varÄtu vÄlÄties pÄrdÄvÄt lauku name
, neiet garÄm laukam code
un pievienojiet lauku 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
Izvaddatu lapas izmÄru (ierakstu skaitu vienÄ daļÄ) nosaka mainÄ«gais page_size
. PiemÄrÄ vÄrtÄ«ba page_size
ir 5. ReÄlÄ programmÄ lapas izmÄram parasti ir lielÄka nozÄ«me. Tas ir atkarÄ«gs no atstarpes kortedža vidÄjÄ lieluma. OptimÄlo lapas izmÄru var noteikt empÄ«riski, mÄrot datu pÄrraides laiku. Jo lielÄks ir lapas izmÄrs, jo mazÄks ir turp un atpakaļ braucienu skaits starp sÅ«tÄ«tÄju un saÅÄmÄju. TÄdÄ veidÄ jÅ«s varat samazinÄt kopÄjo izmaiÅu lejupielÄdes laiku. TomÄr, ja lapas izmÄrs ir pÄrÄk liels, mÄs pÄrÄk ilgu laiku pavadÄ«sim serverÄ«, lai serializÄtu paraugu. TÄ rezultÄtÄ var rasties kavÄÅ”anÄs, apstrÄdÄjot citus serverÄ« saÅemtos pieprasÄ«jumus. Parametrs page_size
var ielÄdÄt no konfigurÄcijas faila. Katrai pÄrraidÄ«tajai telpai varat iestatÄ«t savu vÄrtÄ«bu. TomÄr lielÄkajai daļai vietu noklusÄjuma vÄrtÄ«ba (piemÄram, 100) var bÅ«t piemÄrota.
Izpildīsim funkciju 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
...
Å
emsim lauka vÄrtÄ«bu row_ver
no pÄdÄjÄs rindas un vÄlreiz izsauciet funkciju:
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
...
VÄlreiz:
tarantool> get_goods(8)
---
- []
...
KÄ redzat, izmantojot Å”ÄdÄ veidÄ, funkcija atgriež visus telpas ierakstus pÄc lapas goods
. PÄc pÄdÄjÄs lapas seko tukÅ”a atlase.
Veiksim izmaiÅas telpÄ:
box.space.goods:update(4, {{'=', 6, 'copybook'}})
box.space.goods:insert{nil, 'clip', 234}
box.space.goods:insert{nil, 'folder', 432}
MÄs esam mainÄ«juÅ”i lauka vÄrtÄ«bu name
vienam ierakstam un pievienoja divus jaunus ierakstus.
AtkÄrtosim pÄdÄjo funkcijas izsaukumu:
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
...
Funkcija atgrieza mainÄ«tos un pievienotos ierakstus. TÄtad funkcija get_goods
ļauj saÅemt datus, kas ir mainÄ«juÅ”ies kopÅ” pÄdÄjÄ izsaukuma, kas ir aplÅ«kojamÄs replikÄcijas metodes pamatÄ.
RezultÄtu izsniegÅ”ana, izmantojot HTTP JSON formÄtÄ, netiks iekļauta Ŕī raksta darbÄ«bas jomÄ. Par to varat lasÄ«t Å”eit:
Klienta/pakalpojuma daļas realizÄcija
ApskatÄ«sim, kÄ izskatÄs saÅÄmÄjas puses ievieÅ”ana. SaÅÄmÄja pusÄ izveidosim vietu lejupielÄdÄto datu glabÄÅ”anai:
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
})
Telpas struktÅ«ra atgÄdina telpas struktÅ«ru avotÄ. Bet, tÄ kÄ saÅemtos datus nekur citur nenodosim, kolonna row_ver
neatrodas adresÄta zonÄ. LaukÄ id
avota identifikatori tiks ierakstÄ«ti. TÄpÄc uztvÄrÄja pusÄ nav nepiecieÅ”ams to automÄtiski palielinÄt.
TurklÄt mums ir vajadzÄ«ga vieta vÄrtÄ«bu saglabÄÅ”anai 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
})
Katrai noslogotajai vietai (lauks space_name
) mÄs Å”eit saglabÄsim pÄdÄjo ielÄdÄto vÄrtÄ«bu row_ver
(lauks value
). Kolonna darbojas kÄ primÄrÄ atslÄga space_name
.
Izveidosim funkciju vietas datu ielÄdei goods
izmantojot HTTP. Lai to izdarÄ«tu, mums ir nepiecieÅ”ama bibliotÄka, kas ievieÅ” HTTP klientu. Å Ä« rindiÅa ielÄdÄ bibliotÄku un izveido HTTP klientu:
local http_client = require('http.client').new()
Mums ir nepiecieÅ”ama arÄ« bibliotÄka JSON deserializÄcijai:
local json = require('json')
Tas ir pietiekami, lai izveidotu datu ielÄdes funkciju:
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
Funkcija izpilda HTTP pieprasījumu uz url adresi un nosūta to row_ver
kÄ parametru un atgriež pieprasÄ«juma deserializÄto rezultÄtu.
SaÅemto datu saglabÄÅ”anas funkcija izskatÄs Å”Ädi:
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
Cikls datu saglabÄÅ”anai kosmosÄ goods
ievietots darÄ«jumÄ (Å”im nolÅ«kam tiek izmantota funkcija box.atomic
), lai samazinÄtu diska darbÄ«bu skaitu.
Visbeidzot, vietÄjÄs telpas sinhronizÄcijas funkcija goods
izmantojot avotu, varat to Ä«stenot Å”Ädi:
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
Vispirms mÄs nolasÄm iepriekÅ” saglabÄto vÄrtÄ«bu row_ver
par telpu goods
. Ja tÄ trÅ«kst (pirmÄ apmaiÅas sesija), tad mÄs to uztveram kÄ row_ver
nulle. TÄlÄk ciklÄ veicam izmainÄ«to datu lejupielÄdi pa lappusei no avota norÄdÄ«tajÄ URL. KatrÄ iterÄcijÄ mÄs saglabÄjam saÅemtos datus attiecÄ«gajÄ lokÄlajÄ telpÄ un atjauninÄm vÄrtÄ«bu row_ver
(kosmosÄ row_ver
un mainÄ«gajÄ row_ver
) - Åemiet vÄrtÄ«bu row_ver
no pÄdÄjÄs ielÄdÄto datu rindas.
Lai pasargÄtu no nejauÅ”as cilpas (programmas kļūdas gadÄ«jumÄ), cilpa while
var aizstÄt ar for
:
for _ = 1, max_req do ...
Funkcijas izpildes rezultÄtÄ sync_goods
telpa goods
uztvÄrÄjÄ bÅ«s visu kosmosa ierakstu jaunÄkÄs versijas goods
avotÄ.
AcÄ«mredzot datu dzÄÅ”anu nevar pÄrraidÄ«t Å”ÄdÄ veidÄ. Ja Å”Äda vajadzÄ«ba pastÄv, varat izmantot dzÄÅ”anas atzÄ«mi. Pievienot telpai goods
BÅ«la lauks is_deleted
un tÄ vietÄ, lai fiziski dzÄstu ierakstu, mÄs izmantojam loÄ£isko dzÄÅ”anu - mÄs iestatÄm lauka vÄrtÄ«bu is_deleted
nozÄ«mÄ true
. Dažreiz BÅ«la lauka vietÄ is_deleted
ir ÄrtÄk izmantot lauku deleted
, kurÄ tiek saglabÄts ieraksta loÄ£iskÄs dzÄÅ”anas datums un laiks. PÄc loÄ£iskÄs dzÄÅ”anas veikÅ”anas ieraksts, kas atzÄ«mÄts dzÄÅ”anai, tiks pÄrsÅ«tÄ«ts no avota uz galamÄrÄ·i (saskaÅÄ ar iepriekÅ” apskatÄ«to loÄ£iku).
Secība row_ver
var izmantot datu pÄrsÅ«tÄ«Å”anai no citÄm telpÄm: nav nepiecieÅ”ams izveidot atseviŔķu secÄ«bu katrai pÄrraidÄ«tajai telpai.
MÄs apskatÄ«jÄm efektÄ«vu augsta lÄ«meÅa datu replikÄcijas veidu lietojumprogrammÄs, izmantojot Tarantool DBVS.
Atzinumi
- Tarantool DBMS ir pievilcīgs, daudzsoloŔs produkts lielas slodzes lietojumprogrammu izveidei.
- Augsta lÄ«meÅa datu replikÄcijai ir vairÄkas priekÅ”rocÄ«bas salÄ«dzinÄjumÄ ar zema lÄ«meÅa replikÄciju.
- RakstÄ aplÅ«kotÄ augsta lÄ«meÅa replikÄcijas metode ļauj samazinÄt pÄrsÅ«tÄ«to datu apjomu, pÄrsÅ«tot tikai tos ierakstus, kas ir mainÄ«juÅ”ies kopÅ” pÄdÄjÄs apmaiÅas sesijas.
Avots: www.habr.com