Redis භාවිතයෙන් බෙදා හරින ලද අගුලු දැමීම

හෙලෝ, හබ්ර්!

අද අපි ඔබේ අවධානයට ගෙන එන්නේ රෙඩිස් භාවිතයෙන් බෙදා හරින ලද අගුලු දැමීම ක්‍රියාත්මක කිරීම පිළිබඳ සංකීර්ණ ලිපියක පරිවර්තනයක් වන අතර මාතෘකාවක් ලෙස රෙඩිස්ගේ අපේක්ෂාවන් ගැන කතා කිරීමට ඔබට ආරාධනා කරන්නෙමු. "" පොතේ කතුවරයා වන මාර්ටින් ක්ලෙප්මන් වෙතින් ප්‍රශ්නගත රෙඩ්ලොක් ඇල්ගොරිතමයේ විශ්ලේෂණයඅධි බර යෙදුම්", දී ඇත මෙහි.

බෙදා හරින ලද අගුලු දැමීම බොහෝ පරිසරවල භාවිතා වන ඉතා ප්‍රයෝජනවත් ප්‍රාථමිකයක් වන අතර එහිදී විවිධ ක්‍රියාවලීන් බෙදාගත් සම්පත් මත අන්‍යෝන්‍ය වශයෙන් බැහැර ආකාරයකින් ක්‍රියා කළ යුතුය.

Redis භාවිතයෙන් DLM (Distributed Lock Manager) ක්‍රියාවට නංවන ආකාරය විස්තර කරන පුස්තකාල සහ පළ කිරීම් ගණනාවක් තිබේ, නමුත් සෑම පුස්තකාලයක්ම වෙනස් ප්‍රවේශයක් ගන්නා අතර ඒවා සපයන සහතික තරමක් සංකීර්ණ නිර්මාණයකින් ලබා ගත හැකි දේට සාපේක්ෂව තරමක් දුර්වල ය.

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

ක්රියාත්මක කිරීම

