Korkean tason replikointi Tarantool DBMS:ssä

Hei, olen luomassa sovelluksia DBMS:lle Tarantool on Mail.ru Groupin kehittämä alusta, joka yhdistää tehokkaan DBMS:n ja sovelluspalvelimen Lua-kielellä. Tarantool-pohjaisten ratkaisujen suuri nopeus saavutetaan erityisesti DBMS:n muistin sisäisen tilan tuen ja kyvyn suorittaa sovellusten liiketoimintalogiikkaa yhdessä osoiteavaruudessa tietojen kanssa. Samaan aikaan tietojen pysyvyys varmistetaan ACID-tapahtumilla (WAL-lokia ylläpidetään levyllä). Tarantoolissa on sisäänrakennettu tuki replikointia ja sirpalointia varten. Versiosta 2.1 alkaen tuetaan SQL-kielen kyselyjä. Tarantool on avoimen lähdekoodin ja lisensoitu Simplified BSD -lisenssillä. On myös kaupallinen Enterprise-versio.

Korkean tason replikointi Tarantool DBMS:ssä
Tunne voima! (… eli nauti esityksestä)

Kaikki edellä mainitut tekevät Tarantoolista houkuttelevan alustan tietokantojen kanssa toimivien suurtehosovellusten luomiseen. Tällaisissa sovelluksissa on usein tarve tietojen replikointiin.

Kuten edellä mainittiin, Tarantoolissa on sisäänrakennettu tietojen replikointi. Sen toimintaperiaate on suorittaa peräkkäin replikoissa kaikki päälokissa (WAL) olevat tapahtumat. Yleensä tällainen replikointi (kutsumme sitä edelleen matala taso) käytetään varmistamaan sovelluksen virhetoleranssi ja/tai jakamaan lukukuormituksen klusterin solmujen välillä.

Korkean tason replikointi Tarantool DBMS:ssä
Riisi. 1. Replikointi klusterin sisällä

Esimerkki vaihtoehtoisesta skenaariosta olisi yhdessä tietokannassa luotujen tietojen siirtäminen toiseen tietokantaan käsittelyä/seurantaa varten. Jälkimmäisessä tapauksessa kätevämpi ratkaisu voi olla käyttää korkeatasoinen replikointi - tietojen replikointi sovelluksen liiketoimintalogiikkatasolla. Nuo. Emme käytä DBMS-järjestelmään sisäänrakennettua valmiita ratkaisuja, vaan toteutamme replikoinnin itse kehittämässämme sovelluksessa. Tällä lähestymistavalla on sekä etuja että haittoja. Listataan edut.

1. Liikennesäästöt:

  • Et voi siirtää kaikkia tietoja, vaan vain osaa siitä (voit esimerkiksi siirtää vain joitain taulukoita, osan niiden sarakkeista tai tietueista, jotka täyttävät tietyn kriteerin);
  • Toisin kuin matalan tason replikointi, joka suoritetaan jatkuvasti asynkronisessa (toteutettu Tarantoolin nykyisessä versiossa - 1.10) tai synkronisessa (toteutetaan Tarantoolin myöhemmissä versioissa) -tilassa, korkean tason replikointi voidaan suorittaa istunnoissa (ts. sovellus synkronoi ensin tiedot - vaihtoistunnon tiedot, sitten replikaatiossa on tauko, jonka jälkeen tapahtuu seuraava vaihtoistunto jne.);
  • jos tietue on muuttunut useita kertoja, voit siirtää vain sen uusimman version (toisin kuin matalan tason replikaatiossa, jossa kaikki masteriin tehdyt muutokset toistetaan peräkkäin replikoissa).

2. HTTP-vaihdon toteuttamisessa ei ole vaikeuksia, mikä mahdollistaa etätietokantojen synkronoinnin.

Korkean tason replikointi Tarantool DBMS:ssä
Riisi. 2. Replikointi HTTP:n kautta

3. Tietokantarakenteiden, joiden välillä tietoja siirretään, ei tarvitse olla samoja (lisäksi yleensä voidaan jopa käyttää erilaisia ​​DBMS-järjestelmiä, ohjelmointikieliä, alustoja jne.).

Korkean tason replikointi Tarantool DBMS:ssä
Riisi. 3. Replikointi heterogeenisissä järjestelmissä

Huonona puolena on, että ohjelmointi on keskimäärin vaikeampaa/kallimpaa kuin konfigurointi, ja sisäänrakennetun toiminnallisuuden räätälöimisen sijaan joudut toteuttamaan omasi.

