Ngonci disebarkeun maké Redis

Héy Habr!

Dinten ieu kami mawa perhatian anjeun tarjamahan tina artikel kompléks ngeunaan palaksanaan ngonci disebarkeun maké Redis sarta ngajak anjeun ngobrol ngeunaan prospek Redis salaku topik. Analisis algoritma Redlock sual ti Martin Kleppmann, panulis buku "Aplikasi Beban Tinggi", dibikeun di dieu.

Ngonci anu disebarkeun mangrupikeun primitif anu kapaké pisan anu dianggo dina seueur lingkungan dimana prosés anu béda-béda kedah dianggo dina sumber daya anu dibagikeun dina cara anu saling ekslusif.

Aya sababaraha perpustakaan jeung tulisan kaluar aya nu ngajelaskeun kumaha carana nerapkeun DLM (Distributed Konci Manajer) maké Redis, tapi unggal perpustakaan nyokot pendekatan béda jeung jaminan aranjeunna nyadiakeun rada lemah dibandingkeun naon achievable kalawan desain rada leuwih canggih.

Dina artikel ieu kami baris coba ngajelaskeun hiji algoritma canonical kondisional nu nunjukkeun kumaha nerapkeun ngonci disebarkeun maké Redis. Urang bakal ngobrol ngeunaan hiji algoritma disebut Konci beureum, éta implements a manajer konci disebarkeun sarta, dina pamadegan urang, algoritma ieu leuwih aman ti biasa pendekatan single-instance. Kami ngarepkeun komunitas bakal nganalisis éta, masihan tanggapan, sareng dianggo salaku titik awal pikeun proyék-proyék anu langkung kompleks atanapi alternatif.

Palaksanaan

Sateuacan ngaléngkah ka déskripsi algoritma, kami nyayogikeun sababaraha tautan kana palaksanaan anu siap-siap. Éta bisa dipaké pikeun rujukan.

Kaamanan sareng Jaminan Kasadiaan

Kami badé ngamodelkeun desain kami kalayan ngan ukur tilu sipat anu kami pikir nyayogikeun jaminan minimum anu diperyogikeun pikeun ngagunakeun konci anu disebarkeun sacara efektif.

  1. harta kaamanan: silih pangaluaran. Iraha wae, ngan hiji klien nu bisa nahan konci.
  2. Kasadiaan Harta A: Taya deadlocks. Ieu salawasna mungkin mun pamustunganana acquire konci a, sanajan klien nu dikonci sumberdaya gagal atawa lemahna dina bagéan disk béda.
  3. Kasadiaan Harta B: Kasabaran Sesar. Salami seuseueurna titik Redis dijalankeun, klien tiasa nampi sareng ngaleupaskeun konci.

Naha palaksanaan dumasar kana recovery gagalna teu cukup dina hal ieu
Pikeun ngartos naon anu urang badé ningkatkeun, hayu urang analisa kaayaan ayeuna sareng seueur perpustakaan ngonci anu disebarkeun dumasar kana Redis.

Cara pangbasajanna pikeun ngonci sumberdaya nganggo Redis nyaéta nyiptakeun konci dina conto. Ilaharna, konci dijieun kalayan umur kawates, ieu kahontal ngagunakeun fitur kadaluwarsa disadiakeun di Redis, jadi sooner atanapi engké konci ieu dileupaskeun (harta 2 dina daptar urang). Nalika klien kedah ngaleupaskeun sumberdaya, éta ngahapus konci.

Dina glance kahiji, leyuran ieu jalan rada alus, tapi aya masalah: arsitéktur urang nyieun hiji titik gagal. Naon anu lumangsung upami conto host Redis gagal? Hayu urang tambahkeun budak! Sareng kami bakal ngagunakeun éta upami presenter henteu sayogi. Hanjakal, pilihan ieu teu giat. Ku ngalakukeun ieu, urang moal bisa leres nerapkeun sipat silih pangaluaran nu urang kudu mastikeun kaamanan, sabab réplikasi di Redis nyaeta Asynchronous.

Jelas, dina modél kitu kaayaan balapan lumangsung:

  1. Klién A acquires konci dina master.
  2. Master gagal sateuacan entri konci ditransfer ka budak.
  3. Nu pengikutna diangkat jadi pamingpin.
  4. Klién B kéngingkeun konci dina sumber anu sami anu parantos dikonci ku A. PELANGGARAN KAAMANAN!

