Tarantool DBMS හි ඉහළ මට්ටමේ අනුකරණය

හෙලෝ, මම DBMS සඳහා යෙදුම් නිර්මාණය කරමි ටැරන්ටූල් Mail.ru සමූහය විසින් වැඩි දියුණු කරන ලද වේදිකාවක් වන අතර එය ඉහළ කාර්යසාධනයක් සහිත DBMS සහ Lua භාෂාවෙන් යෙදුම් සේවාදායකයක් ඒකාබද්ධ කරයි. Tarantool මත පදනම් වූ විසඳුම්වල ඉහළ වේගය, විශේෂයෙන්ම, DBMS හි මතකයේ මාදිලිය සඳහා සහය දැක්වීම සහ දත්ත සමඟ තනි ලිපින අවකාශයක යෙදුම් ව්‍යාපාර තර්කනය ක්‍රියාත්මක කිරීමේ හැකියාව හේතුවෙන් සාක්ෂාත් කරගනු ලැබේ. ඒ සමගම, ACID ගණුදෙණු භාවිතා කරමින් දත්ත අඛණ්ඩතාව සහතික කරනු ලැබේ (තැටිය මත WAL ලොගයක් පවත්වා ගෙන යනු ලැබේ). ටැරන්ටූල් ප්‍රතිනිර්මාණය කිරීම සහ බෙදා හැරීම සඳහා සහය දක්වයි. 2.1 අනුවාදයෙන් පටන් ගෙන, SQL භාෂාවෙන් විමසුම් සඳහා සහය දක්වයි. Tarantool විවෘත මූලාශ්‍රයක් වන අතර සරල කළ BSD බලපත්‍රය යටතේ බලපත්‍ර ලබා ඇත. වාණිජ ව්යවසාය අනුවාදයක් ද ඇත.

Tarantool DBMS හි ඉහළ මට්ටමේ අනුකරණය
බලය දැනෙන්න! (…හෝ කාර්ය සාධනය භුක්ති විඳින්න)

ඉහත සියල්ලම ටැරන්ටූල් දත්ත සමුදායන් සමඟ වැඩ කරන ඉහළ බර යෙදුම් නිර්මාණය කිරීම සඳහා ආකර්ෂණීය වේදිකාවක් බවට පත් කරයි. එවැනි යෙදුම් වලදී, බොහෝ විට දත්ත අනුකරණය සඳහා අවශ්ය වේ.

ඉහත සඳහන් කළ පරිදි, ටැරන්ටූල් තුළ දත්ත අනුකරණයක් ඇත. එහි ක්‍රියාකාරිත්වයේ මූලධර්මය වන්නේ ප්‍රධාන ලොගයේ (WAL) අඩංගු සියලුම ගනුදෙනු අනුපිටපත් මත අනුක්‍රමිකව ක්‍රියාත්මක කිරීමයි. සාමාන්යයෙන් එවැනි අනුකරණයක් (අපි එය තවදුරටත් අමතන්නෙමු පහත් මට්ටමේ) යෙදුම් දෝෂ ඉවසීම සහතික කිරීමට සහ/හෝ පොකුරු නෝඩ් අතර කියවීමේ භාරය බෙදා හැරීමට භාවිතා කරයි.

Tarantool DBMS හි ඉහළ මට්ටමේ අනුකරණය
සහල්. 1. පොකුරක් තුළ අනුකරණය

විකල්ප අවස්ථාවක් සඳහා උදාහරණයක් වනුයේ එක් දත්ත ගබඩාවක සාදන ලද දත්ත සැකසීම/අධීක්ෂණය සඳහා තවත් දත්ත සමුදායකට මාරු කිරීමයි. අවසාන අවස්ථාවේ දී, වඩාත් පහසු විසඳුමක් භාවිතා කළ හැකිය ඉහළ මට්ටමේ අනුකරණය - යෙදුම් ව්‍යාපාර තාර්කික මට්ටමින් දත්ත අනුකරණය. එම. අපි DBMS තුළ ගොඩනගා ඇති සූදානම් කළ විසඳුමක් භාවිතා නොකරමු, නමුත් අප විසින් සංවර්ධනය කරන යෙදුම තුළ අපගේම අනුවර්තනය ක්රියාත්මක කරන්න. මෙම ප්රවේශය වාසි සහ අවාසි යන දෙකම ඇත. අපි වාසි ලැයිස්තුගත කරමු.

1. රථවාහන ඉතිරිකිරීම්:

  • ඔබට සියලු දත්ත මාරු කළ නොහැක, නමුත් එයින් කොටසක් පමණක් (උදාහරණයක් ලෙස, ඔබට මාරු කළ හැක්කේ සමහර වගු, ඒවායේ තීරු හෝ යම් නිර්ණායකයක් සපුරාලන වාර්තා පමණි);
  • අසමමුහුර්ත (වර්තමාන ටැරන්ටූල් - 1.10 අනුවාදයේ ක්‍රියාත්මක) හෝ සමමුහුර්ත (ටැරන්ටූල් හි පසුව අනුවාදවල ක්‍රියාත්මක කිරීමට) ප්‍රකාරයේදී අඛණ්ඩව සිදු කෙරෙන පහත මට්ටමේ ප්‍රතිනිර්මාණය මෙන් නොව, සැසිවලදී (එනම්, ද යෙදුම පළමුව දත්ත සමමුහුර්ත කරයි - හුවමාරු සැසි දත්ත, පසුව අනුකරණයේ විරාමයක් ඇත, ඉන්පසු ඊළඟ හුවමාරු සැසිය සිදු වේ, ආදිය);
  • වාර්තාවක් කිහිප වතාවක් වෙනස් වී ඇත්නම්, ඔබට එහි නවතම අනුවාදය පමණක් මාරු කළ හැකිය (පහළ මට්ටමේ අනුකරණය මෙන් නොව, ප්‍රධාන මත සිදු කරන ලද සියලුම වෙනස්කම් අනුපිළිවෙලින් අනුපිළිවෙලින් නැවත වාදනය කරනු ලැබේ).

