Tarantool DBMS ۾ اعلي سطحي نقل

هيلو، مان ڊي بي ايم ايس لاءِ ايپليڪيشن ٺاهي رهيو آهيان ترنتول هڪ پليٽ فارم آهي جيڪو Mail.ru گروپ پاران تيار ڪيو ويو آهي جيڪو هڪ اعلي ڪارڪردگي DBMS ۽ Lua ٻولي ۾ ايپليڪيشن سرور کي گڏ ڪري ٿو. Tarantool جي بنياد تي حل جي تيز رفتار حاصل ڪئي وئي آهي، خاص طور تي، DBMS جي ان-ميموري موڊ جي حمايت ۽ ڊيٽا سان گڏ هڪ واحد پتي جي جڳهه ۾ ايپليڪيشن ڪاروباري منطق کي عمل ڪرڻ جي صلاحيت جي ڪري. ساڳئي وقت، ڊيٽا جي تسلسل کي يقيني بڻايو وڃي ٿو ACID ٽرانزيڪشن استعمال ڪندي (هڪ WAL لاگ ڊسڪ تي رکيل آهي). Tarantool ۾ نقل ۽ شارڊنگ لاءِ بلٽ ان سپورٽ آهي. ورجن 2.1 کان شروع ڪندي، SQL ٻولي ۾ سوالن جي مدد ڪئي وئي آھي. Tarantool کليل ذريعو آهي ۽ آسان ٿيل BSD لائسنس تحت لائسنس يافته آهي. اتي پڻ ھڪڙو تجارتي انٽرنيشنل ورزن آھي.

Tarantool DBMS ۾ اعلي سطحي نقل
طاقت محسوس ڪريو! (...اڪا ڪارڪردگي جو مزو وٺو)

مٿين سڀني کي Tarantool ٺاهيندو آهي هڪ پرڪشش پليٽ فارم ٺاهڻ لاءِ هاءِ لوڊ ايپليڪيشنون جيڪي ڊيٽابيس سان ڪم ڪن ٿيون. اهڙين ايپليڪيشنن ۾، اڪثر ڪري ڊيٽا جي نقل جي ضرورت هوندي آهي.

جيئن مٿي ذڪر ڪيو ويو آهي، Tarantool ۾ ڊيٽا جي نقل ٺاهي وئي آهي. هن جي آپريشن جو اصول آهي ته ترتيبوار طور تي سڀني ٽرانزيڪشن کي نقل ڪرڻ تي عمل ڪيو وڃي جيڪو ماسٽر لاگ (WAL) ۾ موجود آهي. عام طور تي اهڙي نقل (اسان ان کي وڌيڪ سڏينداسين گھٽ سطح) استعمال ڪيو ويندو آهي ايپليڪيشن جي غلطي رواداري کي يقيني بڻائڻ ۽ / يا ڪلستر نوڊس جي وچ ۾ پڙهڻ واري لوڊ کي ورهائڻ لاء.

Tarantool DBMS ۾ اعلي سطحي نقل
چانور. 1. ڪلستر جي اندر نقل

هڪ متبادل منظر جو هڪ مثال هڪ ڊيٽابيس ۾ ٺاهيل ڊيٽا کي پروسيسنگ / مانيٽرنگ لاءِ ٻئي ڊيٽابيس ۾ منتقل ڪري رهيو آهي. پوئين صورت ۾، هڪ وڌيڪ آسان حل استعمال ڪري سگهجي ٿو اعليٰ سطح نقل - ايپليڪيشن ڪاروباري منطق جي سطح تي ڊيٽا جي نقل. اهي. اسان ڊي بي ايم ايس ۾ ٺهيل تيار ٿيل حل استعمال نٿا ڪريون، پر اسان جي ترقي يافته ايپليڪيشن جي اندر پاڻ تي نقل لاڳو ڪريو. اهو طريقو ٻنهي فائدن ۽ نقصانات آهي. اچو ته فائدن جي فهرست ڏيو.

