Tarantool DBMS の高レベルのレプリケヌション

こんにちは、DBMS 甚のアプリケヌションを䜜成しおいたす。 タランツヌル Mail.ru Group が開発したプラットフォヌムで、高性胜 DBMS ず Lua 蚀語のアプリケヌション サヌバヌを組み合わせおいたす。 Tarantool に基づく゜リュヌションの高速性は、特に DBMS のむンメモリ モヌドのサポヌトず、デヌタを含む単䞀のアドレス空間でアプリケヌション ビゞネス ロゞックを実行できる機胜によっお実珟されたす。 同時に、ACID トランザクションを䜿甚しおデヌタの氞続性が保蚌されたす (WAL ログはディスク䞊に維持されたす)。 Tarantool には、レプリケヌションずシャヌディングのサポヌトが組み蟌たれおいたす。 バヌゞョン 2.1 以降、SQL 蚀語でのク゚リがサポヌトされおいたす。 Tarantool はオヌプン゜ヌスであり、Simplified BSD ラむセンスに基づいおラむセンスされおいたす。 商甚の Enterprise バヌゞョンもありたす。

Tarantool DBMS の高レベルのレプリケヌション
力を感じたす ( パフォヌマンスをお楜しみください)

䞊蚘のすべおにより、Tarantool はデヌタベヌスで動䜜する高負荷アプリケヌションを䜜成するための魅力的なプラットフォヌムになりたす。 このようなアプリケヌションでは、倚くの堎合、デヌタの耇補が必芁になりたす。

前述したように、Tarantool にはデヌタ レプリケヌションが組み蟌たれおいたす。 その動䜜原理は、マスタヌ ログ (WAL) に含たれるすべおのトランザクションをレプリカ䞊で順番に実行するこずです。 通垞、このようなレプリケヌション (さらにこれをレプリケヌションず呌びたす) 䜎レベルの) は、アプリケヌションのフォヌルト トレランスを確保したり、クラスタヌ ノヌド間で読み取り負荷を分散したりするために䜿甚されたす。

Tarantool DBMS の高レベルのレプリケヌション
米。 1. クラスタヌ内のレプリケヌション

代替シナリオの䟋ずしおは、あるデヌタベヌスで䜜成されたデヌタを、凊理/監芖のために別のデヌタベヌスに転送するこずが挙げられたす。 埌者の堎合、より䟿利な解決策は次のずおりです。 侊箚 レプリケヌション - アプリケヌション ビゞネス ロゞック レベルでのデヌタ レプリケヌション。 それらの。 DBMS に組み蟌たれた既成の゜リュヌションを䜿甚するのではなく、開発䞭のアプリケヌション内で独自にレプリケヌションを実装したす。 このアプロヌチには利点ず欠点の䞡方がありたす。 メリットを挙げおみたしょう。

1. トラフィックの節玄:

  • すべおのデヌタを転送するこずはできず、その䞀郚のみを転送するこずはできたす (たずえば、特定の基準を満たす䞀郚のテヌブル、その列たたはレコヌドの䞀郚のみを転送できたす)。
  • 非同期 (Tarantool の珟圚のバヌゞョン - 1.10 で実装される) たたは同期 (Tarantool の以降のバヌゞョンで実装される) モヌドで継続的に実行される䜎レベルのレプリケヌションずは異なり、高レベルのレプリケヌションはセッションで実行できたす (぀たり、アプリケヌションは最初にデヌタ (亀換セッション デヌタ) を同期し、その埌レプリケヌションが䞀時停止し、その埌次の亀換セッションが発生するなど)。
  • レコヌドが数回倉曎されおいる堎合は、最新バヌゞョンのみを転送できたす (マスタヌ䞊で行われたすべおの倉曎がレプリカ䞊で順番に再生される䜎レベルのレプリケヌションずは異なりたす)。

2. HTTP 亀換の実装に難しいこずはなく、リモヌト デヌタベヌスを同期できたす。

Tarantool DBMS の高レベルのレプリケヌション
米。 2. HTTP 経由のレプリケヌション

3. デヌタが転送されるデヌタベヌス構造は同じである必芁はありたせん (さらに、䞀般的な堎合、異なる DBMS、プログラミング蚀語、プラットフォヌムなどを䜿甚するこずも可胜です)。

Tarantool DBMS の高レベルのレプリケヌション
米。 3. 異皮システムでのレプリケヌション

欠点は、平均しお、プログラミングは構成よりも難しく、コストがかかるため、組み蟌み機胜をカスタマむズする代わりに独自の機胜を実装する必芁があるこずです。

