Tarantool DBMS'de üst düzey çoğaltma

Merhaba, DBMS için uygulamalar geliştiriyorum tarantool Mail.ru Group tarafından geliştirilen ve yüksek performanslı bir DBMS ile Lua dilinde bir uygulama sunucusunu birleştiren bir platformdur. Tarantool tabanlı çözümlerin yüksek hızı, özellikle DBMS'nin bellek içi modunun desteklenmesi ve uygulama iş mantığını verilerle tek bir adres alanında yürütme yeteneği sayesinde elde edilir. Aynı zamanda ACID işlemleri kullanılarak veri kalıcılığı sağlanır (disk üzerinde WAL kaydı tutulur). Tarantool, çoğaltma ve parçalama için yerleşik desteğe sahiptir. Sürüm 2.1'den itibaren SQL dilindeki sorgular desteklenmektedir. Tarantool açık kaynaktır ve Basitleştirilmiş BSD lisansı altında lisanslanmıştır. Ayrıca ticari bir Enterprise sürümü de bulunmaktadır.

Tarantool DBMS'de üst düzey çoğaltma
Gücü hisset! (…diğer bir deyişle performansın tadını çıkarın)

Yukarıdakilerin hepsi Tarantool'u veritabanlarıyla çalışan yüksek yüklü uygulamalar oluşturmak için çekici bir platform haline getiriyor. Bu tür uygulamalarda sıklıkla veri replikasyonuna ihtiyaç duyulur.

Yukarıda belirtildiği gibi Tarantool yerleşik veri çoğaltma özelliğine sahiptir. Çalışma prensibi, ana günlükte (WAL) bulunan tüm işlemlerin kopyaları üzerinde sırayla yürütülmesidir. Genellikle böyle bir çoğaltma (buna ayrıca diyeceğiz) düşük seviye) uygulamanın hata toleransını sağlamak ve/veya okuma yükünü küme düğümleri arasında dağıtmak için kullanılır.

Tarantool DBMS'de üst düzey çoğaltma
Pirinç. 1. Küme içinde çoğaltma

Alternatif bir senaryo örneği, bir veritabanında oluşturulan verilerin işlenmek/izlenmek üzere başka bir veritabanına aktarılması olabilir. İkinci durumda, daha uygun bir çözüm kullanmak olabilir. yüksek seviye çoğaltma - uygulama iş mantığı düzeyinde veri çoğaltma. Onlar. DBMS'nin içine yerleştirilmiş hazır bir çözüm kullanmıyoruz, geliştirdiğimiz uygulama içerisinde replikasyonu kendi başımıza gerçekleştiriyoruz. Bu yaklaşımın hem avantajları hem de dezavantajları vardır. Avantajlarını sıralayalım.

1. Trafik tasarrufu:

  • Verilerin tamamını değil, yalnızca bir kısmını aktarabilirsiniz (örneğin, yalnızca bazı tabloları, bunların bazı sütunlarını veya belirli bir kriteri karşılayan kayıtları aktarabilirsiniz);
  • Sürekli olarak eşzamansız (Tarantool - 1.10'un mevcut sürümünde uygulanmıştır) veya eşzamanlı (Tarantool'un sonraki sürümlerinde uygulanacak) modda gerçekleştirilen düşük düzeyli çoğaltmanın aksine, yüksek düzeyli çoğaltma oturumlar halinde gerçekleştirilebilir (ör. uygulama önce verileri senkronize eder - bir oturum verileri alışverişi yapılır, ardından çoğaltmada bir duraklama olur, ardından bir sonraki değişim oturumu gerçekleşir, vb.);
  • bir kayıt birkaç kez değiştiyse, yalnızca en son sürümünü aktarabilirsiniz (ana bilgisayarda yapılan tüm değişikliklerin kopyalarda sırayla oynatılacağı düşük seviyeli çoğaltmanın aksine).

2. Uzak veritabanlarını senkronize etmenize olanak tanıyan HTTP değişimini uygulamada herhangi bir zorluk yoktur.

Tarantool DBMS'de üst düzey çoğaltma
Pirinç. 2. HTTP üzerinden çoğaltma

