Ibinahagi ang mga kandado gamit ang Redis

Hoy Habr!

Ngayon dinadala namin sa iyong pansin ang isang pagsasalin ng isang kumplikadong artikulo tungkol sa pagpapatupad ng ipinamahagi na pag-lock gamit ang Redis at inaanyayahan ka na pag-usapan ang tungkol sa mga prospect ng Redis bilang isang paksa. Pagsusuri ng algorithm ng Redlock na pinag-uusapan mula kay Martin Kleppmann, may-akda ng aklat "Mataas na Load Application", binigay dito.

Ang distributed locking ay isang napaka-kapaki-pakinabang na primitive na ginagamit sa maraming kapaligiran kung saan ang iba't ibang proseso ay dapat gumana sa mga nakabahaging mapagkukunan sa paraang magkahiwalay.

Mayroong ilang mga aklatan at mga post doon na naglalarawan kung paano ipatupad ang DLM (Distributed Lock Manager) gamit ang Redis, ngunit ang bawat library ay gumagamit ng ibang diskarte at ang mga garantiyang ibinibigay nila ay medyo mahina kumpara sa kung ano ang makakamit na may bahagyang mas sopistikadong disenyo.

Sa artikulong ito susubukan naming ilarawan ang isang conditional canonical algorithm na nagpapakita kung paano ipatupad ang distributed locking gamit ang Redis. Pag-uusapan natin ang tungkol sa tinatawag na algorithm redlock, nagpapatupad ito ng distributed lock manager at, sa aming opinyon, ang algorithm na ito ay mas ligtas kaysa sa karaniwang single-instance na diskarte. Umaasa kaming susuriin ito ng komunidad, magbibigay ng feedback, at gamitin ito bilang panimulang punto para sa mas kumplikado o alternatibong mga proyekto.

Pagpapatupad