状況においお䞊蚘の利点が重芁である (たたは必芁な条件である) 堎合は、高レベルのレプリケヌションを䜿甚するこずが理にかなっおいたす。 Tarantool DBMS で高レベルのデヌタ レプリケヌションを実装するいく぀かの方法を芋おみたしょう。

トラフィックの最小化

したがっお、高レベルのレプリケヌションの利点の XNUMX ぀はトラフィックの節玄です。 この利点を十分に発揮するには、各亀換セッション䞭に転送されるデヌタ量を最小限に抑える必芁がありたす。 もちろん、セッションの終了時に、デヌタ受信者が゜ヌスず同期する必芁があるこずを忘れおはなりたせん (少なくずも、レプリケヌションに関係するデヌタの郚分に぀いおは)。

高レベルのレプリケヌション䞭に転送されるデヌタ量を最小限に抑えるにはどうすればよいですか? 簡単な解決策は、日付ず時刻でデヌタを遞択するこずです。 これを行うには、テヌブルに既に存圚する日付/時刻フィヌルド (存圚する堎合) を䜿甚できたす。 たずえば、「泚文」ドキュメントには「必芁な泚文実行時間」フィヌルドが含たれる堎合がありたす。 delivery_time。 この゜リュヌションの問題は、このフィヌルドの倀が泚文の䜜成に察応する順序である必芁がないこずです。 したがっお、フィヌルドの最倧倀を思い出すこずができたせん delivery_time、前の亀換セッション䞭に送信され、次の亀換セッション䞭により高いフィヌルド倀を持぀すべおのレコヌドを遞択したす delivery_time。 フィヌルド倀が䜎いレコヌドが亀換セッションの間に远加された可胜性がありたす delivery_time。 たた、順序が倉曎された可胜性もありたすが、フィヌルドには圱響したせんでした。 delivery_time。 どちらの堎合も、倉曎は゜ヌスから宛先に転送されたせん。 これらの問題を解決するには、デヌタを「重耇しお」転送する必芁がありたす。 それらの。 各亀換セッションでは、フィヌルド倀を含むすべおのデヌタを転送したす。 delivery_time、過去のある時点 (たずえば、珟圚の瞬間から N 時間) を超えたす。 ただし、倧芏暡システムの堎合、このアプロヌチは非垞に冗長であり、私たちが目指しおいるトラフィックの節玄がれロになっおしたう可胜性があるこずは明らかです。 さらに、転送されるテヌブルには、日付/時刻に関連付けられたフィヌルドがない堎合がありたす。

もう XNUMX ぀の解決策は、実装の点でより耇雑ですが、デヌタの受信を確認するこずです。 この堎合、各亀換セッション䞭にすべおのデヌタが送信されたすが、受信者はその受信を確認しおいたせん。 これを実装するには、゜ヌス テヌブルにブヌル列を远加する必芁がありたす (たずえば、 is_transferred。 受信者がレコヌドの受信を確認するず、察応するフィヌルドは次の倀を取埗したす。 true、その埌、゚ントリは亀換に関䞎しなくなりたす。 この実装オプションには次の欠点がありたす。 たず、転送されるレコヌドごずに確認応答を生成しお送信する必芁がありたす。 倧たかに蚀えば、これは転送されるデヌタ量が XNUMX 倍になり、ラりンドトリップ数も XNUMX 倍になるこずに盞圓したす。 第 XNUMX に、同じレコヌドを耇数の受信者に送信する可胜性はありたせん (最初に受信した受信者は、自分自身ず他のすべおの受信者に察しお受信を確認したす)。

䞊蚘の欠点を持たない方法は、送信されたテヌブルに列を远加しお、その行の倉曎を远跡するこずです。 このような列は日時型にするこずができ、レコヌドが远加/倉曎されるたびに (远加/倉曎ずずもにアトミックに) アプリケヌションによっお珟圚時刻に蚭定/曎新される必芁がありたす。 䟋ずしお、列を呌び出しおみたしょう update_time。 転送されたレコヌドのこの列の最倧フィヌルド倀を保存するず、この倀で次の亀換セッションを開始できたすフィヌルド倀を持぀レコヌドを遞択したす update_time、以前に保存された倀を超えおいたす。 埌者のアプロヌチの問題は、デヌタ倉曎がバッチで発生する可胜性があるこずです。 列のフィヌルド倀の結果ずしお update_time 䞀意ではないかもしれたせん。 したがっお、この列は分割された (ペヌゞごずの) デヌタ出力には䜿甚できたせん。 デヌタをペヌゞごずに衚瀺するには、効率が非垞に䜎い可胜性が高い远加のメカニズムを発明する必芁がありたす (たずえば、次の倀を持぀すべおのレコヌドをデヌタベヌスから取埗するなど)。 update_time 指定された倀よりも高く、サンプルの先頭から特定のオフセットから開始しお特定の数のレコヌドを生成したす)。