Jos edellä mainitut edut ovat tilanteessasi ratkaisevia (tai välttämättömiä), on järkevää käyttää korkean tason replikointia. Tarkastellaan useita tapoja toteuttaa korkean tason tietojen replikointi Tarantool DBMS:ssä.

Liikenteen minimoiminen

Joten yksi korkean tason replikoinnin eduista on liikenteen säästö. Jotta tämä etu toteutuisi täysin, on tarpeen minimoida siirrettävän datan määrä jokaisen vaihtoistunnon aikana. Emme tietenkään saa unohtaa, että istunnon lopussa datavastaanotin on synkronoitava lähteen kanssa (ainakin sen osan osalta, joka liittyy replikointiin).

Kuinka minimoida siirrettävän tiedon määrä korkean tason replikoinnin aikana? Yksinkertainen ratkaisu voisi olla tietojen valitseminen päivämäärän ja kellonajan mukaan. Voit tehdä tämän käyttämällä taulukossa jo olevaa päivämäärä-aika-kenttää (jos sellainen on). Esimerkiksi "tilaus"-asiakirjassa voi olla kenttä "tarvittava tilauksen suoritusaika" - delivery_time. Tämän ratkaisun ongelmana on, että tämän kentän arvojen ei tarvitse olla järjestyksessä, joka vastaa tilausten luomista. Emme siis muista kentän enimmäisarvoa delivery_time, lähetetty edellisen vaihtoistunnon aikana, ja valitse seuraavan vaihtoistunnon aikana kaikki tietueet, joilla on korkeampi kenttäarvo delivery_time. Tietueita, joilla on pienempi kenttäarvo, on saatettu lisätä vaihtoistuntojen välillä delivery_time. Myös tilaukseen olisi voinut tulla muutoksia, jotka eivät kuitenkaan vaikuttaneet kentälle delivery_time. Kummassakaan tapauksessa muutoksia ei siirretä lähteestä kohteeseen. Näiden ongelmien ratkaisemiseksi meidän on siirrettävä tiedot "päällekkäin". Nuo. jokaisessa vaihtoistunnossa siirrämme kaikki tiedot kentän arvolla delivery_time, ylittää jonkin pisteen menneisyydestä (esimerkiksi N tuntia nykyisestä hetkestä). On kuitenkin selvää, että suurille järjestelmille tämä lähestymistapa on erittäin tarpeeton ja voi vähentää tavoittelemamme liikenteen säästöjä. Lisäksi siirrettävässä taulukossa ei välttämättä ole kenttää, joka liittyy päivämäärään ja aikaan.

Toinen toteutuksen kannalta monimutkaisempi ratkaisu on kuitata tietojen vastaanottaminen. Tällöin jokaisen vaihtoistunnon aikana lähetetään kaikki tiedot, joiden vastaanottamista vastaanottaja ei ole vahvistanut. Tämän toteuttamiseksi sinun on lisättävä Boolen sarake lähdetaulukkoon (esim. is_transferred). Jos vastaanottaja kuittaa tietueen vastaanottamisen, vastaava kenttä ottaa arvon true, jonka jälkeen merkintä ei ole enää mukana vaihdoissa. Tällä toteutusvaihtoehdolla on seuraavat haitat. Ensin jokaisesta siirretystä tietueesta on luotava ja lähetettävä kuittaus. Karkeasti sanottuna tämä voisi olla verrattavissa siirrettävän tiedon määrän kaksinkertaistumiseen ja edestakaisen matkojen määrän kaksinkertaistumiseen. Toiseksi, samaa tietuetta ei ole mahdollista lähettää usealle vastaanottajalle (ensimmäinen vastaanottaja vahvistaa vastaanottamisen itselleen ja kaikille muille).

Menetelmä, jolla ei ole edellä esitettyjä haittoja, on lisätä siirrettyyn taulukkoon sarake sen rivien muutosten seuraamiseksi. Tällainen sarake voi olla päivämäärä-aika-tyyppinen, ja sovelluksen on asetettava/päivitettävä se nykyiseen aikaan aina, kun tietueita lisätään/muutetaan (atomisesti lisäyksen/muutoksen kanssa). Esimerkkinä kutsutaan saraketta update_time. Tallentamalla tämän sarakkeen kentän maksimiarvon siirretyille tietueille, voimme aloittaa seuraavan vaihtoistunnon tällä arvolla (valitse tietueet kentän arvolla update_time, ylittää aiemmin tallennetun arvon). Jälkimmäisen lähestymistavan ongelmana on, että datamuutoksia voi tapahtua erissä. Sarakkeen kenttäarvojen seurauksena update_time ei välttämättä ole ainutlaatuinen. Näin ollen tätä saraketta ei voida käyttää ositettuun (sivu sivulta) tietojen tuottamiseen. Jotta voit näyttää tiedot sivulta, sinun on keksittävä lisämekanismeja, joiden tehokkuus on todennäköisesti erittäin alhainen (esimerkiksi kaikkien tietueiden hakeminen tietokannasta, joissa on arvo update_time korkeampi kuin tietty ja tuottaa tietyn määrän tietueita alkaen tietystä poikkeamasta näytteen alusta).