3. Verilerin aralarında aktarıldığı veritabanı yapılarının aynı olması gerekmez (ayrıca genel durumda farklı DBMS'lerin, programlama dillerinin, platformların vb. kullanılması bile mümkündür).

Tarantool DBMS'de üst düzey çoğaltma
Pirinç. 3. Heterojen sistemlerde çoğaltma

Dezavantajı ise ortalama olarak programlamanın konfigürasyondan daha zor/pahalı olması ve yerleşik işlevselliği özelleştirmek yerine kendinizinkini uygulamanız gerekmesidir.

Sizin durumunuzda yukarıdaki avantajlar çok önemliyse (veya gerekli bir koşulsa), o zaman yüksek düzeyde çoğaltmayı kullanmak mantıklı olacaktır. Tarantool DBMS'de üst düzey veri çoğaltmayı uygulamanın çeşitli yollarına bakalım.

Trafik minimizasyonu

Dolayısıyla, yüksek düzeyde çoğaltmanın avantajlarından biri trafik tasarrufudur. Bu avantajın tam anlamıyla gerçekleşebilmesi için her değişim oturumu sırasında aktarılan veri miktarının en aza indirilmesi gerekmektedir. Elbette, oturumun sonunda veri alıcısının kaynakla senkronize edilmesi gerektiğini (en azından verinin çoğaltmada yer alan kısmı için) unutmamalıyız.

Üst düzey çoğaltma sırasında aktarılan veri miktarı nasıl en aza indirilir? Verileri tarih ve saate göre seçmek basit bir çözüm olabilir. Bunu yapmak için tabloda zaten mevcut olan (varsa) tarih-saat alanını kullanabilirsiniz. Örneğin, bir "sipariş" belgesinde "gerekli sipariş yürütme süresi" alanı bulunabilir - delivery_time. Bu çözümün sorunu, bu alandaki değerlerin, siparişlerin oluşturulmasına karşılık gelen sırada olmasının gerekmemesidir. Bu yüzden maksimum alan değerini hatırlayamıyoruz delivery_time, önceki değişim oturumu sırasında iletilir ve sonraki değişim oturumu sırasında alan değeri daha yüksek olan tüm kayıtları seçer delivery_time. Daha düşük alan değerine sahip kayıtlar değişim oturumları arasına eklenmiş olabilir delivery_time. Ayrıca siparişte değişiklik yapılmış olabilir, ancak bu durum yine de alanı etkilememiştir. delivery_time. Her iki durumda da değişiklikler kaynaktan hedefe aktarılmayacaktır. Bu sorunları çözmek için verileri "örtüşen" olarak aktarmamız gerekecek. Onlar. her değişim oturumunda tüm verileri alan değeriyle aktaracağız delivery_time, geçmişteki bir noktayı aşan (örneğin, şu andaki N saat sonrası). Ancak büyük sistemler için bu yaklaşımın son derece gereksiz olduğu ve uğruna çabaladığımız trafik tasarruflarını sıfıra indirebileceği açıktır. Ayrıca aktarılan tablonun tarih-saat ile ilişkilendirilmiş bir alanı olmayabilir.

Uygulama açısından daha karmaşık olan diğer bir çözüm ise verinin alındığının onaylanmasıdır. Bu durumda, her değişim oturumu sırasında, alındığı alıcı tarafından onaylanmayan tüm veriler iletilir. Bunu uygulamak için kaynak tabloya bir Boolean sütunu eklemeniz gerekir (örneğin, is_transferred). Alıcı kaydın alındığını onaylarsa ilgili alan değeri alır true, bundan sonra giriş artık borsalarda yer almaz. Bu uygulama seçeneğinin aşağıdaki dezavantajları vardır. Öncelikle aktarılan her kayıt için bir onay oluşturulup gönderilmelidir. Kabaca söylemek gerekirse, bu, aktarılan veri miktarının iki katına çıkarılması ve gidiş-dönüş sayısının iki katına çıkarılmasıyla karşılaştırılabilir. İkinci olarak, aynı kaydın birden fazla alıcıya gönderilmesi mümkün değildir (ilk alıcı, kendisi ve diğerleri için alındığını onaylayacaktır).

Yukarıda belirtilen dezavantajlara sahip olmayan bir yöntem, aktarılan tabloya satırlarındaki değişiklikleri takip etmek için bir sütun eklemektir. Böyle bir sütun, tarih-saat türünde olabilir ve kayıtların her eklendiği/değiştirildiği (atomik olarak ekleme/değiştirme ile) uygulama tarafından geçerli saate ayarlanması/güncellenmesi gerekir. Örnek olarak sütunu çağıralım update_time. Aktarılan kayıtlar için bu sütunun maksimum alan değerini kaydederek bir sonraki değişim oturumunu bu değerle başlatabiliriz (alan değerine sahip kayıtları seçin) update_time, önceden saklanan değeri aşıyor). İkinci yaklaşımın sorunu, veri değişikliklerinin gruplar halinde meydana gelebilmesidir. Sütundaki alan değerleri sonucunda update_time benzersiz olmayabilir. Bu nedenle, bu sütun bölümlenmiş (sayfa sayfa) veri çıkışı için kullanılamaz. Verileri sayfa sayfa görüntülemek için, büyük olasılıkla çok düşük verimliliğe sahip olacak ek mekanizmalar icat etmeniz gerekecektir (örneğin, değere sahip tüm kayıtları veritabanından almak). update_time belirli bir kayıttan daha yüksek ve örneğin başlangıcından itibaren belirli bir sapmadan başlayarak belirli sayıda kayıt üreten).