2. දුරස්ථ දත්ත සමුදායන් සමමුහුර්ත කිරීමට ඔබට ඉඩ සලසන HTTP හුවමාරුව ක්රියාත්මක කිරීමේදී දුෂ්කරතා නොමැත.

Tarantool DBMS හි ඉහළ මට්ටමේ අනුකරණය
සහල්. 2. HTTP හරහා අනුකරණය

3. දත්ත මාරු කරන දත්ත සමුදා ව්‍යුහයන් සමාන විය යුතු නැත (එපමනක් නොව, සාමාන්‍ය අවස්ථාවෙහිදී, විවිධ DBMS, ක්‍රමලේඛන භාෂා, වේදිකා ආදිය භාවිතා කිරීමට පවා හැකිය).

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 හි කිසියම් දත්ත සමුදා මෙහෙයුමක් සිදු කිරීමට පෙර, ඔබ පහත විධානය ක්‍රියාත්මක කළ යුතුය:

box.cfg{}

එහි ප්‍රතිඵලයක් ලෙස, ටැරන්ටූල් වත්මන් නාමාවලියට දත්ත සමුදා ස්නැප්ෂොට් සහ ගණුදෙණු ලොග ලිවීම ආරම්භ කරයි.

අපි අනුපිළිවෙලක් නිර්මාණය කරමු 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 අනුපිළිවෙලෙහි ඊළඟ අගයට tuple ගබඩා කර ඇත 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, වෙනස්කම් ගොඩබෑම අවශ්‍ය වන අතර, වෙනස් කළ දත්ත වලින් කොටසක් ආපසු ලබා දෙයි.

ටැරන්ටූල් හි දත්ත නියැදීම දර්ශක හරහා සිදු කෙරේ. කාර්යය get_goods දර්ශකය අනුව පුනරාවර්තකයක් භාවිතා කරයි row_ver වෙනස් වූ දත්ත ලබා ගැනීමට. පුනරාවර්තක වර්ගය GT (Greater than, 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

ප්රතිදාන දත්තවල පිටු ප්රමාණය (එක් කොටසක වාර්තා සංඛ්යාව) විචල්යය මගින් තීරණය කරනු ලැබේ page_size. උදාහරණයේ අගය page_size යනු 5. සැබෑ වැඩසටහනකදී, පිටු ප්‍රමාණය සාමාන්‍යයෙන් වඩා වැදගත් වේ. එය අභ්යවකාශ ටියුපල් වල සාමාන්ය ප්රමාණය මත රඳා පවතී. දත්ත හුවමාරු කාලය මැනීමෙන් ප්‍රශස්ත පිටු ප්‍රමාණය ආනුභවිකව තීරණය කළ හැක. පිටු ප්‍රමාණය විශාල වන තරමට, යැවීම සහ ලැබීම යන පැති අතර වට සංචාර ගණන කුඩා වේ. මේ ආකාරයෙන් ඔබට වෙනස්කම් බාගත කිරීමේ සමස්ත කාලය අඩු කළ හැකිය. කෙසේ වෙතත්, පිටු ප්‍රමාණය ඉතා විශාල නම්, අපි නියැදිය අනුක්‍රමික කිරීමට සේවාදායකයේ වැඩි කාලයක් ගත කරන්නෙමු. එහි ප්‍රතිඵලයක් ලෙස, සේවාදායකය වෙත එන අනෙකුත් ඉල්ලීම් සැකසීමේ ප්‍රමාදයන් ඇති විය හැක. පරාමිතිය 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 එක් ප්‍රවේශයක් සඳහා සහ නව ඇතුළත් කිරීම් දෙකක් එකතු කරන ලදී.

අපි අවසාන ක්‍රියාකාරී ඇමතුම නැවත කියමු:

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 පරාමිතියක් ලෙස සහ ඉල්ලීමේ deserialized ප්රතිඵලය ලබා දෙයි.

ලැබුණු දත්ත සුරැකීමේ කාර්යය මේ ආකාරයෙන් පෙනේ:

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

මුලින්ම අපි කලින් save කරපු අගය කියවමු 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. ලිපියේ සාකච්ඡා කර ඇති ඉහළ මට්ටමේ අනුවර්තන ක්‍රමය මඟින් පසුගිය හුවමාරු සැසියේ සිට වෙනස් වූ වාර්තා පමණක් මාරු කිරීමෙන් මාරු කළ දත්ත ප්‍රමාණය අවම කිරීමට ඔබට ඉඩ සලසයි.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න