Voit parantaa tiedonsiirron tehokkuutta parantamalla hieman edellistä lähestymistapaa. Käytämme tätä varten kokonaislukutyyppiä (pitkä kokonaisluku) sarakekentän arvoina muutosten seurannassa. Nimetään sarake row_ver. Tämän sarakkeen kentän arvo on silti asetettava/päivitettävä aina, kun tietue luodaan/muutetaan. Mutta tässä tapauksessa kenttään ei määritetä nykyistä päivämäärää ja kellonaikaa, vaan jonkin laskurin arvoa korotettuna yhdellä. Tämän seurauksena sarake row_ver sisältää ainutlaatuisia arvoja, ja sitä voidaan käyttää paitsi näyttämään "delta"-dataa (edellisen vaihto-istunnon päättymisen jälkeen lisätyt/muokatut tiedot), vaan myös jakaa ne yksinkertaisesti ja tehokkaasti sivuiksi.

Viimeisin ehdotettu menetelmä korkean tason replikoinnin puitteissa siirrettävien tietojen määrän minimoimiseksi näyttää minusta optimaalisimmalta ja universaalimmalta. Katsotaanpa sitä tarkemmin.

Tietojen välittäminen riviversiolaskurin avulla

Palvelin/isäntäosan toteutus

MS SQL Serverissä on erityinen saraketyyppi tämän lähestymistavan toteuttamiseksi - rowversion. Jokaisessa tietokannassa on laskuri, joka kasvaa yhdellä joka kerta, kun tietue lisätään/muutetaan taulukkoon, jossa on sarakkeen kaltainen rowversion. Tämän laskurin arvo liitetään automaattisesti tämän sarakkeen kenttään lisätyssä/muokatussa tietueessa. Tarantool DBMS:ssä ei ole samanlaista sisäänrakennettua mekanismia. Tarantoolissa sen toteuttaminen manuaalisesti ei kuitenkaan ole vaikeaa. Katsotaanpa, miten tämä tehdään.

Ensinnäkin vähän terminologiaa: Tarantoolin taulukoita kutsutaan välilyönneiksi ja tietueita monikkoiksi. Tarantoolissa voit luoda sarjoja. Sekvenssit eivät ole mitään muuta kuin järjestetyn kokonaislukuarvon nimettyjä generaattoreita. Nuo. tämä on juuri sitä mitä tarvitsemme tarkoituksiin. Alla luomme tällaisen sekvenssin.

Ennen kuin teet mitään tietokantatoimintoa Tarantoolissa, sinun on suoritettava seuraava komento:

box.cfg{}

Tämän seurauksena Tarantool alkaa kirjoittaa tietokannan tilannekuvia ja tapahtumalokeja nykyiseen hakemistoon.

Luodaan sarja row_version:

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

Vaihtoehto if_not_exists mahdollistaa luomisskriptin suorittamisen useita kertoja: jos objekti on olemassa, Tarantool ei yritä luoda sitä uudelleen. Tätä vaihtoehtoa käytetään kaikissa myöhemmissä DDL-komennoissa.

Luodaan tila esimerkkinä.

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

Tässä asetetaan tilan nimi (goods), kenttien nimet ja niiden tyypit.

Automaattisesti kasvavat kentät Tarantoolissa luodaan myös sekvenssien avulla. Luodaan automaattisesti kasvava ensisijainen avain kenttien mukaan 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 tukee useita indeksejä. Yleisimmin käytetyt indeksit ovat TREE- ja HASH-tyypit, jotka perustuvat nimeä vastaaviin rakenteisiin. PUU on monipuolisin indeksityyppi. Sen avulla voit hakea tietoja järjestelmällisesti. Mutta tasa-arvoiseen valintaan HASH on sopivampi. Tästä syystä on suositeltavaa käyttää HASH:ia ensisijaisena avaimena (mikä teimme).