Önceki yaklaşımı biraz geliştirerek veri aktarımının verimliliğini artırabilirsiniz. Bunu yapmak için değişiklikleri izlemek için sütun alanı değerleri olarak tamsayı türünü (uzun tamsayı) kullanacağız. Sütuna isim verelim row_ver. Bu sütunun alan değeri, her kayıt oluşturulduğunda/değiştirildiğinde yine de ayarlanmalı/güncellenmelidir. Ancak bu durumda, alana geçerli tarih-saat atanmayacak, ancak bazı sayaçların değeri bir artırılacaktır. Sonuç olarak sütun row_ver benzersiz değerler içerecektir ve yalnızca "delta" verilerini (önceki değişim oturumunun sonundan bu yana eklenen/değiştirilen veriler) görüntülemek için değil, aynı zamanda bunları basit ve etkili bir şekilde sayfalara ayırmak için de kullanılabilir.

Yüksek düzeyde çoğaltma çerçevesinde aktarılan veri miktarını en aza indirmenin son önerilen yöntemi bana en uygun ve evrensel görünüyor. Gelin buna daha detaylı bakalım.

Satır Sürümü Sayacı Kullanarak Veri Aktarma

Sunucu/ana bölümün uygulanması

MS SQL Server'da bu yaklaşımı uygulamak için özel bir sütun türü vardır - rowversion. Her veritabanında, aşağıdaki gibi bir sütuna sahip bir tabloya her kayıt eklendiğinde/değiştirildiğinde bir artan bir sayaç bulunur. rowversion. Bu sayacın değeri, eklenen/değiştirilen kayıtta bu sütunun alanına otomatik olarak atanır. Tarantool DBMS'nin benzer bir yerleşik mekanizması yoktur. Ancak Tarantool'da bunu manuel olarak uygulamak zor değil. Bunun nasıl yapıldığına bakalım.

Öncelikle küçük bir terminoloji: Tarantool'daki tablolara boşluk, kayıtlara da tuple denir. Tarantool'da diziler oluşturabilirsiniz. Diziler, sıralı tamsayı değerlerinin adlandırılmış oluşturucularından başka bir şey değildir. Onlar. amaçlarımız açısından tam olarak ihtiyacımız olan şey bu. Aşağıda böyle bir dizi oluşturacağız.

Tarantool'da herhangi bir veritabanı işlemi yapmadan önce aşağıdaki komutu çalıştırmanız gerekir:

box.cfg{}

Sonuç olarak Tarantool, veritabanı anlık görüntülerini ve işlem günlüklerini geçerli dizine yazmaya başlayacaktır.

Bir dizi oluşturalım row_version:

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

Seçenek if_not_exists oluşturma komut dosyasının birden çok kez yürütülmesine izin verir: nesne mevcutsa Tarantool onu yeniden oluşturmaya çalışmaz. Bu seçenek sonraki tüm DDL komutlarında kullanılacaktır.

Örnek olarak bir alan oluşturalım.

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

Burada alanın adını belirliyoruz (goods), alan adları ve türleri.

Tarantool'da otomatik olarak artan alanlar da diziler kullanılarak oluşturulur. Alana göre otomatik artan bir birincil anahtar oluşturalım 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 çeşitli indeks türlerini destekler. En sık kullanılan indeksler isme karşılık gelen yapıları temel alan TREE ve HASH türleridir. TREE en çok yönlü indeks türüdür. Verileri düzenli bir şekilde almanızı sağlar. Ancak eşitlik seçimi için HASH daha uygundur. Buna göre birincil anahtar olarak HASH kullanılması tavsiye edilir (biz de öyle yaptık).

Sütunu kullanmak için row_ver Değiştirilen verileri aktarmak için sıra değerlerini bu sütunun alanlarına bağlamanız gerekir row_ver. Ancak birincil anahtardan farklı olarak sütun alanı değeri row_ver sadece yeni kayıt eklerken değil, mevcut kayıtları değiştirirken de birer birer artmalıdır. Bunun için tetikleyicileri kullanabilirsiniz. Tarantool'un iki tür alan tetikleyicisi vardır: before_replace и on_replace. Alandaki veriler değiştiğinde tetikleyiciler tetiklenir (değişikliklerden etkilenen her demet için bir tetikleyici işlevi başlatılır). Farklı on_replace, before_replace-triggers, tetikleyicinin yürütüldüğü tuple'ın verilerini değiştirmenize olanak tanır. Buna göre son tip tetikleyiciler bize uygundur.

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