1. ٽرئفڪ جي بچت:

  • توهان سڀني ڊيٽا کي منتقلي نٿا ڪري سگهو، پر صرف ان جو حصو (مثال طور، توهان صرف ڪجهه جدولن کي منتقل ڪري سگهو ٿا، انهن مان ڪجهه ڪالمن يا رڪارڊ جيڪي هڪ خاص معيار سان ملن ٿا)؛
  • گھٽ-سطح جي نقل جي برعڪس، جيڪا مسلسل اسيئنڪرونس (Tarantool جي موجوده ورزن ۾ لاڳو ٿيل آهي - 1.10) يا هم وقت ساز (Tarantool جي ايندڙ ورزن ۾ لاڳو ٿيڻ لاءِ) موڊ ۾، اعليٰ سطحي نقل سيشن ۾ ڪري سگهجي ٿي (يعني، ايپليڪيشن پهريون ڀيرو ڊيٽا کي هم وقت سازي ڪري ٿو - هڪ مٽائي سيشن ڊيٽا، پوء نقل ۾ هڪ وقفو آهي، جنهن کان پوء ايندڙ تبادلي جو سيشن ٿئي ٿو، وغيره؛
  • جيڪڏهن هڪ رڪارڊ ڪيترائي ڀيرا تبديل ٿي چڪو آهي، توهان صرف ان جو جديد نسخو منتقل ڪري سگهو ٿا (گهٽ-سطح جي نقل جي برعڪس، جنهن ۾ ماسٽر تي ڪيل سڀني تبديلين کي ترتيب سان ٻيهر نقل ڪيو ويندو).

2. HTTP ايڪسچينج کي لاڳو ڪرڻ ۾ ڪا به مشڪلات نه آهي، جيڪا توهان کي ريموٽ ڊيٽابيس کي هم وقت سازي ڪرڻ جي اجازت ڏئي ٿي.

Tarantool DBMS ۾ اعلي سطحي نقل
چانور. 2. HTTP تي نقل

3. ڊيٽابيس جي جوڙجڪ جن جي وچ ۾ ڊيٽا کي منتقل ڪيو وڃي ٿو ساڳيو نه هجڻ گهرجي (وڌيڪ، عام صورت ۾، اهو ممڪن آهي ته مختلف DBMSs، پروگرامنگ ٻوليون، پليٽ فارم، وغيره استعمال ڪرڻ).

Tarantool DBMS ۾ اعلي سطحي نقل
چانور. 3. متفاوت سسٽم ۾ نقل

نقصان اهو آهي ته، سراسري طور تي، پروگرامنگ ترتيب کان وڌيڪ ڏکيو / قيمتي آهي، ۽ بلٽ ان ڪارڪردگي کي ترتيب ڏيڻ جي بدران، توهان کي پنهنجو پاڻ تي عمل ڪرڻو پوندو.

جيڪڏهن توهان جي صورتحال ۾ مٿين فائدن اهم آهن (يا هڪ ضروري شرط آهي)، پوء اهو اعلي سطحي نقل استعمال ڪرڻ جو مطلب آهي. اچو ته Tarantool DBMS ۾ اعلي سطحي ڊيٽا جي نقل کي لاڳو ڪرڻ جا ڪيترائي طريقا ڏسو.

ٽرئفڪ جي گھٽتائي

تنهن ڪري، اعلي سطحي نقل جي فائدن مان هڪ آهي ٽرئفڪ جي بچت. هن فائدي لاء مڪمل طور تي محسوس ڪيو وڃي، اهو ضروري آهي ته هر مٽائي سيشن دوران منتقل ڪيل ڊيٽا جي مقدار کي گھٽائڻ لاء. يقينن، اسان کي اهو نه وسارڻ گهرجي ته سيشن جي آخر ۾، ڊيٽا وصول ڪندڙ کي ماخذ سان هم وقت سازي ڪرڻ گهرجي (گهٽ ۾ گهٽ ڊيٽا جي انهي حصي لاء جيڪو نقل ۾ شامل آهي).

اعلي سطحي نقل جي دوران منتقل ٿيل ڊيٽا جي مقدار کي ڪيئن گھٽائڻ؟ ھڪڙو سڌو حل ٿي سگھي ٿو تاريخ ۽ وقت جي لحاظ کان ڊيٽا کي چونڊيو. ھن کي ڪرڻ لاء، توھان استعمال ڪري سگھوٿا تاريخ جي وقت واري فيلڊ اڳ ۾ ئي موجود جدول ۾ (جيڪڏھن اھو موجود آھي). مثال طور، هڪ "آرڊر" دستاويز ۾ هڪ فيلڊ ٿي سگهي ٿي "گهربل آرڊر تي عملدرآمد جو وقت" - delivery_time. هن حل سان مسئلو اهو آهي ته هن فيلڊ ۾ قيمتون ترتيب ۾ نه هجن جيڪي آرڊر جي تخليق سان ملن ٿيون. تنهنڪري اسان کي ياد نه ٿا ڪري سگهون وڌ ۾ وڌ فيلڊ جي قيمت delivery_time, منتقل ڪيو ويو پوئين ايڪسچينج سيشن دوران، ۽ ايندڙ ايڪسچينج سيشن دوران سڀني رڪارڊ کي اعلي فيلڊ جي قيمت سان چونڊيو delivery_time. گھٽ فيلڊ جي قيمت سان رڪارڊ شايد مٽائي سيشن جي وچ ۾ شامل ڪيا ويا آھن delivery_time. انهي سان گڏ، آرڊر تبديل ٿي سگهي ٿي، جنهن جي باوجود فيلڊ تي اثر انداز نه ڪيو delivery_time. ٻنهي صورتن ۾، تبديلين کي ماخذ کان منزل ڏانهن منتقل نه ڪيو ويندو. انهن مسئلن کي حل ڪرڻ لاء، اسان کي ڊيٽا "اوورليپنگ" کي ​​منتقل ڪرڻ جي ضرورت پوندي. اهي. هر مٽا سٽا واري سيشن ۾ اسان سڀني ڊيٽا کي فيلڊ جي قيمت سان منتقل ڪنداسين delivery_time، ماضي ۾ ڪجهه نقطي کان وڌيڪ (مثال طور، موجوده لمحن کان N ڪلاڪ). بهرحال، اهو ظاهر آهي ته وڏي سسٽم لاء اهو طريقو انتهائي بيڪار آهي ۽ ٽرئفڪ جي بچت کي گهٽائي سگھي ٿو جيڪو اسان ڪجھ به نه ڪرڻ جي ڪوشش ڪري رهيا آهيون. ان کان علاوه، ٽيبل جي منتقلي ٿي سگھي ٿي شايد ڪو فيلڊ نه هجي جيڪو تاريخ جي وقت سان لاڳاپيل هجي.

ٻيو حل، عمل درآمد جي لحاظ کان وڌيڪ پيچيده، ڊيٽا جي وصولي کي تسليم ڪرڻ آهي. انهي صورت ۾، هر بدلي سيشن دوران، سڀني ڊيٽا کي منتقل ڪيو ويندو آهي، جنهن جي وصولي جي تصديق نه ڪئي وئي آهي وصول ڪندڙ طرفان. ھن کي لاڳو ڪرڻ لاءِ، توھان کي ماخذ جدول ۾ ھڪڙو بوليان ڪالم شامل ڪرڻو پوندو (مثال طور، is_transferred). جيڪڏهن وصول ڪندڙ رڪارڊ جي وصولي کي تسليم ڪري ٿو، لاڳاپيل فيلڊ قيمت وٺندو آهي true، جنهن کان پوءِ داخلا تبادلي ۾ شامل ناهي. ھن عمل درآمد اختيار ۾ ھيٺيون نقصان آھن. پهريون، هر رڪارڊ جي منتقلي لاء، هڪ تسليم ڪيو وڃي ۽ موڪليو وڃي. تقريبن ڳالهائڻ، هي منتقل ٿيل ڊيٽا جي مقدار کي ٻيڻو ڪرڻ ۽ گول ٽرپس جي تعداد کي ٻيڻو ڪرڻ جي مقابلي ۾ ٿي سگهي ٿو. ٻيو، ڪيترن ئي وصول ڪندڙن ڏانهن ساڳيو رڪارڊ موڪلڻ جو ڪو به امڪان ناهي (وصول ڪرڻ وارو پهريون وصول ڪندڙ پنهنجي لاءِ ۽ ٻين سڀني لاءِ رسيد جي تصديق ڪندو).

ھڪڙو طريقو جنھن ۾ مٿي ڏنل نقصان نه آھي اھو آھي ھڪڙي ڪالمن کي شامل ڪرڻ لاءِ منتقل ٿيل جدول ۾ ان جي قطارن ۾ تبديلين کي ٽريڪ ڪرڻ لاءِ. اهڙو ڪالم تاريخ جي وقت جي قسم جو ٿي سگهي ٿو ۽ لازمي طور تي ايپليڪيشن طرفان سيٽ/اپڊيٽ ڪيو وڃي موجوده وقت تي هر وقت رڪارڊ شامل/تبديل ڪيو وڃي (جوهر ۾ اضافو/تبديل سان). مثال طور، اچو ته ڪالمن کي سڏين update_time. منتقل ٿيل رڪارڊز لاءِ هن ڪالمن جي وڌ ۾ وڌ فيلڊ ويليو کي محفوظ ڪرڻ سان، اسان ان قيمت سان ايندڙ ايڪسچينج سيشن شروع ڪري سگھون ٿا (فيلڊ ويليو سان رڪارڊ چونڊيو update_time، اڳئين ذخيرو ڪيل قدر کان وڌيڪ). پوئين طريقي سان مسئلو اهو آهي ته ڊيٽا تبديليون بيچ ۾ ٿي سگهن ٿيون. ڪالمن ۾ فيلڊ جي قدرن جي نتيجي ۾ update_time منفرد نه ٿي سگهي. اهڙيءَ طرح، هي ڪالم استعمال نه ٿو ڪري سگهجي پارشن ٿيل (صفحو-جي-صفحو) ڊيٽا جي پيداوار لاءِ. صفحي ذريعي ڊيٽا صفحي کي ڊسپلي ڪرڻ لاء، توهان کي اضافي ميڪانيزم کي ايجاد ڪرڻو پوندو جيڪو گهڻو ڪري تمام گهٽ ڪارڪردگي وارو هوندو (مثال طور، ڊيٽابيس مان ٻيهر حاصل ڪرڻ سان گڏ سڀني رڪارڊن کي قيمت سان. update_time ڏنل هڪ کان وڌيڪ ۽ رڪارڊ جو هڪ خاص تعداد پيدا ڪرڻ، نموني جي شروعات کان هڪ خاص آفسٽ کان شروع ٿئي ٿو).

توھان اڳئين طريقي کي ٿورو بهتر ڪندي ڊيٽا جي منتقلي جي ڪارڪردگي کي بهتر ڪري سگھو ٿا. هن کي ڪرڻ لاءِ، اسان انٽيجر قسم (ڊگهي انٽيجر) کي استعمال ڪنداسين ڪالمن فيلڊ ويلز جي طور تي تبديلين کي ٽريڪ ڪرڻ لاءِ. اچو ته ڪالم جو نالو ڏيو row_ver. ھن ڪالمن جي فيلڊ جي قيمت اڃا تائين مقرر / تازه ڪاري ٿيڻ گھرجي ھر دفعي رڪارڊ ٺاھيو / تبديل ڪيو وڃي. پر هن حالت ۾، فيلڊ کي موجوده تاريخ جي وقت مقرر نه ڪيو ويندو، پر ڪجهه انسداد جي قيمت، هڪ کان وڌي وئي. نتيجي طور، ڪالمن row_ver منفرد قدرن تي مشتمل هوندو ۽ استعمال ڪري سگھجي ٿو نه رڳو ”ڊيلٽا“ ڊيٽا کي ڏيکارڻ لاءِ (ڊيٽا شامل ڪئي وئي/بدلجي وئي پوئين مٽاسٽا واري سيشن جي آخر کان)، پر ان کي آسان ۽ مؤثر طريقي سان صفحن ۾ ورهائڻ لاءِ.

آخري تجويز ڪيل طريقي سان گھٽ ۾ گھٽ ڊيٽا جي مقدار کي گھٽائڻ جي فريم ورڪ ۾ اعلي سطحي نقل جي فريم ورڪ ۾، مون کي تمام بھترين ۽ آفاقي لڳي ٿو. اچو ته ان کي وڌيڪ تفصيل سان ڏسو.

قطار ورزن ڪاؤنٽر استعمال ڪندي ڊيٽا کي پاس ڪرڻ

سرور / ماسٽر حصو جو نفاذ

MS SQL سرور ۾، ھن طريقي کي لاڳو ڪرڻ لاء ھڪڙو خاص ڪالمن جو قسم آھي - rowversion. هر ڊيٽابيس ۾ هڪ ڪائونٽر هوندو آهي جيڪو هر دفعي هڪ کان وڌي ويندو آهي جڏهن هڪ ٽيبل ۾ رڪارڊ شامل ڪيو ويندو/تبديل ڪيو ويندو آهي جنهن ۾ هڪ ڪالم هوندو آهي. 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 نه رڳو نوان رڪارڊ شامل ڪرڻ وقت، پر موجوده رڪارڊ کي تبديل ڪرڻ وقت پڻ. توھان استعمال ڪري سگھوٿا ھن لاءِ ٽريگرز. Tarantool ۾ ٻن قسمن جا خلائي محرڪ آھن: 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 تبديل ٿيل ڊيٽا حاصل ڪرڻ لاء. Iterator جو قسم GT آهي (وڏي کان وڏو، کان وڏو). ان جو مطلب اهو آهي ته آئٽرٽر ترتيب سان انڊيڪس ويلز کي منتقل ڪندو جيڪو پاس ڪيل ڪيئي (فيلڊ ويل 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

آئوٽ پٽ ڊيٽا جي صفحي جي سائيز (هڪ حصي ۾ رڪارڊ جو تعداد) متغير طرفان طئي ڪيو ويندو آهي page_size. مثال ۾ قدر page_size آهي 5. هڪ حقيقي پروگرام ۾، صفحي جي سائيز عام طور تي وڌيڪ اهميت رکي ٿي. اهو خلائي ٽوپل جي اوسط سائيز تي منحصر آهي. ڊيٽا جي منتقلي جي وقت کي ماپڻ سان بهترين صفحي جي سائيز کي تجرباتي طور تي طئي ڪري سگهجي ٿو. صفحي جي سائيز جيتري وڏي هوندي، موڪلڻ ۽ وصول ڪرڻ وارن پاسن جي وچ ۾ گول ٽرپ جو تعداد اوترو ئي ننڍو هوندو. هن طريقي سان توهان تبديلين کي ڊائون لوڊ ڪرڻ لاء مجموعي وقت گھٽائي سگهو ٿا. بهرحال، جيڪڏهن صفحي جي سائيز تمام وڏي آهي، اسان نموني کي ترتيب ڏيڻ سرور تي تمام ڊگهو خرچ ڪنداسين. نتيجي طور، سرور تي اچڻ واري ٻين درخواستن جي پروسيسنگ ۾ دير ٿي سگھي ٿي. پيرا ميٽر page_size configuration فائل مان لوڊ ڪري سگھجي ٿو. هر منتقل ٿيل جڳهه لاء، توهان پنهنجي قيمت مقرر ڪري سگهو ٿا. بهرحال، اڪثر هنڌن لاءِ ڊفالٽ قدر (مثال طور، 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 هڪ داخلا لاءِ ۽ ٻه نيون داخلائون شامل ڪيون ويون.

اچو ته آخري فنڪشن ڪال کي ورجائي:

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 deserialization لاءِ به هڪ لائبريري جي ضرورت آهي:

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 ٻُڙي. اڳيون چڪر ۾ اسين ترتيب ڏنل يو آر ايل تي ذريعن کان تبديل ٿيل ڊيٽا جي صفحي جي صفحي تي ڊائون لوڊ ڪندا آهيون. هر ورهاڱي تي، اسان وصول ڪيل ڊيٽا کي مناسب مقامي جاء تي محفوظ ڪيو ۽ قيمت کي اپڊيٽ ڪيو row_ver (خلا ۾ row_ver ۽ variable ۾ row_ver) - قدر وٺو row_ver لوڊ ٿيل ڊيٽا جي آخري لائين کان.

حادثاتي لوپنگ کان بچائڻ لاءِ (پروگرام ۾ غلطي جي صورت ۾)، لوپ while طرفان تبديل ڪري سگهجي ٿو for:

for _ = 1, max_req do ...

عمل جي عمل جي نتيجي ۾ sync_goods خلا goods وصول ڪندڙ سڀني خلائي رڪارڊ جي جديد نسخن تي مشتمل هوندو goods ذريعن ۾.

ظاهر آهي، ڊيٽا کي ختم ڪرڻ هن طريقي سان نشر نٿو ڪري سگهجي. جيڪڏهن اهڙي ضرورت موجود آهي، توهان استعمال ڪري سگهو ٿا حذف ڪرڻ جو نشان. خلا ۾ شامل ڪريو goods بولين فيلڊ is_deleted ۽ رڪارڊ کي جسماني طور تي حذف ڪرڻ جي بدران، اسان منطقي حذف ڪرڻ استعمال ڪندا آهيون - اسان فيلڊ جي قيمت مقرر ڪندا آهيون is_deleted معنيٰ ۾ true. ڪڏهن ڪڏهن هڪ boolean فيلڊ جي بدران is_deleted اهو ميدان استعمال ڪرڻ لاء وڌيڪ آسان آهي deleted، جيڪو رڪارڊ جي منطقي حذف ٿيڻ جي تاريخ جو وقت محفوظ ڪري ٿو. منطقي حذف ڪرڻ کان پوء، حذف ڪرڻ لاء نشان لڳل رڪارڊ ماخذ کان منزل ڏانهن منتقل ڪيو ويندو (مٿي بحث ڪيل منطق جي مطابق).

تسلسل row_ver ٻين اسپيس مان ڊيٽا منتقل ڪرڻ لاءِ استعمال ٿي سگهي ٿو: هر منتقل ٿيل جڳهه لاءِ الڳ ترتيب ٺاهڻ جي ضرورت ناهي.

اسان Tarantool DBMS استعمال ڪندي ايپليڪيشنن ۾ اعلي سطحي ڊيٽا جي نقل جو هڪ مؤثر طريقو ڏٺو.

پهچڻ

  1. Tarantool DBMS هڪ پرڪشش پراڊڪٽ آهي، پراڊڪٽ اعلي لوڊ ايپليڪيشن ٺاهڻ لاءِ.
  2. اعلي سطحي ڊيٽا جي نقل ڪرڻ ۾ گھٽ سطح جي نقل تي ڪيترائي فائدا آھن.
  3. آرٽيڪل ۾ بحث ڪيل اعلي سطحي نقل جو طريقو توهان کي صرف انهن رڪارڊن کي منتقل ڪندي منتقل ڪيل ڊيٽا جي مقدار کي گھٽائڻ جي اجازت ڏئي ٿو جيڪي آخري مٽاسٽا سيشن کان تبديل ٿي چڪا آهن.

جو ذريعو: www.habr.com

تبصرو شامل ڪريو