Voit käyttää saraketta row_ver Jos haluat siirtää muuttuneita tietoja, sinun on sidottava sekvenssiarvot tämän sarakkeen kenttiin row_ver. Mutta toisin kuin ensisijainen avain, sarakekentän arvo row_ver pitäisi kasvaa yhdellä paitsi uusia tietueita lisättäessä myös olemassa olevia tietueita muuttaessa. Voit käyttää triggereitä tähän. Tarantoolilla on kahden tyyppisiä tilalaukaisimia: before_replace и on_replace. Triggerit käynnistetään aina, kun tilan tiedot muuttuvat (jokaiselle muutoksille vaikuttaneelle monikolle käynnistetään laukaisutoiminto). Toisin kuin on_replace, before_replace-triggereillä voit muokata sen monikon tietoja, jolle liipaisin suoritetaan. Näin ollen viimeinen laukaisutyyppi sopii meille.

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

Seuraava liipaisin korvaa kentän arvon row_ver tallennettu monikko sekvenssin seuraavaan arvoon row_version.

Jotta voidaan poimia tietoja avaruudesta goods sarakkeen mukaan row_ver, luodaan indeksi:

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

Hakemistotyyppi - puu (TREE), koska meidän on poimittava tiedot sarakkeen arvojen nousevassa järjestyksessä row_ver.

Lisätään tietoja tilaan:

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}

Koska Ensimmäinen kenttä on automaattisesti kasvava laskuri; ohitamme sen sijaan nollan. Tarantool korvaa automaattisesti seuraavan arvon. Samoin sarakekenttien arvona row_ver voit jättää nollan - tai olla määrittämättä arvoa ollenkaan, koska tämä sarake on tilan viimeisessä paikassa.

Tarkastetaan lisäystulos:

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

Kuten näet, ensimmäinen ja viimeinen kentät täytetään automaattisesti. Nyt on helppo kirjoittaa funktio tilanmuutosten sivulta lataamiseen 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

Funktio ottaa parametriksi arvon row_ver, josta alkaen muutokset on purettava, ja palauttaa osan muuttuneista tiedoista.

Tarantoolissa datanäytteenotto tapahtuu indeksien kautta. Toiminto get_goods käyttää iteraattoria indeksin mukaan row_ver vastaanottaa muuttuneita tietoja. Iteraattorin tyyppi on GT (suurempi kuin, suurempi kuin). Tämä tarkoittaa, että iteraattori kulkee peräkkäin indeksiarvot alkaen välitetystä avaimesta (kentän arvo row_ver).

Iteraattori palauttaa monikot. Jotta dataa voidaan myöhemmin siirtää HTTP:n kautta, monikot on muutettava rakenteeseen, joka on kätevä myöhempää sarjoitusta varten. Esimerkki käyttää tähän standardifunktiota tomap. Käyttämisen sijaan tomap voit kirjoittaa oman funktiosi. Haluamme esimerkiksi nimetä kentän uudelleen name, älä ohita kenttää code ja lisää kenttä 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

Tulostiedon sivukoko (tietueiden lukumäärä yhdessä osassa) määräytyy muuttujan mukaan page_size. Esimerkissä arvo page_size on 5. Oikeassa ohjelmassa sivun koolla on yleensä enemmän merkitystä. Se riippuu avaruustupelin keskimääräisestä koosta. Optimaalinen sivukoko voidaan määrittää empiirisesti mittaamalla tiedonsiirtoaika. Mitä suurempi sivukoko, sitä pienempi on kiertomatkojen määrä lähettävän ja vastaanottavan puolen välillä. Tällä tavalla voit lyhentää muutosten lataamiseen kuluvaa kokonaisaikaa. Jos sivun koko on kuitenkin liian suuri, käytämme liian kauan palvelimella näytteen sarjoittamista. Tämän seurauksena muiden palvelimelle tulevien pyyntöjen käsittelyssä voi esiintyä viiveitä. Parametri page_size voidaan ladata asetustiedostosta. Jokaiselle lähetetylle tilalle voit asettaa oman arvon. Useimmille tiloille oletusarvo (esimerkiksi 100) voi kuitenkin olla sopiva.

Suoritetaan toiminto 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
...

Otetaan kentän arvo row_ver viimeiseltä riviltä ja kutsu funktio uudelleen:

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

Taas kerran:

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

Kuten näet, tällä tavalla käytettynä funktio palauttaa kaikki tilatietueet sivulta sivulta goods. Viimeistä sivua seuraa tyhjä valinta.

Tehdään muutoksia tilaan:

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

Olemme muuttaneet kentän arvoa name yhdelle merkinnälle ja lisäsi kaksi uutta merkintää.

Toistetaan viimeinen funktiokutsu:

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

Funktio palautti muutetut ja lisätyt tietueet. Toiminto siis get_goods voit vastaanottaa tietoja, jotka ovat muuttuneet sen viimeisen kutsun jälkeen, mikä on tarkasteltavan replikointimenetelmän perusta.