Kadang-kadang normal pisan yén dina kaayaan khusus, sapertos gagalna, seueur klien tiasa nahan konci dina waktos anu sami. Dina kasus sapertos kitu, solusi dumasar réplikasi tiasa diterapkeun. Upami teu kitu, kami nyarankeun solusi anu dijelaskeun dina tulisan ieu.

Palaksanaan anu leres sareng hiji conto

Sateuacan nyobian nungkulan kakurangan tina konfigurasi single-instance ditétélakeun di luhur, hayu urang ngartos kumaha carana leres nanganan kasus basajan ieu, sabab solusi ieu saleresna valid dina aplikasi dimana kaayaan lomba téh bisa ditarima ti jaman ka jaman, sarta ogé alatan blocking on a conto tunggal dijadikeun dadasar anu dipaké dina algoritma disebarkeun dijelaskeun di dieu.

Pikeun kéngingkeun konci, lakukeun ieu:

SET resource_name my_random_value NX PX 30000

Paréntah ieu masang konci ngan upami éta henteu acan aya (pilihan NX), kalayan periode validitas 30000 milliseconds (pilihan PX). koncina disetel ka "myrandomvalue" Nilai ieu kedah unik dina sadaya klien sareng sadaya pamundut konci.
Dasarna, hiji nilai acak dipaké pikeun aman ngaleupaskeun konci, kalawan naskah ngabejaan Redis: ngan miceun konci lamun eta aya na nilai disimpen dina éta persis naon anu dipiharep. Ieu kahontal nganggo skrip Lua di handap ieu:

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

Ieu penting pikeun nyegah konci anu dicekel ku klien sanés dihapus. Contona, hiji klien bisa meunangkeun konci, lajeng jadi dikonci dina sababaraha operasi nu lasts leuwih panjang batan konci kahiji (supaya konci boga waktu kadaluwarsa), sarta engké cabut konci nu sababaraha klien sejenna geus disimpen.
Ngagunakeun DEL basajan teu aman sabab klien bisa nyabut konci dicekel ku klien sejen. Sabalikna, nalika nganggo skrip di luhur, unggal konci "ditandatanganan" nganggo senar acak, janten ngan ukur klien anu saacanna nempatkeun éta tiasa ngahapus.

Naon kedah string acak ieu? Kuring guessing kudu 20 bait ti / dev / urandom, tapi anjeun bisa manggihan cara kirang mahal sangkan string cukup unik keur kaperluan anjeun. Contona, éta bakal rupa mun siki RC4 kalawan / dev / urandom lajeng ngahasilkeun aliran pseudo-acak ti dinya. Solusi anu langkung saderhana ngalibatkeun kombinasi waktos unix dina resolusi microsecond ditambah ID klien; éta teu jadi aman, tapi meureun nepi ka tugas di paling konteks.

Waktu anu urang dianggo salaku ukuran umur konci disebut "umur konci". Nilai ieu mangrupikeun jumlah waktos sateuacan konci dileupaskeun sacara otomatis sareng jumlah waktos klien kedah ngarengsekeun operasi sateuacan klien sanés tiasa ngonci sumberdaya éta, tanpa leres-leres ngalanggar jaminan pangaluaran silih. Garansi ieu ngan ukur dugi ka sababaraha waktos waktos, anu dimimitian ti mimiti mésér konci.

Janten kami parantos ngabahas cara anu saé pikeun kéngingkeun sareng ngaleupaskeun konci. Sistim nu (lamun urang ngobrol ngeunaan sistem non-disebarkeun diwangun ku hiji conto tunggal tur salawasna sadia) aman. Hayu urang manjangkeun konsép ieu sistem disebarkeun, dimana urang teu boga jaminan misalna.

Algoritma Redlock

Versi anu disebarkeun tina algoritma nganggap yén urang gaduh master N Redis. Titik ieu sagemblengna bebas tina silih, jadi urang teu make réplikasi atawa sistem koordinasi implisit lianna. Kami parantos nutupan kumaha kéngingkeun aman sareng ngaleupaskeun konci dina hiji conto. Kami nganggap yén algoritma, nalika damel sareng hiji conto, bakal ngagunakeun persis metode ieu. Dina conto urang urang nyetel N ka 5, nu mangrupakeun nilai lumrah. Ku kituna, urang kudu make 5 master Redis dina komputer béda atawa mesin virtual pikeun mastikeun yén maranéhna meta umumna bebas unggal lianna.