ඇල්ගොරිතමයේ විස්තරය වෙත යාමට පෙර, අපි සූදානම් කළ ක්රියාත්මක කිරීම් සඳහා සබැඳි කිහිපයක් ලබා දෙන්නෙමු. ඒවා යොමු කිරීම සඳහා භාවිතා කළ හැකිය.

  • Redlock-rb (රූබි සඳහා ක්රියාත්මක කිරීම). ද ඇත දෙබලක බෙදා හැරීමේ පහසුව සඳහා පැකේජයක් (මැණික්) එකතු කරන Redlock-rb, සහ ඒ සඳහා පමණක් නොවේ.
  • Redlock-py (පයිතන් ක්‍රියාත්මක කිරීම).
  • Aioredlock (Asyncio Python සඳහා ක්‍රියාත්මක කිරීම).
  • Redlock-php (PHP සඳහා ක්‍රියාත්මක කිරීම).
  • PHPRedisMutex (PHP සඳහා තවත් ක්‍රියාත්මක කිරීමක්)
  • cheprasov/php-redis-lock (අගුළු සඳහා PHP පුස්තකාලය)
  • Redsync (Go සඳහා ක්රියාත්මක කිරීම).
  • රෙඩිසන් (ජාවා සඳහා ක්රියාත්මක කිරීම).
  • Redis::DistLock (Perl සඳහා ක්රියාත්මක කිරීම).
  • Redlock-cpp (C++ සඳහා ක්‍රියාත්මක කිරීම).
  • Redlock-cs (C#/.NET සඳහා ක්‍රියාත්මක කිරීම).
  • RedLock.net (C#/.NET සඳහා ක්‍රියාත්මක කිරීම). Async සහ lock extensions සඳහා සහය ඇතිව.
  • ScarletLock (වින්‍යාසගත කළ හැකි දත්ත ගබඩාවක් සහිත C# .NET සඳහා ක්‍රියාත්මක කිරීම)
  • Redlock4Net (C# .NET සඳහා ක්‍රියාත්මක කිරීම)
  • node-redlock (NodeJS සඳහා ක්‍රියාත්මක කිරීම). අගුල් දිගු කිරීම සඳහා ආධාරකයක් ඇතුළත් වේ.

ආරක්ෂාව සහ ලබා ගත හැකි සහතික

බෙදා හරින ලද අගුලු දැමීම ඵලදායි ලෙස භාවිතා කිරීමට අවශ්‍ය අවම සහතික ලබා දෙන බව අප සිතන ගුණාංග තුනකින් පමණක් අපගේ සැලසුම ආදර්ශයට ගැනීමට අපි යන්නෙමු.

  1. ආරක්ෂක දේපල: අන්යෝන්ය බැහැර කිරීම. ඕනෑම අවස්ථාවක, අගුල තබා ගත හැක්කේ එක් සේවාදායකයෙකුට පමණි.
  2. ලබා ගත හැකි දේපල A: අවහිරතා නොමැත. සම්පත අගුලු දැමූ සේවාදායකයා අසමත් වුවහොත් හෝ වෙනත් තැටි කොටසකට ගොඩ බැස්සද අවසානයේ අගුලක් ලබා ගැනීමට සැමවිටම හැකි වේ.
  3. ලබා ගත හැකි දේපල B: වැරදි ඉවසීම. රෙඩිස් නෝඩ් බහුතරයක් ක්‍රියාත්මක වන තාක්, සේවාලාභීන්ට අගුලු ලබා ගැනීමට සහ මුදා හැරීමට හැකි වේ.

අසාර්ථක ප්රතිසාධනය මත පදනම්ව ක්රියාත්මක කිරීම මෙම නඩුවේ ප්රමාණවත් නොවේ ඇයි
අප වැඩි දියුණු කිරීමට යන්නේ කුමක්ද යන්න තේරුම් ගැනීමට, Redis මත පදනම් වූ බොහෝ බෙදා හරින ලද අගුලු දැමීමේ පුස්තකාල සමඟ වත්මන් තත්ත්වය විශ්ලේෂණය කරමු.

Redis භාවිතයෙන් සම්පතක් අගුළු දැමීමේ සරලම ක්‍රමය නම් යතුරක් සෑදීමයි. සාමාන්‍යයෙන්, යතුරක් නිර්මාණය කර ඇත්තේ සීමිත ආයු කාලයක් සමඟින්, මෙය ලබා ගන්නේ Redis හි සපයා ඇති කල් ඉකුත් වීමේ විශේෂාංගය භාවිතයෙන්, එබැවින් ඉක්මනින් හෝ පසුව මෙම යතුර මුදා හරිනු ලැබේ (අපගේ ලැයිස්තුවේ දේපල 2). සේවාදායකයාට සම්පත මුදා හැරීමට අවශ්‍ය වූ විට, එය යතුර මකා දමයි.

මුලින්ම බැලූ බැල්මට, මෙම විසඳුම තරමක් හොඳින් ක්රියා කරයි, නමුත් ගැටළුවක් තිබේ: අපගේ ගෘහ නිර්මාණ ශිල්පය අසාර්ථක වීමේ තනි ලක්ෂ්යයක් නිර්මාණය කරයි. සත්කාරක රෙඩිස් අවස්ථාව අසාර්ථක වුවහොත් කුමක් සිදුවේද? අපි වහලෙක් එකතු කරමු එහෙනම්! ඉදිරිපත් කරන්නා නොමැති නම් අපි එය භාවිතා කරන්නෙමු. අවාසනාවකට මෙන්, මෙම විකල්පය ශක්ය නොවේ. මෙය කිරීමෙන්, අපට ආරක්ෂාව සහතික කිරීමට අවශ්‍ය අන්‍යෝන්‍ය බැහැර කිරීමේ දේපල නිසි ලෙස ක්‍රියාත්මක කිරීමට නොහැකි වනු ඇත, මන්ද Redis හි අනුකරණය අසමමිතික වේ.

නිසැකවම, එවැනි ආකෘතියක් තුළ ධාවන තත්වයක් ඇතිවේ:

  1. A සේවාදායකයා මාස්ටර් මත අගුලක් ලබා ගනී.
  2. ප්රධාන ඇතුල්වීම වහලා වෙත මාරු කිරීමට පෙර ස්වාමියා අසමත් වේ.
  3. අනුගාමිකයා නායකයා ලෙස උසස් කරනු ලැබේ.
  4. A විසින් දැනටමත් අගුලු දමා ඇති සම්පතෙහිම B Client විසින් අගුලක් ලබා ගනී. ආරක්ෂක උල්ලංඝනය!

අසාර්ථක වීමක් වැනි විශේෂ අවස්ථා වලදී, බොහෝ සේවාදායකයින්ට එකවර අගුල තබා ගත හැකි වීම සමහර විට සම්පූර්ණයෙන්ම සාමාන්‍ය දෙයකි. එවැනි අවස්ථාවන්හිදී, අනුරූ මත පදනම් වූ විසඳුමක් යෙදිය හැකිය. එසේ නොමැතිනම්, මෙම ලිපියේ විස්තර කර ඇති විසඳුම අපි නිර්දේශ කරමු.

එක් අවස්ථාවක් සමඟ නිවැරදි ක්රියාත්මක කිරීම

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

අගුලක් ලබා ගැනීමට, මෙය කරන්න:

SET resource_name my_random_value NX PX 30000

මෙම විධානය යතුර ස්ථාපනය කරන්නේ එය දැනටමත් නොමැති නම් පමණි (NX විකල්පය), වලංගු කාලය මිලි තත්පර 30000 (PX විකල්පය). යතුර සකසා ඇත්තේ "myrandomvalue" මෙම අගය සියලුම සේවාලාභීන් සහ සියලුම අගුළු ඉල්ලීම් හරහා අනන්‍ය විය යුතුය.
මූලික වශයෙන්, අගුලු දැමීම ආරක්ෂිතව මුදා හැරීමට අහඹු අගයක් භාවිතා කරයි, ස්ක්‍රිප්ට් එකකින් රෙඩිස්: යතුර තිබේ නම් පමණක් ඉවත් කරන්න සහ එහි ගබඩා කර ඇති අගය හරියටම අපේක්ෂා කළ අගයයි. පහත Lua ස්ක්‍රිප්ට් භාවිතයෙන් මෙය සාක්ෂාත් කරගනු ලැබේ:

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

වෙනත් සේවාදායකයෙකු විසින් තබා ඇති අගුල ඉවත් කිරීම වැළැක්වීම සඳහා මෙය වැදගත් වේ. උදාහරණයක් ලෙස, සේවාදායකයා අගුලක් ලබාගෙන, පසුව පළමු අගුලට වඩා දිගු කාලයක් පවතින යම් මෙහෙයුමක අගුලු දමා ඇත (යතුර කල් ඉකුත් වීමට කාලය ඇත), පසුව වෙනත් සේවාදායකයෙකු තබා ඇති අගුල ඉවත් කරන්න.
සරල DEL එකක් භාවිතා කිරීම අනාරක්ෂිතයි මොකද සේවාලාභියෙකුට වෙනත් සේවාලාභියෙකු විසින් තබා ඇති අගුලක් ඉවත් කළ හැක. ඊට වෙනස්ව, ඉහත ස්ක්‍රිප්ටය භාවිතා කරන විට, සෑම අගුලක්ම අහඹු නූලකින් "අත්සන්" කර ඇත, එබැවින් එය ඉවත් කළ හැක්කේ එය කලින් තැබූ සේවාදායකයාට පමණි.

මෙම අහඹු තන්තුව කුමක් විය යුතුද? එය /dev/urandom වෙතින් බයිට් 20ක් විය යුතු යැයි මම අනුමාන කරමි, නමුත් ඔබේ අරමුණු සඳහා ප්‍රමාණවත් තරම් තන්තුව අද්විතීය කිරීමට ඔබට අඩු වියදම් ක්‍රම සොයාගත හැකිය. උදාහරණයක් ලෙස, /dev/urandom සමඟින් RC4 බීජ කර එයින් ව්‍යාජ අහඹු ප්‍රවාහයක් උත්පාදනය කිරීම සුදුසුය. සරල විසඳුමකට මයික්‍රො තත්පර විභේදනයේ unix කාලය සහ සේවාදායක හැඳුනුම්පත ඇතුළත් වේ; එය එතරම් ආරක්ෂිත නොවේ, නමුත් එය බොහෝ සන්දර්භයන් තුළ කාර්යයට බොහෝ දුරට ඉඩ ඇත.

යතුරේ ආයු කාලය මැනීමට අප භාවිතා කරන කාලය "අගුළු ආයු කාලය" ලෙස හැඳින්වේ. මෙම අගය යනු අගුලු දැමීම ස්වයංක්‍රීයව මුදා හැරීමට පෙර කාලය සහ වෙනත් සේවාදායකයෙකුට එම සම්පත අගුලු දැමීමට පෙර සේවාදායකයෙකුට මෙහෙයුමක් සම්පූර්ණ කිරීමට ඇති කාලය යන දෙකම වන අතර, ඇත්ත වශයෙන්ම අන්‍යෝන්‍ය බැහැර කිරීමේ සහතික කඩ නොකර. මෙම ඇපකරය නිශ්චිත කාල කවුළුවකට පමණක් සීමා වේ, එය අගුල මිලදී ගත් මොහොතේ සිට ආරම්භ වේ.

එබැවින් අගුලක් අත්පත් කර ගැනීමට සහ මුදා හැරීමට හොඳ ක්රමයක් අපි සාකච්ඡා කර ඇත. පද්ධතිය (අපි කතා කරන්නේ තනි සහ සෑම විටම පවතින අවස්ථාවකින් සමන්විත බෙදා නොදෙන පද්ධතියක් ගැන නම්) ආරක්ෂිතයි. අපට එවැනි සහතිකයක් නොමැති බෙදාහැරීමේ පද්ධතියකට මෙම සංකල්පය දීර්ඝ කරමු.

Redlock ඇල්ගොරිතම

ඇල්ගොරිතමයේ බෙදා හරින ලද අනුවාදය අපට N Redis මාස්ටර් ඇති බව උපකල්පනය කරයි. මෙම නෝඩ් එකිනෙක සම්පූර්ණයෙන්ම ස්වායත්ත වේ, එබැවින් අපි අනුකරණය හෝ වෙනත් ව්‍යංග සම්බන්ධීකරණ පද්ධතියක් භාවිතා නොකරමු. අපි දැනටමත් එක් අවස්ථාවකදී ආරක්ෂිතව අගුලක් ලබා ගන්නේ කෙසේද සහ මුදා හරින ආකාරය ආවරණය කර ඇත. ඇල්ගොරිතම, තනි අවස්ථාවක් සමඟ වැඩ කරන විට, මෙම ක්රමය හරියටම භාවිතා කරන බව අපි එය සැලකිල්ලට ගනිමු. අපගේ උදාහරණ වලදී අපි N 5 වෙත සකසන්නෙමු, එය සාධාරණ අගයකි. මේ අනුව, අපි එකිනෙකාගෙන් බොහෝ දුරට ස්වාධීනව ක්‍රියා කරන බව සහතික කිරීම සඳහා විවිධ පරිගණක හෝ අතථ්‍ය යන්ත්‍රවල රෙඩිස් මාස්ටර් 5ක් භාවිතා කිරීමට අවශ්‍ය වනු ඇත.

අගුලක් ලබා ගැනීම සඳහා, සේවාදායකයා පහත සඳහන් මෙහෙයුම් සිදු කරයි:

  1. වත්මන් කාලය මිලි තත්පර වලින් ලබා ගනී.
  2. අනුක්‍රමිකව සියලුම N අවස්ථාවන්හි අගුලක් ලබා ගැනීමට උත්සාහ කරයි, සෑම අවස්ථාවකදීම එකම ප්‍රධාන නම සහ අහඹු අගයන් භාවිතා කරයි. 2 වන අදියරේදී, සේවාලාභියා එක් එක් අවස්ථා පදනමක් මත අගුලක් සකසන විට, සේවාදායකයා එය අත්පත් කර ගැනීමට ප්‍රමාදයක් භාවිතා කරයි, එය අගුල ස්වයංක්‍රීයව මුදා හරින කාලයට සාපේක්ෂව ප්‍රමාණවත් වේ. උදාහරණයක් ලෙස, අවහිර කිරීමේ කාලසීමාව තත්පර 10 ක් නම්, ප්‍රමාදය මිලි තත්පර ~5-50 අතර විය හැකිය. මෙමගින් සේවාදායකයා අසාර්ථක වූ Redis node එකක් වෙත ළඟා වීමට උත්සාහ කරමින් දිගු කාලයක් අවහිර වී සිටිය හැකි තත්ත්වය ඉවත් කරයි: එම අවස්ථාව නොමැති නම්, අපි හැකි ඉක්මනින් වෙනත් අවස්ථාවක් වෙත සම්බන්ධ වීමට උත්සාහ කරමු.
  3. අගුලක් ගැනීමට, සේවාදායකයා කොපමණ කාලයක් ගතවී ඇත්දැයි ගණනය කරයි; මෙය සිදු කිරීම සඳහා, එය පියවර 1 හි ලබා ගත් වේලා මුද්‍රාව සත්‍ය කාල අගයෙන් අඩු කරයි. සේවාදායකයාට බොහෝ අවස්ථා (අවම වශයෙන් 3) සඳහා අගුල ලබා ගැනීමට හැකි වූයේ නම් සහ එයට ගත වූ මුළු කාලය පමණි. අගුල ලබා ගන්න, අගුළු කාල සීමාවට වඩා අඩු, අගුල ලබා ගත් බව සලකනු ලැබේ.
  4. අගුලක් අත්පත් කර ගෙන තිබේ නම්, අගුලු කාලසීමාව මුල් අගුළු කාලසීමාව 3 පියවරේදී ගණනය කරන ලද ගත වූ කාලය අඩු කරයි.
  5. සේවාදායකයා කිසියම් හේතුවක් නිසා අගුල ලබා ගැනීමට අපොහොසත් වුවහොත් (එක්කෝ N/2+1 අවස්ථා අගුළු දැමීමට නොහැකි විය, නැතහොත් අගුලු දැමීමේ කාලසීමාව සෘණාත්මක විය), එවිට එය සියලු අවස්ථා (එය අවහිර කළ නොහැකි යැයි සිතූ ඒවා පවා) අගුළු හැරීමට උත්සාහ කරයි. )

ඇල්ගොරිතම අසමමුහුර්තද?

මෙම ඇල්ගොරිතම පදනම් වී ඇත්තේ, සියලුම ක්‍රියාවලීන් ක්‍රියා කරන සමමුහුර්ත ඔරලෝසුවක් නොමැති වුවද, සෑම ක්‍රියාවලියකම දේශීය වේලාව තවමත් ආසන්න වශයෙන් එකම වේගයකින් ගලා යන අතර, අගුල ඇති මුළු කාලයට සාපේක්ෂව දෝෂය කුඩා වේ. ස්වයංක්‍රීයව මුදා හැරේ. මෙම උපකල්පනය සාමාන්‍ය පරිගණක සඳහා සාමාන්‍ය තත්වයට බෙහෙවින් සමාන ය: සෑම පරිගණකයකම දේශීය ඔරලෝසුවක් ඇති අතර, විවිධ පරිගණක අතර කාල වෙනස කුඩා බව අපට සාමාන්‍යයෙන් ගණන් ගත හැකිය.

මෙම අවස්ථාවෙහිදී, අපි අපගේ අන්‍යෝන්‍ය බැහැර කිරීමේ රීතිය වඩාත් ප්‍රවේශමෙන් සකස් කළ යුතුය: අන්‍යෝන්‍ය බැහැර කිරීම සහතික වන්නේ අගුල වලංගු කාලය තුළ (3 වන පියවරෙන් ලබාගත් මෙම අගය) අගුලු තබාගෙන සිටින සේවාදායකයා පිටවී ගියහොත් පමණි (මෙම අගය XNUMX වන විට), තවත් කාලයක් (මුළු කිහිපයක්). ක්‍රියාවලි අතර කාල වෙනස සඳහා වන්දි ගෙවීමට මිලි තත්පර).

කාල පරතරයන් සම්බන්ධීකරණය කිරීම අවශ්‍ය වන එවැනි පද්ධති ගැන පහත රසවත් ලිපිය කියයි: ලීසිං: බෙදා හරින ලද ගොනු හැඹිලි අනුකූලතාව සඳහා කාර්යක්ෂම දෝෂ-ඉවසන යාන්ත්‍රණයක්.

අසාර්ථක වීම මත නැවත උත්සාහ කරන්න

සේවාදායකයකු අගුලක් ලබා ගැනීමට අපොහොසත් වූ විට, එය අහඹු ප්‍රමාදයකින් පසුව නැවත උත්සාහ කළ යුතුය; මෙය සිදු කරනුයේ එකම සම්පතක් මත එකවර අගුලක් ලබා ගැනීමට උත්සාහ කරන බහු සේවාදායකයින් සමමුහුර්ත කිරීම සඳහා ය (එය ජයග්‍රාහකයින් නොමැති "මොළය බෙදීමේ" තත්වයකට තුඩු දිය හැකිය). මීට අමතරව, රෙඩිස් අවස්ථා බොහොමයක අගුලක් ලබා ගැනීමට සේවාදායකයෙකු වේගයෙන් උත්සාහ කරන තරමට, මොළය බෙදීමේ තත්වයක් ඇතිවිය හැකි කවුළුව පටු වේ (සහ නැවත උත්සාහ කිරීමේ අවශ්‍යතාවය අඩු වේ). එබැවින්, ඉතා මැනවින්, සේවාලාභියා Multiplexing භාවිතයෙන් එකවර N අවස්ථාවන් වෙත SET විධාන යැවීමට උත්සාහ කළ යුතුය.

බොහෝ අගුලු ලබා ගැනීමට අපොහොසත් වන සේවාදායකයින්ට (අර්ධ වශයෙන්) අත්පත් කරගත් අගුලු මුදා හැරීම කොතරම් වැදගත්ද යන්න මෙහිදී අවධාරණය කිරීම වටී, එවිට සම්පතේ ඇති අගුල නැවත ලබා ගැනීමට පෙර යතුර කල් ඉකුත් වන තෙක් බලා සිටීමට සිදු නොවේ. (ජාල ඛණ්ඩනය සිදු වුවහොත් සහ සේවාලාභියාට Redis අවස්ථාවන් සමඟ සම්බන්ධතා නැති වුවහොත්, යතුර කල් ඉකුත් වන තෙක් බලා සිටියදී ඔබට ලබා ගත හැකි දඩයක් ගෙවිය යුතුය).

අගුල නිදහස් කරන්න

අගුලක් මුදා හැරීම සරල මෙහෙයුමක් වන අතර, සේවාදායකයා යම් අවස්ථාවක් සාර්ථකව අගුලු දමා ඇති බවක් පෙනෙන්නට තිබුණත්, සියලු අවස්ථා අගුළු හැරීම අවශ්‍ය වේ.

ආරක්ෂක සලකා බැලීම්

ඇල්ගොරිතම ආරක්ෂිතද? විවිධ අවස්ථා වලදී සිදුවන්නේ කුමක්දැයි සිතීමට උත්සාහ කරමු.

ආරම්භ කිරීම සඳහා, සේවාදායකයාට බොහෝ අවස්ථාවන්හි අගුලක් ලබා ගැනීමට හැකි වූ බව උපකල්පනය කරමු. සෑම අවස්ථාවකම සියල්ලන්ටම එකම ආයු කාලයක් සහිත යතුරක් අඩංගු වේ. කෙසේ වෙතත්, මෙම එක් එක් යතුරු වෙනස් වේලාවක ස්ථාපනය කර ඇත, එබැවින් ඒවා විවිධ කාලවලදී කල් ඉකුත් වේ. නමුත්, පළමු යතුර T1 ට වඩා නරක නොවන අවස්ථාවක ස්ථාපනය කර ඇත්නම් (පළමු සේවාදායකය හා සම්බන්ධ වීමට පෙර අප තෝරා ගන්නා කාලය), සහ අවසාන යතුර ස්ථාපනය කර ඇත්තේ T2 ට වඩා නරක නොවන වේලාවක (ප්‍රතිචාරය ලැබුණු වේලාව) අවසාන සේවාදායකයෙන්), එවිට කල් ඉකුත්වන කට්ටලයේ පළමු යතුර අවම වශයෙන් නොනැසී පවතිනු ඇතැයි අපට විශ්වාසයි MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT. අනෙකුත් සියලුම යතුරු පසුව කල් ඉකුත් වනු ඇත, එබැවින් සියලුම යතුරු අවම වශයෙන් මෙම කාලය සඳහා එකවර වලංගු වනු ඇති බවට අපට සහතික විය හැක.

බොහෝ යතුරු වලංගුව පවතින කාලය තුළ, N/2+1 යතුරු දැනටමත් පවතී නම් N/2+1 SET NX මෙහෙයුම් සාර්ථක විය නොහැකි බැවින්, වෙනත් සේවාලාභියෙකුට අගුල ලබා ගැනීමට නොහැකි වනු ඇත. එබැවින්, අගුලක් අත්පත් කර ගත් පසු, එම මොහොතේම එය නැවත අත්පත් කර ගත නොහැක (මෙය අන්යෝන්ය බැහැර කිරීමේ දේපල උල්ලංඝනය කරනු ඇත).
කෙසේ වෙතත්, අපට එකවර අගුලක් ලබා ගැනීමට උත්සාහ කරන බහු සේවාදායකයින් එකවර සාර්ථක විය නොහැකි බව සහතික කර ගැනීමට අපට අවශ්‍යය.

සේවාලාභියා උපරිම අගුළු කාලසීමාවට වඩා වැඩි කාලයක් හෝ ඊට වඩා වැඩි අවස්ථාවන් අගුලු දමා තිබේ නම්, එය අගුල අවලංගු ලෙස සලකනු ලබන අතර අවස්ථා අගුළු හරිනු ඇත. එබැවින්, කල් ඉකුත්වන දිනයට වඩා අඩු කාලයකදී බොහෝ අවස්ථාවන් අවහිර කිරීමට සේවාදායකයා සමත් වූ අවස්ථාව පමණක් අපට සැලකිල්ලට ගත යුතුය. මෙම අවස්ථාවේ දී, ඉහත තර්කය සම්බන්ධයෙන්, කාලය තුළ MIN_VALIDITY කිසිදු සේවාදායකයෙකුට අගුල නැවත ලබා ගැනීමට නොහැකි විය යුතුය. එමනිසා, බොහෝ සේවාලාභීන්ට N/2+1 අවස්ථා එකම වේලාවක අගුලු දැමීමට හැකි වනු ඇත (එය 2 අදියර අවසානයේ අවසන් වේ) බහුතරය අගුලු දැමීමේ කාලය TTL කාලයට වඩා වැඩි වූ විට පමණි, එය අගුල වලංගු නොවේ.

ඔබට ආරක්‍ෂාව පිළිබඳ විධිමත් සාක්ෂියක් සැපයිය හැකිද, පවතින සමාන ඇල්ගොරිතම සඳහන් කළ හැකිද, නැතහොත් ඉහත සඳහන් දෝෂයක් සොයා ගත හැකිද?

ප්‍රවේශ්‍යතා සලකා බැලීම්

පද්ධතියේ ඇති බව ප්රධාන ලක්ෂණ තුනක් මත රඳා පවතී:

  1. අගුලු ස්වයංක්‍රීයව මුදා හරින්න (යතුරු කල් ඉකුත් වන විට): යතුරු අවසානයේ අගුලු සඳහා භාවිතා කිරීමට නැවත ලබා ගත හැක.
  2. අපේක්ෂිත අගුල අත්පත් කර ගෙන නොමැති විට හෝ අත්පත් කර ගෙන රැකියාව සම්පූර්ණ කර ඇති විට සේවාදායකයින් සාමාන්‍යයෙන් අගුලු ඉවත් කිරීමෙන් එකිනෙකාට උපකාර කරන බව; එබැවින් අගුල නැවත ලබා ගැනීමට යතුරු කල් ඉකුත් වන තෙක් අපට බලා සිටීමට සිදු නොවනු ඇත.
  3. සේවාදායකයෙකුට අගුලක් ලබා ගැනීමට නැවත උත්සාහ කිරීමට අවශ්‍ය වූ විට, එය බොහෝ අගුලු ලබා ගැනීමට අවශ්‍ය කාල සීමාවට වඩා සාපේක්ෂව දිගු කාලයක් බලා සිටීමයි. මෙය සම්පත් සඳහා තරඟ කිරීමේදී මොළයේ බෙදීම් තත්වයක් ඇතිවීමේ සම්භාවිතාව අඩු කරයි.

කෙසේ වෙතත්, ජාල ඛණ්ඩවල TTL ට සමාන ලබා ගත හැකි දඩයක් ඇත, එබැවින් යාබද කොටස් තිබේ නම්, දඩුවම අසීමිත විය හැකිය. සේවාදායකයෙකු අගුලක් ලබාගෙන එය මුදා හැරීමට පෙර වෙනත් කොටසකට ඉරා දැමූ විට මෙය සිදු වේ.

ප්‍රතිපත්තිමය වශයෙන්, අසීමිත යාබද ජාල කොටස් ලබා දී, පද්ධතියක් අසීමිත කාලයක් සඳහා ලබා ගත නොහැක.

කාර්ය සාධනය, අසාර්ථකත්වය සහ fsync

බොහෝ අය Redis භාවිතා කරන්නේ අගුලු ලබා ගැනීමට සහ මුදා හැරීමට අවශ්‍ය ප්‍රමාදය සහ තත්පරයකට සම්පූර්ණ කළ හැකි අත්පත් කර ගැනීම් / මුදා හැරීම් සංඛ්‍යාව අනුව ඔවුන්ට ඉහළ අගුළු සේවාදායක කාර්ය සාධනයක් අවශ්‍ය වන බැවිනි. මෙම අවශ්‍යතාවය සපුරාලීම සඳහා, ප්‍රමාදය අඩු කිරීම සඳහා N Redis සේවාදායකයන් සමඟ සන්නිවේදනය කිරීමේ උපාය මාර්ගයක් ඇත. මෙය මල්ටිප්ලෙක්සිං උපාය මාර්ගයකි (හෝ "දුප්පත් මිනිසාගේ මල්ටිප්ලෙක්සින්", එහිදී සොකට් එක අවහිර නොවන ආකාරයෙන් තබා, සියලුම විධාන යවන අතර, සේවාලාභියා සහ එක් එක් අවස්ථාව අතර වට-සංචාර කාලය සමාන වේ යැයි උපකල්පනය කරමින් විධාන පසුව කියවයි) .

කෙසේ වෙතත්, අසාර්ථකත්වයන්ගෙන් විශ්වාසදායක ප්‍රතිසාධනයක් සහිත ආකෘතියක් නිර්මාණය කිරීමට අප උත්සාහ කරන්නේ නම්, දිගු කාලීන දත්ත ගබඩා කිරීම හා සම්බන්ධ සලකා බැලීම ද අප සැලකිල්ලට ගත යුතුය.

මූලික වශයෙන්, ගැටළුව පැහැදිලි කිරීම සඳහා, අපි දිගු කාලීන දත්ත ගබඩාවක් නොමැතිව Redis වින්‍යාස කරමු යැයි උපකල්පනය කරමු. සේවාලාභියා අවස්ථා 3න් 5ක් අවහිර කිරීමට සමත් වේ. සේවාදායකයා අවහිර කිරීමට සමත් වූ එක් අවස්ථාවක් නැවත ආරම්භ කර ඇති අතර, මේ මොහොතේ එකම සම්පත සඳහා නැවත අවස්ථා 3 ක් ඇත, එය අපට අවහිර කළ හැකි අතර, තවත් සේවාදායකයෙකුට නැවත ආරම්භ කළ අවස්ථාව අවහිර කළ හැකිය, ආරක්ෂක දේපල උල්ලංඝනය කරයි. අගුල් වල සුවිශේෂත්වය උපකල්පනය කරයි.

ඔබ ඉදිරි දත්ත (AOF) සක්‍රීය කරන්නේ නම්, තත්වය තරමක් දියුණු වනු ඇත. උදාහරණයක් ලෙස, ඔබට SHUTDOWN විධානය යවා එය නැවත ආරම්භ කිරීමෙන් සේවාදායකයක් ප්‍රවර්ධනය කළ හැකිය. Redis හි කල් ඉකුත් වීමේ මෙහෙයුම් අර්ථකථනය අනුව ක්‍රියාත්මක කර ඇත්තේ සේවාදායකය ක්‍රියා විරහිත කර තිබියදීත් කාලය ගලා යන ආකාරයට බැවින්, අපගේ සියලු අවශ්‍යතා හොඳින් පවතී. සාමාන්‍ය වසා දැමීමක් සහතික වන තාක් මෙය සාමාන්‍ය වේ. විදුලිය ඇනහිටීම් වලදී කුමක් කළ යුතුද? Redis පෙරනිමියෙන් වින්‍යාස කර ඇත්නම්, සෑම තත්පරයකම තැටියේ fsync සමමුහුර්ත කිරීමත් සමඟ, නැවත ආරම්භ කිරීමෙන් පසු අපට අපගේ යතුර නොතිබිය හැකිය. න්‍යායාත්මකව, අපට ඕනෑම අවස්ථාවක නැවත ආරම්භ කිරීමේදී අගුලු ආරක්ෂාව සහතික කිරීමට අවශ්‍ය නම්, අපි සක්‍රිය කළ යුතුය fsync=always දිගු කාලීන දත්ත ගබඩා කිරීම සඳහා සැකසුම් තුළ. මෙය සම්ප්‍රදායිකව බෙදා හරින ලද අගුල් ආරක්ෂිතව ක්‍රියාත්මක කිරීමට භාවිතා කරන CP පද්ධති මට්ටම දක්වා කාර්ය සාධනය සම්පූර්ණයෙන්ම විනාශ කරනු ඇත.

නමුත් තත්ත්වය බැලූ බැල්මට පෙනෙනවාට වඩා හොඳයි. ප්‍රතිපත්තිමය වශයෙන්, ඇල්ගොරිතමයේ ආරක්‍ෂාව සුරකිනු ලබන්නේ අසාර්ථක වීමෙන් පසු අවස්ථාව නැවත ආරම්භ කරන විට, එය දැනට සක්‍රියව පවතින කිසිදු අගුලකට තවදුරටත් සහභාගී නොවන බැවිනි.

මෙය සහතික කිරීම සඳහා, අසාර්ථක වීමෙන් පසුව අප භාවිතා කරන උපරිම TTL ඉක්මවන කාල සීමාවක් සඳහා එම අවස්ථාව ලබා ගත නොහැකි බව සහතික කළ යුතුය. මේ ආකාරයෙන් අපි කල් ඉකුත්වන දිනය සහ අසාර්ථක වූ අවස්ථාවේ සක්‍රිය වූ සියලුම යතුරු ස්වයංක්‍රීයව මුදා හැරීම තෙක් බලා සිටිමු.

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

අපි ඇල්ගොරිතම ලබා ගැනීම වැඩි කරමු: අපි අවහිර කිරීම දිගු කරමු

සේවාලාභීන් විසින් සිදු කරනු ලබන කාර්යය කුඩා පියවර වලින් සමන්විත වේ නම්, පෙරනිමි අගුළු කාලසීමාව අඩු කිරීමට සහ අගුලු දිගු කිරීම සඳහා යාන්ත්රණයක් ක්රියාත්මක කිරීමට හැකි වේ. ප්‍රතිපත්තිමය වශයෙන්, සේවාලාභියා පරිගණනය කිරීමේදී කාර්යබහුල නම් සහ අගුළු කල් ඉකුත් වීමේ අගය අනතුරුදායක ලෙස අඩු නම්, යතුර තවමත් පවතී නම් සහ එහි අගය අහඹු ලෙස ලබා ගන්නා අගයක් නම් යතුරේ TTL දිගු කරන සියලුම අවස්ථා සඳහා Lua ස්ක්‍රිප්ට් යැවිය හැක. අගුල අත්පත් කර ගන්නා ලදී.

සේවාදායකයෙකු නැවත ලබා ගත යුතු අගුලක් සලකා බැලිය යුත්තේ එය වලංගු කාල සීමාව තුළ බොහෝ අවස්ථා අගුලු දැමීමට සමත් වුවහොත් පමණි.

ඇත්ත, තාක්‍ෂණිකව ඇල්ගොරිතම වෙනස් නොවේ, එබැවින් අගුලු ලබා ගැනීමට නැවත නැවත උත්සාහ කරන උපරිම සංඛ්‍යාව සීමා කළ යුතුය, එසේ නොමැතිනම් ප්‍රවේශ්‍යතා ගුණාංග උල්ලංඝනය වේ.

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

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