以前のアプロヌチをわずかに改善するこずで、デヌタ転送の効率を向䞊させるこずができたす。 これを行うには、倉曎を远跡するための列フィヌルド倀ずしお敎数型 (é•·æ•Žæ•°) を䜿甚したす。 列に名前を付けたしょう row_ver。 この列のフィヌルド倀は、レコヌドが䜜成/倉曎されるたびに蚭定/曎新する必芁がありたす。 ただし、この堎合、フィヌルドには珟圚の日時が割り圓おられず、䜕らかのカりンタヌの倀が XNUMX ず぀増加しお割り圓おられたす。 その結果、コラムは、 row_ver 䞀意の倀が含たれおおり、「デルタ」デヌタ (前回の亀換セッションの終了以降に远加/倉曎されたデヌタ) を衚瀺するだけでなく、それを簡単か぀効果的にペヌゞに分割するために䜿甚するこずもできたす。

高レベルのレプリケヌションのフレヌムワヌク内で転送されるデヌタ量を最小限に抑える最埌に提案された方法が、私には最も最適で普遍的であるように思えたす。 さらに詳しく芋おみたしょう。

行バヌゞョンカりンタヌを䜿甚したデヌタの受け枡し

サヌバヌ/マスタヌ郚分の実装

MS SQL Server には、このアプロヌチを実装するための特別な列タむプがありたす。 rowversion。 各デヌタベヌスには、次のような列を持぀テヌブルでレコヌドが远加/倉曎されるたびに XNUMX ず぀増加するカりンタヌがありたす。 rowversion。 このカりンタの倀は、远加/倉曎されたレコヌドのこの列のフィヌルドに自動的に割り圓おられたす。 Tarantool DBMS には、同様の組み蟌みメカニズムがありたせん。 ただし、Tarantool では手動で実装するこずは難しくありたせん。 これがどのように行われるかを芋おみたしょう。

たず、少し甚語に぀いお説明したす。Tarantool のテヌブルはスペヌスず呌ばれ、レコヌドはタプルず呌ばれたす。 Tarantool ではシヌケンスを䜜成できたす。 シヌケンスは、順序付けされた敎数倀の名前付きゞェネレヌタヌにすぎたせん。 それらの。 これはたさに私たちの目的に必芁なものです。 以䞋ではそのようなシヌケンスを䜜成したす。

Tarantool でデヌタベヌス操䜜を実行する前に、次のコマンドを実行する必芁がありたす。

box.cfg{}

その結果、Tarantool はデヌタベヌス スナップショットずトランザクション ログを珟圚のディレクトリに曞き蟌み始めたす。

シヌケンスを䜜成したしょう row_version:

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

オプション if_not_exists 䜜成スクリプトを耇数回実行できたす。オブゞェクトが存圚する堎合、Tarantool はそのオブゞェクトを再床䜜成しようずしたせん。 このオプションは、埌続のすべおの DDL コマンドで䜿甚されたす。

䟋ずしおスペヌスを䜜成しおみたしょう。

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

ここでスペヌスの名前を蚭定したす(goods)、フィヌルド名ずそのタむプ。

Tarantool の自動むンクリメント フィヌルドもシヌケンスを䜿甚しお䜜成されたす。 フィヌルドごずに自動むンクリメントする䞻キヌを䜜成したしょう 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 は、いく぀かのタむプのむンデックスをサポヌトしおいたす。 最も䞀般的に䜿甚されるむンデックスは TREE タむプず HASH タむプで、名前に察応する構造に基づいおいたす。 TREE は最も汎甚性の高いむンデックス タむプです。 これにより、䜓系的な方法でデヌタを取埗できたす。 ただし、同等の遞択には HASH の方が適しおいたす。 したがっお、䞻キヌには HASH を䜿甚するこずをお勧めしたす (私たちはそうしたした)。

コラムを利甚するには row_ver 倉曎されたデヌタを転送するには、シヌケンス倀をこの列のフィヌルドにバむンドする必芁がありたす row_ver。 ただし、䞻キヌずは異なり、列フィヌルドの倀は row_ver 新しいレコヌドを远加するずきだけでなく、既存のレコヌドを倉曎するずきにも XNUMX ず぀増やす必芁がありたす。 これにはトリガヌを䜿甚できたす。 Tarantool には XNUMX 皮類のスペヌス トリガヌがありたす。 before_replace О on_replace。 スペヌス内のデヌタが倉曎されるたびにトリガヌが起動されたす (倉曎の圱響を受けるタプルごずに、トリガヌ関数が起動されたす)。 ずは異なり on_replace, before_replace-triggers を䜿甚するず、トリガヌが実行されるタプルのデヌタを倉曎できたす。 したがっお、最埌のタむプのトリガヌが私たちに適しおいたす。

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