Pikeun kéngingkeun konci, klien ngalaksanakeun operasi ieu:

  1. Meunangkeun waktos ayeuna dina milidetik.
  2. Sequentially usaha pikeun ménta konci dina sagala instansi N, ngagunakeun ngaran konci sarua jeung nilai acak dina sagala hal. Dina Tahap 2, nalika klien nyetél konci dina dasar per-instance, klien ngagunakeun reureuh pikeun acquire eta anu cukup pondok dibandingkeun jeung waktu sanggeus éta konci otomatis dileupaskeun. Contona, upami durasi blocking nyaeta 10 detik, teras reureuh bisa jadi dina rentang ~5-50 milliseconds. Ieu ngaleungitkeun kaayaan dimana klien tiasa tetep diblokir pikeun waktos anu lami nyobian ngahontal titik Redis anu gagal: upami instancena henteu sayogi, teras urang nyobian nyambung ka conto anu sanés pas mungkin.
  3. Pikeun nyandak konci, klien ngitung sabaraha waktos anu tos lami; Jang ngalampahkeun ieu, eta subtracts tina nilai waktu sabenerna timestamp nu dicandak dina hambalan 1. Lamun jeung ngan lamun klien éta bisa ménta konci dina mayoritas instansi (sahenteuna 3), sarta total waktu nu diperlukeun pikeun meunang konci, kirang ti durasi konci, konci dianggap geus diala.
  4. Lamun konci geus kaala, lila konci dianggap durasi konci aslina dikurangan waktu kaliwat diitung dina hambalan 3.
  5. Upami klien gagal kéngingkeun konci pikeun sababaraha alesan (boh éta henteu tiasa ngonci instan N / 2 + 1, atanapi durasi konci négatip), maka éta bakal nyobian muka konci sadaya instansi (sanaos anu disangka teu tiasa meungpeuk. ).

Algoritma asynchronous?

Algoritma ieu didasarkeun kana anggapan yén, sanaos teu aya jam anu nyingkronkeun dimana sadaya prosés bakal jalan, waktos lokal dina unggal prosés masih ngalir dina laju anu sami, sareng kasalahanna leutik dibandingkeun sareng total waktos saatos konci na. otomatis dileupaskeun. Anggapan ieu mirip pisan sareng kaayaan anu khas pikeun komputer biasa: unggal komputer gaduh jam lokal, sareng urang biasana tiasa ngandelkeun kanyataan yén bédana waktos antara komputer anu béda-béda leutik.

Dina titik ieu, urang kudu leuwih taliti ngarumuskeun aturan silih pangaluaran urang: silih pangaluaran dijamin ngan lamun klien nyekel konci kaluar salila konci valid (nilai ieu dicandak dina hambalan 3), dikurangan sababaraha waktos deui (total sababaraha). milliseconds pikeun ngimbangan bédana waktu antara prosés).

Artikel metot di handap ieu ngabejaan ngeunaan sistem sapertos nu merlukeun koordinasi interval waktu: Leases: mékanisme lepat-toleran efisien pikeun konsistensi cache file disebarkeun.

Coba deui gagal

Lamun klien gagal acquire konci a, eta kudu nyobaan deui sanggeus reureuh acak; Hal ieu dilakukeun pikeun de-nyingkronkeun sababaraha klien nyoba acquire konci dina sumberdaya sarua dina waktos anu sareng (anu bisa ngakibatkeun kaayaan "split-otak" nu euweuh winners). Salaku tambahan, langkung gancang klien nyobian kéngingkeun konci dina seuseueurna instansi Redis, langkung heureut jandela dimana kaayaan pamisah-otak tiasa kajantenan (sareng kirang peryogi percobaan deui). Ku alatan éta, ideally, klien kudu nyoba ngirim paréntah SET mun N instansi sakaligus ngagunakeun multiplexing.

Di dieu patut negeskeun kumaha pentingna pikeun klien anu gagal nampi seuseueurna konci pikeun ngaleupaskeun konci (sawaréh) anu kaala, ku kituna aranjeunna henteu kedah ngantosan konci kadaluwarsa sateuacan konci dina sumberna tiasa kaala deui. (sanajan lamun fragméntasi jaringan lumangsung, sarta klien nu leungiteun kontak jeung instansi Redis, mangka anjeun kudu mayar hiji pinalti kasadiaan bari ngantosan konci kadaluwarsa).

Leupaskeun koncina