Aşağıdaki tetikleyici alan değerinin yerini alır row_ver dizinin bir sonraki değerine depolanan tuple row_version.

Uzaydan veri çekebilmek için goods sütuna göre row_ver, bir dizin oluşturalım:

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

Dizin türü - ağaç (TREE), Çünkü verileri sütundaki değerlere göre artan sırada çıkarmamız gerekecek row_ver.

Uzaya biraz veri ekleyelim:

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}

Çünkü İlk alan otomatik olarak artan bir sayaçtır; bunun yerine nil'i geçiyoruz. Tarantool otomatik olarak bir sonraki değeri değiştirecektir. Benzer şekilde sütun alanlarının değeri olarak row_ver sıfır değerini iletebilir veya değeri hiç belirtmeyebilirsiniz, çünkü bu sütun uzaydaki son konumu kaplar.

Ekleme sonucunu kontrol edelim:

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

Gördüğünüz gibi ilk ve son alanlar otomatik olarak dolduruluyor. Artık alan değişikliklerinin sayfa sayfa yüklenmesi için bir fonksiyon yazmak kolay olacak 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

Fonksiyon parametre olarak değeri alır row_ver, değişikliklerin kaldırılmasının gerekli olduğu yerden başlayarak ve değiştirilen verilerin bir kısmını döndürür.

Tarantool'da veri örneklemesi indeksler aracılığıyla yapılır. İşlev get_goods dizine göre bir yineleyici kullanır row_ver Değiştirilen verileri almak için. Yineleyici türü GT'dir (Büyüktür, büyüktür). Bu, yineleyicinin, iletilen anahtardan (alan değeri) başlayarak dizin değerlerini sırayla geçeceği anlamına gelir. row_ver).

Yineleyici, tuple'ları döndürür. Daha sonra verileri HTTP yoluyla aktarabilmek için, tuple'ların daha sonraki serileştirmeye uygun bir yapıya dönüştürülmesi gerekir. Örnek bunun için standart işlevi kullanıyor tomap. Kullanmak yerine tomap kendi fonksiyonunuzu yazabilirsiniz. Örneğin, bir alanı yeniden adlandırmak isteyebiliriz name, alanı geçmeyin code ve bir alan ekleyin 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

Çıkış verilerinin sayfa boyutu (bir kısımdaki kayıt sayısı) değişken tarafından belirlenir. page_size. Örnekte değer page_size 5'tir. Gerçek bir programda sayfa boyutu genellikle daha önemlidir. Space Tuple'ın ortalama boyutuna bağlıdır. Optimum sayfa boyutu, veri aktarım süresi ölçülerek ampirik olarak belirlenebilir. Sayfa boyutu ne kadar büyük olursa, gönderen ve alan taraflar arasındaki gidiş-dönüş sayısı da o kadar az olur. Bu şekilde değişiklikleri indirmek için gereken toplam süreyi azaltabilirsiniz. Ancak sayfa boyutu çok büyükse, sunucuda numuneyi seri hale getirmek için çok fazla zaman harcayacağız. Bunun sonucunda sunucuya gelen diğer isteklerin işlenmesinde gecikmeler yaşanabilir. Parametre page_size yapılandırma dosyasından yüklenebilir. İletilen her alan için kendi değerini ayarlayabilirsiniz. Ancak çoğu alan için varsayılan değer (örneğin 100) uygun olabilir.

Fonksiyonu çalıştıralım 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
...

Alan değerini alalım row_ver son satırdan itibaren işlevi tekrar çağırın:

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

Ve yine:

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

Görüldüğü üzere fonksiyon bu şekilde kullanıldığında tüm alan kayıtlarını sayfa sayfa döndürmektedir. goods. Son sayfanın ardından boş bir seçim gelir.

Uzayda değişiklikler yapalım:

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

Alan değerini değiştirdik name bir giriş için ve iki yeni giriş eklendi.

Son fonksiyon çağrımızı tekrarlayalım:

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

İşlev, değiştirilen ve eklenen kayıtları döndürdü. Yani fonksiyon get_goods Söz konusu çoğaltma yönteminin temeli olan, son çağrısından bu yana değişen verileri almanıza olanak tanır.