次のトリガヌはフィヌルド倀を眮き換えたす row_ver 栌玍されたタプルをシヌケンスの次の倀に倉換する row_version.

宇宙からデヌタを抜出できるようにするために goods 列ごず row_ver、むンデックスを䜜成したしょう。

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

むンデックス タむプ - ツリヌ (TREE、 なぜなら列の倀の昇順でデヌタを抜出する必芁がありたす row_ver.

スペヌスにデヌタを远加しおみたしょう。

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}

なぜなら最初のフィヌルドは自動むンクリメントするカりンタヌで、代わりに nil を枡したす。 Tarantool は次の倀を自動的に眮き換えたす。 同様に、列フィヌルドの倀ずしお row_ver nil を枡すこずも、倀をたったく指定しないこずもできたす。 この列はスペヌスの最埌の䜍眮を占めたす。

挿入結果を確認しおみたしょう。

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

ご芧のずおり、最初ず最埌のフィヌルドは自動的に入力されたす。 スペヌスの倉曎をペヌゞごずにアップロヌドする関数を簡単に䜜成できるようになりたした。 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

関数はパラメヌタずしお倀を受け取りたす row_ver、そこから倉曎をアンロヌドする必芁があり、倉曎されたデヌタの䞀郚を返したす。

Tarantool でのデヌタ サンプリングはむンデックスを通じお行われたす。 関数 get_goods むンデックスによるむテレヌタを䜿甚したす row_ver 倉曎されたデヌタを受信したす。 むテレヌタのタむプは GT (Greater Than、より倧きい) です。 これは、むテレヌタが枡されたキヌフィヌルド倀から始たるむンデックス倀を順番に走査するこずを意味したす。 row_ver).

むテレヌタはタプルを返したす。 その埌 HTTP 経由でデヌタを転送できるようにするには、タプルをその埌のシリアル化に䟿利な構造に倉換する必芁がありたす。 この䟋では、これに暙準関数を䜿甚したす。 tomap。 䜿甚する代わりに tomap 独自の関数を䜜成できたす。 たずえば、フィヌルドの名前を倉曎したい堎合がありたす。 name、フィヌルドを通過しないでください code そしおフィヌルドを远加したす 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

出力デヌタのペヌゞ サむズ (XNUMX ぀の郚分のレコヌド数) は倉数によっお決たりたす。 page_size。 この䟋では、倀は page_size 実際のプログラムでは、通垞はペヌゞ サむズの方が重芁です。 それは空間タプルの平均サむズによっお異なりたす。 最適なペヌゞ サむズは、デヌタ転送時間を枬定するこずで経隓的に決定できたす。 ペヌゞサむズが倧きいほど、送信偎ず受信偎の間の埀埩回数は少なくなりたす。 こうするこずで、倉曎をダりンロヌドする党䜓の時間を短瞮できたす。 ただし、ペヌゞ サむズが倧きすぎるず、サヌバヌでのサンプルのシリアル化に時間がかかりすぎたす。 その結果、サヌバヌに送信される他のリク゚ストの凊理に遅延が発生する可胜性がありたす。 パラメヌタ page_size 蚭定ファむルから読み蟌むこずができたす。 送信されるスペヌスごずに、独自の倀を蚭定できたす。 ただし、ほずんどのスペヌスでは、デフォルト倀 (100 など) が適切な堎合がありたす。

関数を実行しおみたしょう 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
...

フィヌルド倀を取埗したしょう row_ver 最埌の行から関数を再床呌び出したす。

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

そしおたた

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

ご芧のずおり、このように䜿甚するず、関数はすべおのスペヌス レコヌドをペヌゞごずに返したす。 goods。 最埌のペヌゞの埌には空の遞択範囲が続きたす。

スペヌスに倉曎を加えおみたしょう。

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

フィヌルド倀を倉曎したした name XNUMX ぀の゚ントリに加え、XNUMX ぀の新しい゚ントリを远加したした。

最埌の関数呌び出しを繰り返しおみたしょう。

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

この関数は、倉曎および远加されたレコヌドを返したした。 したがっお、関数は get_goods を䜿甚するず、最埌の呌び出し以降に倉曎されたデヌタを受信できたす。これが、怜蚎䞭のレプリケヌション方法の基瀎ずなりたす。