Jätämme tulosten antamisen HTTP:n kautta JSON-muodossa tämän artikkelin ulkopuolelle. Voit lukea aiheesta täältä: https://habr.com/ru/company/mailru/blog/272141/

Asiakas/orja-osan toteutus

Katsotaanpa, miltä vastaanottavan puolen toteutus näyttää. Luodaan vastaanottavalle puolelle tila ladattujen tietojen tallentamiseksi:

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

Tilan rakenne muistuttaa lähteessä olevan tilan rakennetta. Mutta koska emme aio välittää vastaanotettuja tietoja muualle, sarake row_ver ei ole vastaanottajan tilassa. Kentällä id lähdetunnisteet tallennetaan. Siksi vastaanottimen puolella sitä ei tarvitse tehdä automaattisesti kasvavaksi.

Lisäksi tarvitsemme tilaa arvojen säästämiseen 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
})

Jokaista ladattua tilaa (kenttä space_name) tallennamme viimeksi ladatun arvon tähän row_ver (ala value). Sarake toimii ensisijaisena avaimena space_name.

Luodaan funktio tilatietojen lataamiseksi goods HTTP:n kautta. Tätä varten tarvitsemme kirjaston, joka toteuttaa HTTP-asiakkaan. Seuraava rivi lataa kirjaston ja instantoi HTTP-asiakkaan:

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

Tarvitsemme myös kirjaston json-deserialisointia varten:

local json = require('json')

Tämä riittää tietojen latausfunktion luomiseen:

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

Funktio suorittaa HTTP-pyynnön url-osoitteeseen ja lähettää sen row_ver parametrina ja palauttaa pyynnön sarjoitetun tuloksen.

Vastaanotettujen tietojen tallennustoiminto näyttää tältä:

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

Tietojen tallennus avaruuteen sykli goods sijoitettu tapahtumaan (toimintoa käytetään tähän box.atomic) vähentääksesi levytoimintojen määrää.

Lopuksi paikallistilan synkronointitoiminto goods lähteen avulla voit toteuttaa sen seuraavasti:

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

Ensin luetaan aiemmin tallennettu arvo row_ver tilaa varten goods. Jos se puuttuu (ensimmäinen vaihtoistunto), otamme sen sellaisena row_ver nolla. Seuraavaksi syklissä lataamme muuttuneet tiedot sivulta sivulta lähteestä määritetyssä URL-osoitteessa. Jokaisessa iteraatiossa tallennamme vastaanotetut tiedot sopivaan paikallistilaan ja päivitämme arvon row_ver (avaruudessa row_ver ja muuttujassa row_ver) - ota arvo row_ver viimeiseltä ladattujen tietojen riviltä.

Suojataksesi vahingossa tapahtuvalta silmukan (jos ohjelmassa on virhe), silmukka while voidaan korvata for:

for _ = 1, max_req do ...

Toiminnon suorittamisen seurauksena sync_goods tilaa goods vastaanotin sisältää uusimmat versiot kaikista avaruustietueista goods lähteessä.

Tietenkin tietojen poistamista ei voida lähettää tällä tavalla. Jos tällainen tarve on olemassa, voit käyttää poistomerkkiä. Lisää avaruuteen goods boolen kenttä is_deleted ja tietueen fyysisen poistamisen sijaan käytämme loogista poistamista - asetamme kentän arvon is_deleted merkitykseen true. Joskus loogisen kentän sijaan is_deleted on mukavampaa käyttää kenttää deleted, joka tallentaa tietueen loogisen poiston päivämäärän ja kellonajan. Loogisen poiston jälkeen poistettavaksi merkitty tietue siirretään lähteestä kohteeseen (yllä käsitellyn logiikan mukaisesti).

Järjestys row_ver voidaan käyttää tiedon siirtämiseen muista tiloista: jokaiselle lähetetylle avaruudelle ei tarvitse luoda erillistä sekvenssiä.

Tarkastelimme tehokasta tapaa korkean tason tietojen replikointiin sovelluksissa, joissa käytetään Tarantool DBMS:ää.

Tulokset

  1. Tarantool DBMS on houkutteleva, lupaava tuote korkean kuormituksen sovellusten luomiseen.
  2. Korkean tason tietojen replikaatiolla on useita etuja matalan tason replikointiin verrattuna.
  3. Artikkelissa käsitellyn korkean tason replikointimenetelmän avulla voit minimoida siirrettävien tietojen määrän siirtämällä vain ne tietueet, jotka ovat muuttuneet edellisen vaihtoistunnon jälkeen.

Lähde: will.com

Lisää kommentti