Sonuçların HTTP aracılığıyla JSON biçiminde verilmesini bu makalenin kapsamı dışında bırakacağız. Bu konuyu buradan okuyabilirsiniz: https://habr.com/ru/company/mailru/blog/272141/

İstemci/bağımlı parçanın uygulanması

Alıcı tarafın uygulamasının nasıl göründüğüne bakalım. İndirilen verileri saklamak için alıcı tarafta bir alan oluşturalım:

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

Mekanın yapısı kaynaktaki mekanın yapısına benzemektedir. Ancak alınan verileri başka bir yere iletmeyeceğimiz için sütun row_ver alıcının alanında değil. Tarlada id kaynak tanımlayıcıları kaydedilecektir. Bu nedenle alıcı tarafında otomatik artış yapılmasına gerek yoktur.

Ayrıca değerleri kaydetmek için bir alana ihtiyacımız var 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
})

Yüklenen her alan için (alan space_name) son yüklenen değeri buraya kaydedeceğiz row_ver (alan value). Sütun birincil anahtar görevi görür space_name.

Uzay verilerini yüklemek için bir fonksiyon oluşturalım goods HTTP aracılığıyla. Bunu yapmak için HTTP istemcisini uygulayan bir kütüphaneye ihtiyacımız var. Aşağıdaki satır kitaplığı yükler ve HTTP istemcisini başlatır:

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

Ayrıca json seri durumdan çıkarma için bir kütüphaneye ihtiyacımız var:

local json = require('json')

Bu, bir veri yükleme işlevi oluşturmak için yeterlidir:

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

İşlev, url adresine bir HTTP isteği yürütür ve bunu gönderir. row_ver parametre olarak kullanılır ve isteğin seri durumdan çıkarılmış sonucunu döndürür.

Alınan verileri kaydetme işlevi şuna benzer:

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

Verileri alana kaydetme döngüsü goods bir işleme yerleştirilir (işlev bunun için kullanılır) box.atomic) disk işlemlerinin sayısını azaltmak için.

Son olarak yerel alan senkronizasyon işlevi goods bir kaynakla bunu şu şekilde uygulayabilirsiniz:

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

İlk önce önceden kaydedilen değeri okuyoruz row_ver uzay için goods. Eğer eksikse (ilk değişim oturumu), o zaman bunu şu şekilde kabul ederiz: row_ver sıfır. Döngünün bir sonraki adımında, değiştirilen verilerin belirtilen URL'deki kaynaktan sayfa sayfa indirilmesini gerçekleştiririz. Her yinelemede alınan verileri uygun yerel alana kaydedip değeri güncelliyoruz row_ver (boşlukta row_ver ve değişkende row_ver) - değeri al row_ver Yüklenen verilerin son satırından.

Yanlışlıkla döngüye karşı koruma sağlamak için (programda bir hata olması durumunda), döngü while ile değiştirilebilir for:

for _ = 1, max_req do ...

Fonksiyonun yürütülmesi sonucunda sync_goods uzay goods alıcı tüm uzay kayıtlarının en son sürümlerini içerecektir goods kaynakta.

Açıkçası veri silme bu şekilde yayınlanamaz. Böyle bir ihtiyaç varsa silme işaretini kullanabilirsiniz. Alana ekle goods boole alanı is_deleted ve bir kaydı fiziksel olarak silmek yerine mantıksal silmeyi kullanırız - alan değerini belirleriz is_deleted anlam içine true. Bazen bir boole alanı yerine is_deleted alanı kullanmak daha uygundur deletedKaydın mantıksal olarak silinmesinin tarih-saatini saklayan. Mantıksal silme işlemi gerçekleştirildikten sonra silinmek üzere işaretlenen kayıt kaynaktan hedefe (yukarıda açıklanan mantığa göre) aktarılacaktır.

dizi row_ver diğer alanlardan veri iletmek için kullanılabilir: iletilen her alan için ayrı bir sıra oluşturmaya gerek yoktur.

Tarantool DBMS'yi kullanan uygulamalarda yüksek düzeyde veri çoğaltmanın etkili bir yolunu inceledik.

Bulgular

  1. Tarantool DBMS, yüksek yüklü uygulamalar oluşturmak için çekici ve gelecek vaat eden bir üründür.
  2. Yüksek düzeyli veri çoğaltmanın, düşük düzeyli çoğaltmaya göre birçok avantajı vardır.
  3. Makalede tartışılan üst düzey çoğaltma yöntemi, yalnızca son değişim oturumundan bu yana değişen kayıtları aktararak aktarılan veri miktarını en aza indirmenize olanak tanır.

Kaynak: habr.com

Yorum ekle