JSON 圢匏での HTTP 経由の結果の発行に぀いおは、この蚘事の範囲倖ずしおおきたす。 これに぀いおはここで読むこずができたす: https://habr.com/ru/company/mailru/blog/272141/

クラむアント/スレヌブ郚分の実装

受信偎の実装がどのようなものかを芋おみたしょう。 ダりンロヌドしたデヌタを保存するためのスペヌスを受信偎に䜜成したしょう。

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

空間の構造は、゜ヌス内の空間の構造に䌌おいたす。 ただし、受信したデヌタを他の堎所に枡す぀もりはないので、列 row_ver 受信者のスペヌスにありたせん。 フィヌルド内 id ゜ヌス識別子が蚘録されたす。 したがっお、受信偎では自動むンクリメントする必芁はありたせん。

さらに、倀を保存するためのスペヌスが必芁です 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
})

ロヌドされたスペヌスごずに (フィヌルド space_name) 最埌にロヌドされた倀をここに保存したす row_ver 分野 value。 列は䞻キヌずしお機胜したす space_name.

空間デヌタを読み蟌む関数を䜜っおみたしょう goods HTTP経由で。 これを行うには、HTTP クラむアントを実装するラむブラリが必芁です。 次の行はラむブラリをロヌドし、HTTP クラむアントをむンスタンス化したす。

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

json デシリアラむれヌション甚のラむブラリも必芁です。

local json = require('json')

デヌタ読み蟌み関数を䜜成するにはこれで十分です。

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

この関数は、URL アドレスに察しお HTTP リク゚ストを実行し、送信したす。 row_ver をパラメヌタずしお受け取り、リク゚ストの逆シリアル化された結果を返したす。

受信したデヌタを保存する関数は次のようになりたす。

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

デヌタをスペヌスに保存するサむクル goods トランザクションに配眮されたす (関数はこのために䜿甚されたす) box.atomic) ディスク操䜜の数を枛らしたす。

最埌に、ロヌカル空間同期機胜 goods ゜ヌスを䜿甚するず、次のように実装できたす。

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

たず、以前に保存した倀を読み取りたす row_ver 宇宙甚 goods。 それが欠萜しおいる堎合 (最初の亀換セッション)、次のようにみなしたす。 row_ver れロ。 サむクルの次は、指定された URL の゜ヌスから倉曎されたデヌタをペヌゞごずにダりンロヌドしたす。 各反埩で、受信したデヌタを適切なロヌカル空間に保存し、倀を曎新したす。 row_ver 宇宙で row_ver そしお倉数の䞭で row_ver) - 倀を取埗したす row_ver ロヌドされたデヌタの最埌の行から。

偶発的なルヌプ (プログラム内で゚ラヌが発生した堎合) を防ぐために、ルヌプ while ず眮き換えるこずができたす for:

for _ = 1, max_req do ...

関数を実行した結果、 sync_goods 空間 goods 受信機にはすべおのスペヌス レコヌドの最新バヌゞョンが含たれたす。 goods ゜ヌスで。

明らかに、デヌタの削陀をこの方法でブロヌドキャストするこずはできたせん。 そのような必芁がある堎合は、削陀マヌクを䜿甚できたす。 スペヌスに远加する goods ブヌルフィヌルド is_deleted レコヌドを物理的に削陀する代わりに、論理的な削陀を䜿甚したす。フィヌルド倀を蚭定したす。 is_deleted 意味に true。 堎合によっおはブヌルフィヌルドの代わりに is_deleted フィヌルドを䜿甚する方が䟿利です deleted、レコヌドの論理削陀の日時が栌玍されたす。 論理削陀を実行するず、削陀察象ずしおマヌクされたレコヌドが゜ヌスから宛先に転送されたす (䞊蚘のロゞックに埓っお)。

シヌケンス row_ver 他のスペヌスからデヌタを送信するために䜿甚できたす。送信されるスペヌスごずに個別のシヌケンスを䜜成する必芁はありたせん。

Tarantool DBMS を䜿甚しおアプリケヌションで高レベルのデヌタ レプリケヌションを行う効果的な方法を怜蚎したした。

所芋

  1. Tarantool DBMS は、高負荷アプリケヌションを䜜成するための魅力的で有望な補品です。
  2. 高レベルのデヌタ レプリケヌションには、䜎レベルのレプリケヌションに比べお倚くの利点がありたす。
  3. この蚘事で説明されおいる高レベルのレプリケヌション方法を䜿甚するず、最埌の亀換セッション以降に倉曎されたレコヌドのみを転送するこずで、転送されるデヌタの量を最小限に抑えるこずができたす。

出所 habr.com

コメントを远加したす