Bago lumipat sa paglalarawan ng algorithm, nagbibigay kami ng ilang mga link sa mga yari na pagpapatupad. Maaari silang magamit para sa sanggunian.

  • Redlock-rb (pagpapatupad para kay Ruby). meron din tinidor Redlock-rb, na nagdaragdag ng isang pakete (hiyas) para sa kadalian ng pamamahagi, at hindi lamang para doon.
  • Redlock-py (Pagpapatupad ng Python).
  • Airedlock (pagpapatupad para sa Asyncio Python).
  • Redlock-php (pagpapatupad para sa PHP).
  • PHPRedisMutex (isa pang pagpapatupad para sa PHP)
  • cheprasov/php-redis-lock (PHP library para sa mga kandado)
  • Redsync (pagpapatupad para sa Go).
  • Redisson (pagpapatupad para sa Java).
  • Redis::DistLock (pagpapatupad para sa Perl).
  • Redlock-cpp (pagpapatupad para sa C++).
  • Redlock-cs (pagpapatupad para sa C#/.NET).
  • RedLock.net (pagpapatupad para sa C#/.NET). Sa suporta para sa mga extension ng async at lock.
  • ScarletLock (pagpapatupad para sa C# .NET na may na-configure na data store)
  • Redlock4Net (pagpapatupad para sa C# .NET)
  • node-redlock (pagpapatupad para sa NodeJS). May kasamang suporta para sa pagpapahaba ng mga lock.

Mga Garantiya sa Seguridad at Availability

Imomodelo namin ang aming disenyo gamit lamang ang tatlong katangian na sa tingin namin ay nagbibigay ng pinakamababang garantiyang kailangan para epektibong magamit ang distributed locking.

  1. Pag-aari ng seguridad: Mutual na pagbubukod. Sa anumang oras, isang kliyente lamang ang maaaring humawak ng lock.
  2. Availability Property A: Walang deadlocks. Palaging posible na makakuha ng lock sa kalaunan, kahit na nabigo ang kliyenteng nag-lock sa mapagkukunan o napunta sa ibang disk segment.
  3. Availability Property B: Fault Tolerance. Hangga't gumagana ang karamihan ng mga Redis node, ang mga kliyente ay nakakakuha at nakakapaglabas ng mga lock.

Bakit hindi sapat ang pagpapatupad batay sa pagkabigo sa pagbawi sa kasong ito
Upang maunawaan kung ano ang pagbutihin natin, suriin natin ang kasalukuyang kalagayan sa karamihan ng mga nakabahaging locking library batay sa Redis.

Ang pinakasimpleng paraan upang i-lock ang isang mapagkukunan gamit ang Redis ay upang lumikha ng isang susi sa instance. Karaniwan, ang isang susi ay nilikha na may limitadong panghabambuhay, ito ay nakakamit gamit ang mag-e-expire na tampok na ibinigay sa Redis, kaya maaga o huli ang key na ito ay inilabas (ang ari-arian 2 sa aming listahan). Kapag kailangang ilabas ng kliyente ang mapagkukunan, tatanggalin nito ang susi.

Sa unang tingin, ang solusyon na ito ay gumagana nang maayos, ngunit may problema: ang aming arkitektura ay lumilikha ng isang punto ng pagkabigo. Ano ang mangyayari kung nabigo ang host Redis instance? Dagdagan pa natin ng alipin! At gagamitin namin ito kung hindi available ang nagtatanghal. Sa kasamaang palad, ang pagpipiliang ito ay hindi mabubuhay. Sa paggawa nito, hindi namin maipapatupad nang maayos ang pag-aari ng mutual exclusion na kailangan namin para matiyak ang seguridad, dahil asynchronous ang replication sa Redis.

Malinaw, sa gayong modelo ang isang kondisyon ng lahi ay nangyayari:

  1. Ang Client A ay nakakakuha ng lock sa master.
  2. Nabigo ang master bago mailipat ang key entry sa alipin.
  3. Ang tagasunod ay na-promote sa pinuno.
  4. Ang Client B ay nakakakuha ng lock sa parehong mapagkukunan na na-lock na ni A. PAGLABAG SA SEGURIDAD!

Minsan ito ay ganap na normal na sa mga espesyal na pangyayari, tulad ng isang pagkabigo, maraming mga kliyente ang maaaring hawakan ang lock sa parehong oras. Sa ganitong mga kaso, maaaring ilapat ang isang replication-based na solusyon. Kung hindi, inirerekumenda namin ang solusyon na inilarawan sa artikulong ito.

Tamang pagpapatupad sa isang pagkakataon

Bago subukang malampasan ang mga pagkukulang ng pagsasaayos ng isang halimbawang inilarawan sa itaas, unawain natin kung paano maayos na pangasiwaan ang simpleng kaso na ito, dahil ang solusyon na ito ay aktwal na wasto sa mga aplikasyon kung saan ang isang kondisyon ng lahi ay katanggap-tanggap paminsan-minsan, at dahil din sa pagharang sa isang ang isang instance ay nagsisilbing batayan na ginagamit sa ipinamahagi na algorithm na inilarawan dito.

Upang makakuha ng lock, gawin ito:

SET resource_name my_random_value NX PX 30000

Ang command na ito ay nag-i-install lamang ng key kung wala pa ito (NX option), na may validity period na 30000 milliseconds (PX option). Ang susi ay nakatakda sa "myrandomvalue" Ang halagang ito ay dapat na natatangi sa lahat ng kliyente at lahat ng kahilingan sa lock.
Karaniwan, ang isang random na halaga ay ginagamit upang ligtas na ilabas ang lock, na may isang script na nagsasabi sa Redis: alisin lamang ang susi kung mayroon ito at ang halaga na nakaimbak dito ay eksakto kung ano ang inaasahan. Nakamit ito gamit ang sumusunod na script ng Lua:

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

Mahalaga ito para maiwasang maalis ang isang lock na hawak ng isa pang kliyente. Halimbawa, maaaring makakuha ng lock ang isang kliyente, pagkatapos ay ma-lock sa ilang operasyon na mas matagal kaysa sa unang lock (para magkaroon ng oras na mag-expire ang susi), at sa paglaon ay alisin ang lock na inilagay ng ibang kliyente.
Ang paggamit ng isang simpleng DEL ay hindi ligtas dahil maaaring tanggalin ng isang kliyente ang isang lock na hawak ng isa pang kliyente. Sa kabaligtaran, kapag ginagamit ang script sa itaas, ang bawat lock ay "nalagdaan" gamit ang isang random na string, kaya ang kliyente lamang na naglagay nito noon ay maaaring magtanggal nito.

Ano dapat ang random string na ito? Sa palagay ko ito ay dapat na 20 bytes mula sa /dev/urandom, ngunit makakahanap ka ng mas murang mga paraan upang gawing kakaiba ang string para sa iyong mga layunin. Halimbawa, mainam na i-seed ang RC4 gamit ang /dev/urandom at pagkatapos ay bumuo ng pseudo-random stream mula dito. Ang isang mas simpleng solusyon ay nagsasangkot ng kumbinasyon ng unix time sa microsecond resolution kasama ang client ID; ito ay hindi kasing-secure, ngunit ito ay malamang na nakasalalay sa gawain sa karamihan ng mga konteksto.

Ang oras na ginagamit namin bilang sukatan ng buhay ng susi ay tinatawag na "habambuhay ng lock". Ang halagang ito ay parehong tagal ng oras bago awtomatikong mailabas ang lock at ang tagal ng oras na kailangan ng isang kliyente upang makumpleto ang isang operasyon bago mai-lock ng isa pang kliyente ang mapagkukunang iyon, nang hindi aktwal na lumalabag sa mga garantiya ng mutual exclusion. Ang garantiyang ito ay limitado lamang sa isang tiyak na palugit ng oras, na magsisimula mula sa sandaling binili ang lock.

Kaya napag-usapan namin ang isang mahusay na paraan upang makakuha at maglabas ng lock. Ang system (kung pinag-uusapan natin ang tungkol sa isang hindi naipamahagi na sistema na binubuo ng isang solong at palaging magagamit na halimbawa) ay ligtas. Palawakin natin ang konseptong ito sa isang distributed system, kung saan wala tayong ganoong mga garantiya.

Algoritmo ng redlock

Ipinapalagay ng ipinamahagi na bersyon ng algorithm na mayroon kaming mga master ng N Redis. Ang mga node na ito ay ganap na independyente sa isa't isa, kaya hindi kami gumagamit ng pagtitiklop o anumang iba pang implicit na sistema ng koordinasyon. Nasaklaw na namin kung paano secure na kumuha at maglabas ng lock sa isang pagkakataon. Isinasaalang-alang namin na ang algorithm, kapag nagtatrabaho sa isang pagkakataon, ay gagamit nang eksakto sa pamamaraang ito. Sa aming mga halimbawa, itinakda namin ang N sa 5, na isang makatwirang halaga. Kaya, kakailanganin nating gumamit ng 5 Redis masters sa iba't ibang mga computer o virtual machine upang matiyak na sila ay kumikilos nang hiwalay sa isa't isa.

Upang makakuha ng lock, ginagawa ng kliyente ang mga sumusunod na operasyon:

  1. Nakukuha ang kasalukuyang oras sa millisecond.
  2. Sunud-sunod na sinusubukang kumuha ng lock sa lahat ng N instance, gamit ang parehong key name at random na value sa lahat ng kaso. Sa Stage 2, kapag ang kliyente ay nag-set up ng isang lock sa bawat pagkakataon na batayan, ang kliyente ay gumagamit ng isang pagkaantala upang makuha ito na sapat na maikli kumpara sa oras pagkatapos kung saan ang lock ay awtomatikong ilalabas. Halimbawa, kung ang tagal ng pagharang ay 10 segundo, ang pagkaantala ay maaaring nasa hanay na ~5-50 millisecond. Inaalis nito ang sitwasyon kung saan maaaring manatiling naka-block ang kliyente sa loob ng mahabang panahon sinusubukang maabot ang isang nabigong Redis node: kung hindi available ang instance, susubukan naming kumonekta sa isa pang instance sa lalong madaling panahon.
  3. Upang kumuha ng lock, kinakalkula ng kliyente kung gaano karaming oras ang lumipas; Upang gawin ito, ibinabawas nito mula sa aktwal na halaga ng oras ang timestamp na nakuha sa hakbang 1. Kung at kung nakuha lang ng kliyente ang lock sa karamihan ng mga pagkakataon (hindi bababa sa 3), at ang kabuuang oras na inabot hanggang makuha ang lock, mas mababa sa tagal ng lock, ang lock ay itinuturing na nakuha.
  4. Kung nakuha ang isang lock, ang tagal ng lock ay ituturing na orihinal na tagal ng lock na binawasan ang lumipas na oras na kinakalkula sa hakbang 3.
  5. Kung nabigo ang kliyente na makuha ang lock para sa ilang kadahilanan (alinman sa hindi nito nagawang i-lock ang N/2+1 na mga instance, o ang tagal ng lock ay negatibo), pagkatapos ay susubukan nitong i-unlock ang lahat ng mga pagkakataon (kahit ang mga naisip na hindi nito ma-block. ).

Asynchronous ba ang algorithm?

Ang algorithm na ito ay batay sa pagpapalagay na, bagama't walang naka-synchronize na orasan kung saan gagana ang lahat ng mga proseso, ang lokal na oras sa bawat proseso ay dumadaloy pa rin sa humigit-kumulang sa parehong bilis, at ang error ay maliit kumpara sa kabuuang oras pagkatapos ng lock ay awtomatikong inilabas. Ang palagay na ito ay halos kapareho sa karaniwang sitwasyon para sa mga ordinaryong computer: ang bawat computer ay may lokal na orasan, at karaniwan nating maaasahan na ang pagkakaiba ng oras sa pagitan ng iba't ibang mga computer ay maliit.

Sa puntong ito, dapat nating mas maingat na bumalangkas ng ating tuntunin sa pagbubukod sa isa't isa: ang pagbubukod sa isa't isa ay ginagarantiyahan lamang kung ang kliyente na may hawak ng lock ay lalabas sa panahon na ang lock ay wasto (nakuha ang halagang ito sa hakbang 3), na binawasan ng ilang oras (kabuuang ilang millisecond upang mabayaran ang pagkakaiba ng oras sa pagitan ng mga proseso).

Ang sumusunod na kawili-wiling artikulo ay nagsasabi ng higit pa tungkol sa mga naturang sistema na nangangailangan ng koordinasyon ng mga agwat ng oras: Mga pag-upa: isang mahusay na mekanismong hindi mapagparaya sa pagkakamali para sa pagkakapare-pareho ng cache ng file.

Subukan muli sa pagkabigo

Kapag nabigo ang isang kliyente na makakuha ng lock, dapat itong subukang muli pagkatapos ng random na pagkaantala; ginagawa ito para i-de-synchronize ang maramihang mga kliyente na sinusubukang kumuha ng lock sa parehong mapagkukunan nang sabay-sabay (na maaaring humantong sa isang "split-brain" na sitwasyon kung saan walang mga nanalo). Bukod pa rito, mas mabilis na sinusubukan ng isang kliyente na makakuha ng lock sa karamihan ng mga pagkakataon ng Redis, mas makitid ang window kung saan maaaring mangyari ang isang split-brain na sitwasyon (at mas maliit ang pangangailangan para sa muling pagsubok). Samakatuwid, sa isip, dapat subukan ng kliyente na magpadala ng mga utos ng SET sa mga N pagkakataon nang sabay-sabay gamit ang multiplexing.

Nararapat na bigyang-diin dito kung gaano kahalaga para sa mga kliyenteng nabigong makuha ang karamihan ng mga kandado na ilabas ang (bahagyang) nakuhang mga kandado, upang hindi na nila kailangang maghintay na mag-expire ang susi bago makuha muli ang lock sa mapagkukunan. (bagaman kung mangyari ang pagkapira-piraso ng network , at ang kliyente ay nawalan ng pakikipag-ugnayan sa mga pagkakataon ng Redis, kailangan mong magbayad ng multa sa kakayahang magamit habang naghihintay na mag-expire ang susi).

Bitawan ang lock

Ang pagpapakawala ng lock ay isang simpleng operasyon na nangangailangan lamang ng pag-unlock sa lahat ng mga pagkakataon, hindi alintana kung ang kliyente ay mukhang matagumpay na na-lock ang isang partikular na pagkakataon.

Mga Pagsasaalang-alang sa Seguridad

Ligtas ba ang algorithm? Subukan nating isipin kung ano ang nangyayari sa iba't ibang mga senaryo.

Upang magsimula, ipagpalagay natin na ang kliyente ay nakakuha ng lock sa karamihan ng mga pagkakataon. Maglalaman ang bawat instance ng key na may parehong buhay para sa lahat. Gayunpaman, na-install ang bawat isa sa mga key na ito sa magkaibang oras, kaya mag-e-expire ang mga ito sa iba't ibang oras. Ngunit, kung ang unang key ay na-install sa isang oras na hindi mas masahol pa kaysa sa T1 (ang oras na pipiliin namin bago makipag-ugnay sa unang server), at ang huling key ay na-install sa isang oras na hindi mas masahol pa kaysa sa T2 (ang oras kung saan ang tugon ay natanggap mula sa huling server), pagkatapos ay tiwala kami na ang unang susi sa set na mag-e-expire ay mabubuhay nang hindi bababa sa MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT. Ang lahat ng iba pang mga susi ay mag-e-expire sa ibang pagkakataon, upang makatitiyak kami na ang lahat ng mga susi ay sabay-sabay na magiging wasto para sa hindi bababa sa oras na ito.

Sa panahong nananatiling valid ang karamihan sa mga susi, hindi makukuha ng isa pang kliyente ang lock, dahil hindi magtagumpay ang N/2+1 SET NX operations kung mayroon nang N/2+1 keys. Samakatuwid, kapag nakuha na ang isang lock, imposibleng makuha itong muli sa parehong sandali (labag ito sa pag-aari ng mutual exclusion).
Gayunpaman, gusto naming tiyakin na maraming kliyenteng sumusubok na kumuha ng lock nang sabay-sabay ay hindi maaaring magtatagumpay sa parehong oras.

Kung ni-lock ng kliyente ang karamihan ng mga instance nang humigit-kumulang o higit pa sa maximum na tagal ng lock, ituturing nitong invalid ang lock at i-unlock ang mga instance. Samakatuwid, kailangan lang nating isaalang-alang ang kaso kung saan nagawang harangan ng kliyente ang karamihan ng mga pagkakataon sa isang oras na mas mababa sa petsa ng pag-expire. Sa kasong ito, tungkol sa argumento sa itaas, sa panahon MIN_VALIDITY walang kliyente ang dapat na muling makuha ang lock. Samakatuwid, maraming kliyente ang makakapag-lock ng N/2+1 instance sa parehong oras (na magtatapos sa dulo ng stage 2) kapag mas malaki ang oras para i-lock ang karamihan kaysa sa TTL time, na nagiging invalid ang lock.

Maaari ka bang magbigay ng pormal na patunay ng seguridad, ipahiwatig ang mga umiiral nang katulad na algorithm, o maghanap ng bug sa itaas?

Mga Pagsasaalang-alang sa Accessibility

Ang pagkakaroon ng system ay nakasalalay sa tatlong pangunahing katangian:

  1. Awtomatikong bitawan ang mga kandado (habang nag-e-expire ang mga susi): Sa kalaunan ay magiging available muli ang mga susi upang magamit para sa mga kandado.
  2. Ang katotohanan na ang mga kliyente ay karaniwang tumutulong sa isa't isa sa pamamagitan ng pag-alis ng mga kandado kapag ang nais na kandado ay hindi nakuha, o nakuha at ang trabaho ay natapos na; kaya malamang na hindi na natin kailangang hintayin na mag-expire ang mga susi upang muling makuha ang lock.
  3. Ang katotohanan na kapag ang isang kliyente ay kailangang subukang muli upang makakuha ng isang lock, naghihintay ito ng medyo mas mahabang oras kaysa sa panahon na kinakailangan upang makuha ang karamihan sa mga kandado. Binabawasan nito ang posibilidad na magkaroon ng split-brain na sitwasyon kapag nakikipagkumpitensya para sa mga mapagkukunan.

Gayunpaman, mayroong parusa sa pagiging available na katumbas ng TTL ng mga segment ng network, kaya kung mayroong magkadikit na mga segment, maaaring hindi tiyak ang parusa. Nangyayari ito sa tuwing nakakakuha ang isang kliyente ng lock at pagkatapos ay pumupunit sa isa pang segment bago nito mailabas ito.

Sa prinsipyo, dahil sa walang katapusang magkadikit na mga segment ng network, maaaring manatiling hindi available ang isang system sa loob ng walang katapusang yugto ng panahon.

Pagganap, failover at fsync

Maraming tao ang gumagamit ng Redis dahil kailangan nila ng mataas na pagganap ng server ng lock sa mga tuntunin ng latency na kinakailangan upang makakuha at mag-release ng mga lock, at ang bilang ng mga acquisition/release na maaaring kumpletuhin bawat segundo. Upang matugunan ang kinakailangang ito, mayroong isang diskarte upang makipag-ugnayan sa mga server ng N Redis upang mabawasan ang latency. Isa itong multiplexing na diskarte (o "poor man's multiplexing", kung saan ang socket ay inilalagay sa non-blocking mode, ipinapadala ang lahat ng command, at binabasa ang mga command sa ibang pagkakataon, sa pag-aakalang ang round-trip time sa pagitan ng kliyente at bawat instance ay magkatulad) .

Gayunpaman, kailangan din nating isaalang-alang ang pagsasaalang-alang na nauugnay sa pangmatagalang pag-iimbak ng data kung magsusumikap tayong lumikha ng isang modelo na may maaasahang pagbawi mula sa mga pagkabigo.

Karaniwan, upang linawin ang isyu, ipagpalagay natin na iko-configure natin ang Redis nang walang pangmatagalang imbakan ng data. Nagagawa ng kliyente na harangan ang 3 sa 5 mga pagkakataon. Ang isa sa mga instance na nagawang i-block ng kliyente ay na-restart, at sa sandaling ito ay may 3 instance na muli para sa parehong mapagkukunan, na maaari naming i-block, at ang isa pang kliyente ay maaaring, sa turn, i-block ang na-restart na instance, na lumalabag sa pag-aari ng seguridad na ipinapalagay ang pagiging eksklusibo ng mga kandado.

Kung ie-enable mo ang data ahead (AOF), bahagyang bubuti ang sitwasyon. Halimbawa, maaari mong i-promote ang isang server sa pamamagitan ng pagpapadala ng SHUTDOWN command at pag-restart nito. Dahil ang mga pagpapatakbo ng pag-expire sa Redis ay semantiko na ipinapatupad sa paraang patuloy na dumadaloy ang oras kahit na naka-off ang server, maayos ang lahat ng aming mga kinakailangan. Ito ay normal hangga't ang isang normal na shutdown ay natiyak. Ano ang gagawin kung sakaling mawalan ng kuryente? Kung ang Redis ay na-configure bilang default, na may fsync na nagsi-synchronize sa disk bawat segundo, posible na pagkatapos ng pag-restart ay wala na ang aming susi. Sa teorya, kung gusto naming garantiya ang seguridad ng lock sa panahon ng pag-restart ng anumang pagkakataon, dapat naming paganahin fsync=always sa mga setting para sa pangmatagalang imbakan ng data. Ito ay ganap na papatayin ang pagganap, hanggang sa antas ng mga CP system na tradisyonal na ginagamit upang ligtas na ipatupad ang mga distributed lock.

Ngunit ang sitwasyon ay mas mahusay kaysa sa tila sa unang tingin. Sa prinsipyo, pinapanatili ang seguridad ng algorithm dahil kapag na-restart ang instance pagkatapos ng pagkabigo, hindi na ito nakikilahok sa anumang lock na kasalukuyang aktibo.

Upang matiyak ito, kailangan lang naming tiyakin na pagkatapos ng isang pagkabigo ang instance ay mananatiling hindi magagamit sa isang yugto ng panahon na bahagyang lumampas sa maximum na TTL na ginagamit namin. Sa ganitong paraan maghihintay kami hanggang sa petsa ng pag-expire at awtomatikong paglabas ng lahat ng mga susi na aktibo sa oras ng pagkabigo.

Gamit ang mga naantalang pag-restart, sa prinsipyo posible na makamit ang seguridad kahit na walang anumang pangmatagalang pagtitiyaga sa Redis. Tandaan, gayunpaman, na maaaring magresulta ito sa multa para sa paglabag sa accessibility. Halimbawa, kung nabigo ang karamihan sa mga pagkakataon, ang system ay magiging hindi magagamit sa buong mundo para sa TTL (at walang mapagkukunang maaaring i-block sa panahong ito).

Pinapataas namin ang kakayahang magamit ng algorithm: pinapalawak namin ang pagharang

Kung ang gawaing ginagawa ng mga kliyente ay binubuo ng maliliit na hakbang, posibleng bawasan ang default na tagal ng lock at ipatupad ang isang mekanismo para sa pagpapalawak ng mga lock. Sa prinsipyo, kung ang kliyente ay abala sa pag-compute at ang lock expiration value ay mapanganib na mababa, maaari kang magpadala ng Lua script sa lahat ng mga pagkakataon na nagpapalawak ng TTL ng key kung ang susi ay umiiral pa rin at ang halaga nito ay random na halaga pa rin na nakuha kapag ang nakuha ang lock.

Dapat lang na isaalang-alang ng isang kliyente ang isang lock na muling makuha kung nagawa nitong i-lock ang karamihan ng mga pagkakataon sa loob ng panahon ng bisa.

Totoo, teknikal na hindi nagbabago ang algorithm, kaya ang maximum na bilang ng mga paulit-ulit na pagtatangka upang makakuha ng mga kandado ay dapat na limitado, kung hindi, ang mga katangian ng pagiging naa-access ay lalabag.

Pinagmulan: www.habr.com

Magdagdag ng komento