Ngaleupaskeun konci mangrupikeun operasi saderhana anu ngan saukur ngabutuhkeun muka konci sadaya instansi, henteu paduli naha klien sigana parantos suksés ngonci hiji instansi.

Pertimbangan Kaamanan

Naha algoritma éta aman? Hayu urang coba ngabayangkeun naon anu lumangsung dina skenario béda.

Pikeun mimitian, hayu urang nganggap yén klien tiasa kéngingkeun konci dina seuseueurna instansi. Unggal conto bakal ngandung konci kalayan umur anu sami pikeun sadayana. Tapi, unggal konci ieu dipasang dina waktos anu béda, janten aranjeunna bakal kadaluwarsa dina waktos anu béda. Tapi, lamun konci kahiji dipasang dina waktu teu leuwih goreng ti T1 (waktu nu urang milih saméméh ngahubungan server kahiji), jeung konci panungtungan dipasang dina hiji waktu teu leuwih goreng ti T2 (waktu nu respon narima. ti server panungtungan), lajeng kami yakin yén konci munggaran dina set anu kadaluwarsa bakal salamet sahenteuna MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT. Sadaya konci anu sanés bakal kadaluwarsa engké, ku kituna urang tiasa mastikeun yén sadaya konci bakal valid sakaligus pikeun sahenteuna waktos ieu.

Dina waktos anu paling konci tetep valid, klien sejen moal bisa acquire konci, saprak N / 2 + 1 SET NX operasi moal bisa hasil lamun N / 2 + 1 konci geus aya. Ku alatan éta, sakali konci geus kaala, mustahil pikeun acquire deui dina momen anu sarua (ieu bakal ngalanggar sipat pangaluaran silih).
Nanging, kami hoyong mastikeun yén sababaraha klien anu nyobian kéngingkeun konci dina waktos anu sami henteu tiasa suksés dina waktos anu sami.

Upami klien parantos ngonci seuseueurna instansi salami atanapi langkung ti durasi konci maksimal, éta bakal nganggap konci éta teu sah sareng muka konci instansi. Kituna, urang ngan kudu tumut kana akun kasus nu klien junun meungpeuk mayoritas instansi dina waktu kirang ti tanggal béakna. Dina hal ieu, ngeunaan argumen di luhur, antukna MIN_VALIDITY euweuh klien kudu bisa reacquire konci. Ku alatan éta, loba klien bakal tiasa konci N / 2 + 1 instansi dina waktos anu sareng (anu ends di ahir tahap 2) ngan lamun waktu konci mayoritas éta leuwih badag batan waktu TTL, nu ngajadikeun konci teu valid.

Naha anjeun tiasa nyayogikeun bukti kaamanan resmi, nunjukkeun algoritma anu sami, atanapi mendakan bug di luhur?

Pertimbangan Aksesibilitas

Kasadiaan sistem gumantung kana tilu ciri utama:

  1. Ngaleupaskeun konci otomatis (sakumaha konci kadaluwarsa): Konci antukna bakal sadia deui pikeun dipaké pikeun konci.
  2. Kanyataan yén klien biasana mantuan silih ku nyoplokkeun konci lamun konci dipikahoyong teu acan kaala, atawa geus kaala jeung pakasaban geus réngsé; janten kamungkinan yén urang henteu kedah ngantosan konci kadaluwarsa pikeun meunangkeun deui konci éta.
  3. Kanyataan yén nalika klien kedah nyobian deui nyandak konci, éta ngantosan waktos anu langkung lami tibatan waktos anu diperyogikeun pikeun nyandak seueur konci. Ieu ngurangan likelihood tina kaayaan pamisah-otak timbul nalika competing sumberdaya.

Sanajan kitu, aya pinalti kasadiaan sarua jeung TTL sahiji bagéan jaringan, jadi lamun aya bagéan contiguous, pinalti bisa jadi teu katangtu. Ieu lumangsung iraha wae klien acquires konci lajeng rips kaluar ka bagean sejen saméméh éta bisa ngaleupaskeun.

Sacara prinsip, tinangtu bagéan jaringan contiguous taya wates, sistem bisa tetep sadia pikeun hiji periode waktu taya wates.

Kinerja, failover sareng fsync

Loba jalma make Redis sabab butuh kinerja server konci tinggi dina watesan latency diperlukeun pikeun acquire sarta ngaleupaskeun konci, sarta jumlah akuisisi / release nu bisa réngsé per detik. Pikeun nyumponan sarat ieu, aya strategi pikeun komunikasi sareng server N Redis pikeun ngirangan latency. Ieu strategi multiplexing (atawa "multiplexing lalaki goréng", dimana stop kontak ditempatkeun dina mode non-blocking, ngirimkeun sagala Paréntah, sarta maca paréntah engké, asumsina yén waktu babak-lalampahan antara klien tur unggal conto sarupa). .

Najan kitu, urang ogé kudu tumut kana akun tinimbangan pakait sareng neundeun data jangka panjang lamun urang narékahan pikeun nyieun modél kalawan recovery dipercaya tina gagal.

Dasarna, pikeun netelakeun masalahna, anggap urang ngonpigurasikeun Redis tanpa neundeun data jangka panjang. Klién junun meungpeuk 3 ti 5 instansi. Salah sahiji instansi anu klien junun meungpeuk ieu restarted, sarta dina momen ieu aya 3 instansi deui pikeun sumberdaya sarua, nu urang bisa meungpeuk, sarta klien sejen bisa, kahareupna meungpeuk conto restarted, violating sipat kaamanan nu. nganggap exclusivity of konci.

Upami anjeun ngaktipkeun data payun (AOF), kaayaan bakal rada ningkat. Contona, anjeun tiasa ngamajukeun server ku ngirim paréntah SHUTDOWN sareng balikan deui. Kusabab operasi kadaluwarsa di Redis sacara semantis dilaksanakeun ku cara anu waktosna terus ngalir sanajan server dipareuman, sadaya syarat urang henteu kunanaon. Ieu normal salami mareuman rutin dipastikeun. Naon anu kudu dilakukeun upami pareum listrik? Upami Redis dikonpigurasi sacara standar, kalayan fsync nyingkronkeun dina disk unggal detik, teras mungkin saatos balikan deui kami moal gaduh konci kami. Sacara téoritis, upami urang hoyong ngajamin kaamanan konci nalika ngamimitian deui, urang kedah ngaktifkeun fsync=always dina setélan pikeun neundeun data jangka panjang. Ieu sagemblengna bakal maéhan kinerja, nepi ka tingkat sistem CP nu tradisional dipaké pikeun aman nerapkeun konci disebarkeun.

Tapi kaayaan leuwih hade tinimbang sigana di glance kahiji. Sacara prinsip, kaamanan algoritma dilestarikan sabab nalika instance di-restart saatos gagal, éta henteu deui milu dina konci anu ayeuna aktip.

Pikeun mastikeun ieu, urang ngan ukur kedah mastikeun yén saatos gagal, conto tetep henteu sayogi pikeun sababaraha waktos langkung seueur tina TTL maksimum anu kami anggo. Ku cara ieu urang bakal antosan dugi ka tanggal béakna sareng sékrési otomatis sadaya konci anu aktip dina waktos gagal.

Ngagunakeun balikan deui nyangsang, prinsipna mah mungkin pikeun ngahontal kaamanan sanajan henteuna sagala kegigihan jangka panjang di Redis. Catet, kumaha oge, ieu tiasa nyababkeun denda pikeun ngalanggar aksésibilitas. Contona, upami seuseueurna instansi gagal, sistem bakal janten teu sadia sacara global pikeun TTL (sareng teu aya sumber anu tiasa diblokir salami ieu).

Urang ningkatkeun kasadiaan algoritma: urang manjangkeun blocking

Lamun karya dipigawé ku klien diwangun ku léngkah leutik, kasebut nyaéta dimungkinkeun pikeun ngurangan durasi konci standar sarta nerapkeun mékanisme pikeun manjangkeun konci. Sacara prinsip, lamun klien sibuk komputasi jeung nilai béakna konci téh picilakaeun low, Anjeun bisa ngirim hiji Aksara Lua ka sadaya instansi nu manjangkeun TTL konci lamun konci masih aya jeung nilai na masih mangrupa nilai acak diala lamun konci ieu kaala.

Klién ngan ukur kedah nganggap hiji konci pikeun dimeunangkeun deui upami parantos tiasa ngonci seuseueurna instansi dina periode validitas.

Leres, sacara teknis algoritmana henteu robih, janten jumlah maksimal usaha anu diulang-ulang pikeun ngonci kedah diwatesan, upami henteu, sipat aksésibilitas bakal dilanggar.

sumber: www.habr.com

Tambahkeun komentar