Redis ашиглан түгжих түгжээ

Хөөе Хабр!

Өнөөдөр бид Redis-ийг ашиглан тархсан түгжээг хэрэгжүүлэх тухай цогц өгүүллийн орчуулгыг та бүхэнд хүргэж, Redis-ийн хэтийн төлөвийн талаар сэдэв болгон ярилцахыг урьж байна. "Номын зохиогч Мартин Клеппманн "Redlock алгоритмын дүн шинжилгээ"Өндөр ачаалалтай програмууд", өгсөн энд.

Түгээмэл түгжээ нь өөр өөр процессууд харилцан үл хамаарах байдлаар хуваалцсан нөөц дээр ажиллах ёстой олон орчинд ашиглагддаг маш ашигтай команд юм.

Redis ашиглан DLM (Тараарсан түгжээ менежер)-ийг хэрхэн хэрэгжүүлэх талаар тайлбарласан олон тооны номын сан, нийтлэлүүд байдаг боловч номын сан бүр өөр өөр арга барилыг ашигладаг бөгөөд тэдгээрийн өгдөг баталгаа нь арай илүү боловсронгуй дизайнтай байх боломжтой зүйлтэй харьцуулахад маш сул байдаг.

Энэ нийтлэлд бид Redis ашиглан тархсан түгжээг хэрхэн хэрэгжүүлэхийг харуулсан нөхцөлт каноник алгоритмыг тайлбарлахыг хичээх болно. гэж нэрлэгддэг алгоритмын талаар ярих болно Улаан түгжээ, энэ нь тархсан түгжигч менежерийг хэрэгжүүлдэг бөгөөд бидний бодлоор энэ алгоритм нь ердийн ганц тохиолдлын аргаас илүү аюулгүй юм. Нийгэмлэг үүнд дүн шинжилгээ хийж, санал хүсэлтээ өгч, илүү төвөгтэй эсвэл өөр төслүүдийг эхлүүлэх цэг болгон ашиглана гэж найдаж байна.

Хэрэгжилт

Алгоритмын тайлбар руу шилжихээсээ өмнө бид бэлэн хэрэгжүүлэлтийн хэд хэдэн холбоосыг өгдөг. Тэдгээрийг лавлагаа болгон ашиглаж болно.

  • Redlock-rb (Ruby-д зориулсан хэрэгжилт). Бас байдаг сэрээ Зөвхөн үүгээр зогсохгүй түгээхэд хялбар болгох үүднээс багц (эрдэнийн чулуу) нэмдэг Redlock-rb.
  • Redlock-py (Python хэрэгжилт).
  • Агаарын түгжээ (Asyncio Python-д зориулсан хэрэгжилт).
  • Redlock-php (PHP-д зориулсан хэрэгжилт).
  • PHPRedisMutex (PHP-д зориулсан өөр хэрэгжүүлэлт)
  • cheprasov/php-redis-lock (түгжээнд зориулсан PHP номын сан)
  • Улаан синк (Go-д зориулсан хэрэгжилт).
  • Редиссон (Java-д зориулсан хэрэгжилт).
  • Redis::DistLock (Perl-д зориулсан хэрэгжилт).
  • Redlock-cpp (C++-д зориулсан хэрэгжилт).
  • Redlock-cs (C#/.NET-д зориулсан хэрэгжилт).
  • RedLock.net (C#/.NET-д зориулсан хэрэгжилт). Асинхрончлол болон түгжих өргөтгөлүүдийн дэмжлэгтэйгээр.
  • ScarletLock (тохируулах боломжтой мэдээллийн сан бүхий C# .NET-д зориулсан хэрэгжилт)
  • Redlock4Net (C# .NET-д зориулсан хэрэгжилт)
  • зангилаа дахин түгжих (NodeJS-д зориулсан хэрэгжилт). Түгжээг сунгах дэмжлэг орно.

Аюулгүй байдал ба бэлэн байдлын баталгаа

Түгээмэл түгжээг үр дүнтэй ашиглахад шаардлагатай хамгийн бага баталгааг хангадаг гэж бид гурван шинж чанараар загвараа загварчлах гэж байна.

  1. Хамгаалалтын өмч: Харилцан хамааралгүй. Ямар ч үед зөвхөн нэг үйлчлүүлэгч түгжээг барьж чадна.
  2. Availability Property A: Ямар ч гацаа байхгүй. Нөөцийг түгжсэн үйлчлүүлэгч бүтэлгүйтсэн эсвэл өөр дискний сегмент дээр буусан ч эцэст нь түгжээ олж авах боломжтой.
  3. Боломжийн шинж чанар B: Алдааг тэсвэрлэх чадвар. Redis-ийн ихэнх зангилаа ажиллаж байгаа үед үйлчлүүлэгчид түгжээ олж авах боломжтой.

Энэ тохиолдолд алдааг сэргээхэд үндэслэсэн хэрэгжилт яагаад хангалтгүй байна вэ?
Бид юу сайжруулах гэж байгаагаа ойлгохын тулд Redis дээр суурилсан ихэнх түгжээтэй номын сангуудын өнөөгийн байдалд дүн шинжилгээ хийцгээе.

Redis ашиглан нөөцийг түгжих хамгийн энгийн арга бол жишээн дээр түлхүүр үүсгэх явдал юм. Дүрмээр бол түлхүүр нь хязгаарлагдмал хугацаанд бүтээгддэг бөгөөд үүнийг Redis-д өгсөн хугацаа дуусах функцийг ашиглан хийдэг тул эрт орой хэзээ нэгэн цагт энэ түлхүүр гарна (манай жагсаалтын 2-р өмч). Үйлчлүүлэгч нөөцийг гаргах шаардлагатай үед энэ нь түлхүүрийг устгадаг.

Эхлээд харахад энэ шийдэл нь маш сайн ажилладаг, гэхдээ нэг асуудал бий: манай архитектур нь нэг л бүтэлгүйтлийн цэгийг бий болгодог. Хост Redis-ийн жишээ амжилтгүй болвол яах вэ? Дараа нь боол нэмье! Хэрэв хөтлөгч байхгүй бол бид үүнийг ашиглах болно. Харамсалтай нь энэ сонголт боломжгүй юм. Үүнийг хийснээр бид Redis-д хуулбарлах нь асинхрон байдаг тул аюулгүй байдлыг хангахад шаардлагатай харилцан үл хамаарах шинж чанарыг зөв хэрэгжүүлэх боломжгүй болно.

Мэдээжийн хэрэг, ийм загварт уралдааны нөхцөл байдал үүсдэг:

  1. Үйлчлүүлэгч А мастер дээр түгжээ олж авдаг.
  2. Түлхүүр оруулгыг боол руу шилжүүлэхээс өмнө мастер амжилтгүй болсон.
  3. Дагагч нь удирдагч болж дэвшдэг.
  4. Үйлчлүүлэгч В нь А аль хэдийн түгжигдсэн ижил нөөцийн түгжээг олж авдаг. АЮУЛГҮЙ БАЙДЛЫГ ЗӨРЧСӨН!

Заримдаа бүтэлгүйтсэн гэх мэт онцгой нөхцөл байдалд олон үйлчлүүлэгч цоожыг нэгэн зэрэг барьж чаддаг нь хэвийн үзэгдэл юм. Ийм тохиолдолд хуулбарлахад суурилсан шийдлийг хэрэглэж болно. Үгүй бол бид энэ нийтлэлд тайлбарласан шийдлийг санал болгож байна.

Нэг тохиолдлоор зөв хэрэгжүүлэлт

Дээр дурдсан ганц инстанцийн тохиргооны дутагдлыг арилгах оролдлого хийхээсээ өмнө энэ шийдэл нь уралдааны нөхцөлийг үе үе хүлээн зөвшөөрдөг програмуудад хүчинтэй байдаг тул энэ энгийн тохиолдлыг хэрхэн зөв зохицуулахыг ойлгоцгооё. ганц жишээ нь энд тайлбарласан тархсан алгоритмд ашиглагдах үндэс болно.

Түгжээ авахын тулд дараах зүйлийг хийнэ үү.

SET resource_name my_random_value NX PX 30000

Энэ тушаал нь түлхүүр байхгүй тохиолдолд л суулгадаг (NX сонголт), хүчинтэй байх хугацаа нь 30000 миллисекунд (PX сонголт). Түлхүүрийг " гэж тохируулсанmyrandomvalue" Энэ утга нь бүх үйлчлүүлэгчид болон түгжих хүсэлтэд өвөрмөц байх ёстой.
Үндсэндээ түгжээг аюулгүй гаргахын тулд санамсаргүй утгыг ашигладаг бөгөөд скрипт нь Redis-д: зөвхөн түлхүүр байгаа тохиолдолд л устгаж, түүнд хадгалагдсан үнэ цэнэ нь хүлээгдэж байсантай ижил байна. Үүнийг дараах Lua скрипт ашиглан хийж болно:

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

Энэ нь өөр үйлчлүүлэгчийн эзэмшиж байсан түгжээг арилгахаас урьдчилан сэргийлэхэд чухал ач холбогдолтой. Жишээлбэл, үйлчлүүлэгч цоож авч, дараа нь эхний түгжээнээс удаан үргэлжилдэг зарим үйлдлээр түгжигдэж (түлхүүр нь дуусах хугацаатай байх болно), дараа нь өөр үйлчлүүлэгчийн тавьсан түгжээг арилгах боломжтой.
Үйлчлүүлэгч өөр үйлчлүүлэгчийн түгжээг арилгах боломжтой тул энгийн DEL ашиглах нь аюултай. Үүний эсрэгээр, дээрх скриптийг ашиглах үед түгжээ бүрийг санамсаргүй тэмдэгт мөрөөр "гарын үсэг зурсан" тул зөвхөн өмнө нь байрлуулсан үйлчлүүлэгч үүнийг арилгах боломжтой.

Энэ санамсаргүй мөр ямар байх ёстой вэ? Энэ нь /dev/urandom-аас 20 байт байх ёстой гэж би таамаглаж байна, гэхдээ та мөрийг өөрийн зорилгод нийцүүлэн өвөрмөц болгох хямд аргуудыг олох боломжтой. Жишээ нь, RC4-ийг /dev/urandom-оор суулгаад түүнээс псевдо-санамсаргүй урсгал үүсгэвэл зүгээр байх болно. Илүү энгийн шийдэл нь микросекундын нарийвчлалтай Unix цаг болон үйлчлүүлэгчийн ID-г хослуулах явдал юм; Энэ нь тийм ч найдвартай биш боловч ихэнх нөхцөл байдалд энэ нь даалгаварт тохирсон байх магадлалтай.

Бидний түлхүүрийн ашиглалтын хугацааг хэмждэг цагийг "түгжээний ашиглалтын хугацаа" гэж нэрлэдэг. Энэ утга нь түгжээг автоматаар гаргахаас өмнөх хугацаа болон өөр үйлчлүүлэгч харилцан үгүйсгэх баталгааг зөрчихгүйгээр тухайн нөөцийг хааж чадахаас өмнө үйлчлүүлэгч ямар нэг үйлдлийг гүйцэтгэхэд шаардагдах хугацаа юм. Энэхүү баталгаа нь зөвхөн түгжээг худалдаж авсан үеэс эхэлдэг тодорхой хугацааны цонхоор хязгаарлагддаг.

Тиймээс бид цоож олж авах, тайлах сайн аргыг ярилцсан. Систем (хэрэв бид нэг бөгөөд үргэлж боломжтой жишээнээс бүрдэх тархаагүй системийн тухай ярьж байгаа бол) аюулгүй. Бидэнд ийм баталгаа байхгүй тархсан системд энэ ойлголтыг өргөжүүлье.

Redlock алгоритм

Алгоритмын тархсан хувилбар нь бидэнд N Redis мастертай гэж үздэг. Эдгээр зангилаа нь бие биенээсээ бүрэн хамааралгүй тул бид хуулбарлах болон бусад далд зохицуулалтын системийг ашигладаггүй. Ганц тохиолдлоор түгжээг хэрхэн найдвартай олж авч, тайлах талаар бид аль хэдийн тайлбарласан. Алгоритм нь нэг жишээтэй ажиллахдаа яг энэ аргыг ашиглах болно гэдгийг бид ердийн зүйл гэж үздэг. Бидний жишээн дээр бид N-ийг 5 болгож тохируулсан бөгөөд энэ нь боломжийн утга юм. Тиймээс бид 5 Redis мастерийг өөр өөр компьютер эсвэл виртуал машин дээр ашиглах шаардлагатай бөгөөд тэдгээр нь бие биенээсээ үл хамааран ажилладаг.

Түгжээ авахын тулд үйлчлүүлэгч дараахь үйлдлүүдийг гүйцэтгэдэг.

  1. Одоогийн цагийг миллисекундээр авна.
  2. Бүх тохиолдолд ижил түлхүүр нэр, санамсаргүй утгыг ашиглан бүх N тохиолдол дээр түгжээ авахыг дараалан оролддог. 2-р шатанд үйлчлүүлэгч түгжээг нэг бүрчлэн тохируулах үед үйлчлүүлэгч түгжээг автоматаар суллах хугацаатай харьцуулахад хангалттай богино хугацаатай саатлыг ашигладаг. Жишээлбэл, блоклох хугацаа 10 секунд бол саатал ~5-50 миллисекундын хооронд байж болно. Энэ нь үйлчлүүлэгч бүтэлгүйтсэн Redis зангилаа руу нэвтрэхийг оролдоход удаан хугацаагаар түгжигдэх нөхцөл байдлыг арилгадаг: хэрэв инстанц боломжгүй бол бид аль болох хурдан өөр инстанттай холбогдохыг оролдоно.
  3. Түгжээ авахын тулд үйлчлүүлэгч хичнээн цаг хугацаа өнгөрснийг тооцоолно; Үүнийг хийхийн тулд энэ нь бодит цагийн утгаас 1-р алхам дээр олж авсан цагийн тэмдгийг хасна. Хэрэв үйлчлүүлэгч ихэнх тохиолдлын (дор хаяж 3) түгжээг авч чадсан бол, үүнд зарцуулсан нийт хугацааг хасна. түгжээг авах, түгжих хугацаанаас бага байвал түгжээг авсан гэж үзнэ.
  4. Хэрэв түгжээ авсан бол түгжээний үргэлжлэх хугацааг 3-р алхамд тооцсон өнгөрсөн хугацааг хассан анхны түгжээний үргэлжлэх хугацаа гэж тооцно.
  5. Хэрэв үйлчлүүлэгч ямар нэг шалтгааны улмаас түгжээ авч чадаагүй бол (энэ нь N/2+1 инстансыг түгжих боломжгүй эсвэл түгжих хугацаа сөрөг байсан) бүх тохиолдлын түгжээг тайлах оролдлого хийх болно (бүх хааж чадахгүй гэж үзсэн байсан ч). ).

Алгоритм асинхрон уу?

Энэ алгоритм нь бүх процессууд дээр ажиллах синхрончлогдсон цаг байхгүй ч процесс тус бүрийн орон нутгийн цаг ойролцоогоор ижил хурдаар урссаар байгаа бөгөөд түгжигдсэн нийт хугацаатай харьцуулахад алдаа бага байна гэсэн таамаглал дээр суурилдаг. автоматаар гаргасан. Энэ таамаглал нь ердийн компьютерт тохиолддог нөхцөл байдалтай маш төстэй юм: компьютер бүр орон нутгийн цагтай байдаг бөгөөд бид өөр өөр компьютеруудын хоорондох цагийн зөрүү бага байдаг гэдэгт найдаж болно.

Энэ үед бид бие биенээ үгүйсгэх дүрмийг илүү нарийн томъёолох ёстой: цоожыг барьж буй үйлчлүүлэгч түгжээ хүчинтэй байх хугацаанд (энэ утгыг 3-р алхамаас олж авсан) гарах үед л харилцан хамааралгүй байх баталгаатай болно. процессуудын хоорондох цагийн зөрүүг нөхөхийн тулд миллисекунд).

Дараах сонирхолтой нийтлэлд цаг хугацааны интервалыг зохицуулах шаардлагатай ийм системүүдийн талаар илүү ихийг өгүүлдэг. Түрээс: тархсан файлын кэшийн тогтвортой байдлыг хангах үр дүнтэй алдааг тэсвэрлэх механизм.

Амжилтгүй бол дахин оролдоно уу

Үйлчлүүлэгч түгжээ авч чадаагүй тохиолдолд санамсаргүй саатал гарсны дараа дахин оролдох ёстой; Энэ нь ижил нөөцийн түгжээг нэгэн зэрэг авахыг оролдож буй олон үйлчлүүлэгчийг синхрончлолгүй болгохын тулд хийгддэг (энэ нь ялагч байхгүй "тархины хуваагдал" байдалд хүргэж болзошгүй). Нэмж дурдахад, үйлчлүүлэгч Redis-ийн ихэнх тохиолдлуудад түгжээг хурдан авахыг оролдох тусам тархи хуваагдах нөхцөл байдал үүсэх цонх нарийсдаг (мөн дахин оролдох хэрэгцээ бага байх болно). Тиймээс хамгийн тохиромжтой нь үйлчлүүлэгч олон талт үйлдлийг ашиглан SET командуудыг N тохиолдол руу нэгэн зэрэг илгээхийг оролдох хэрэгтэй.

Ихэнх түгжээг авч чадаагүй үйлчлүүлэгчид нөөцийн түгжээг дахин авахаас өмнө түлхүүрийн хугацаа дуусахыг хүлээх шаардлагагүй (хэсэгчилсэн) авсан түгжээг суллах нь хэчнээн чухал болохыг энд онцлон тэмдэглэх нь зүйтэй. (хэрэв сүлжээний хуваагдал үүсч, үйлчлүүлэгч Redis-тай холбоо тасарсан бол түлхүүрийн хугацаа дуусахыг хүлээх зуураа бэлэн байдлын торгууль төлөх ёстой).

Түгжээг суллана

Түгжээг суллах нь үйлчлүүлэгч тодорхой нэг инстансыг амжилттай түгжсэн эсэхээс үл хамааран бүх тохиолдлын түгжээг тайлах шаардлагатай энгийн үйлдэл юм.

Аюулгүй байдлын талаар анхаарах зүйлс

Алгоритм аюулгүй юу? Өөр өөр хувилбаруудад юу тохиолдохыг төсөөлөхийг хичээцгээе.

Эхлэхийн тулд үйлчлүүлэгч ихэнх тохиолдлуудад түгжээ авч чадсан гэж үзье. Инстанц бүр нь бүгдийн адил ашиглалтын хугацаатай түлхүүрийг агуулна. Гэсэн хэдий ч эдгээр түлхүүрүүд тус бүрийг өөр өөр хугацаанд суулгасан тул өөр өөр хугацаанд хүчинтэй байх болно. Гэхдээ хэрэв эхний түлхүүрийг T1-ээс муугүй хугацаанд суулгасан бол (эхний сервертэй холбогдохын өмнө бидний сонгосон цаг), сүүлчийн түлхүүрийг T2-ээс муугүй хугацаанд суулгасан бол (хариулт хүлээн авсан цаг). сүүлчийн серверээс), дараа нь хугацаа нь дууссан багцын эхний түлхүүр дор хаяж амьд үлдэнэ гэдэгт бид итгэлтэй байна. MIN_VALIDITY=TTL-(T2-T1)-CLOCK_DRIFT. Бусад бүх түлхүүрүүдийн хугацаа хожим дуусах тул бид бүх түлхүүрүүд дор хаяж энэ удаад нэгэн зэрэг хүчинтэй байх болно гэдэгт итгэлтэй байж болно.

Ихэнх түлхүүрүүд хүчинтэй байх хугацаанд N/2+1 SET NX үйлдлүүд аль хэдийн байгаа бол 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 дээд хэмжээнээс бага зэрэг давсан хугацаанд тухайн жишээг ашиглах боломжгүй хэвээр байгаа эсэхийг баталгаажуулах хэрэгтэй. Ингэснээр бид бүтэлгүйтлийн үед идэвхтэй байсан бүх түлхүүрүүд дуусах хугацаа, автоматаар гарах хүртэл хүлээх болно.

Хойшлогдсон дахин ачааллыг ашигласнаар Redis-д удаан хугацааны турш ажиллахгүй байсан ч аюулгүй байдлыг хангах нь зарчмын хувьд боломжтой юм. Гэхдээ энэ нь хүртээмжийг зөрчсөн тохиолдолд торгууль ногдуулж болзошгүйг анхаарна уу. Жишээлбэл, ихэнх тохиолдлууд амжилтгүй болвол систем нь TTL-д ажиллах боломжгүй болно (мөн энэ хугацаанд ямар ч нөөцийг хаах боломжгүй).

Бид алгоритмын хүртээмжийг нэмэгдүүлдэг: бид блоклох хугацааг сунгадаг

Үйлчлүүлэгчдийн гүйцэтгэсэн ажил нь жижиг алхмуудаас бүрддэг бол анхдагч түгжээний хугацааг багасгаж, түгжээг сунгах механизмыг хэрэгжүүлэх боломжтой. Зарчмын хувьд, хэрэв үйлчлүүлэгч тооцоо хийх завгүй байгаа бөгөөд түгжээний хүчинтэй байх хугацаа нь аюултай бага байвал түлхүүр хэвээр байгаа бөгөөд түүний үнэ цэнэ нь санамсаргүй утгыг ашиглах үед олж авсан түлхүүрийн TTL-ийг өргөтгөх бүх тохиолдлуудад Lua скриптийг илгээж болно. цоож авсан.

Үйлчлүүлэгч хүчинтэй байх хугацаанд ихэнх тохиолдлуудыг түгжиж чадсан тохиолдолд л түгжээг дахин авах боломжтой гэж үзэх ёстой.

Үнэн бол техникийн хувьд алгоритм өөрчлөгддөггүй тул түгжээ олж авах оролдлогын хамгийн их тоог хязгаарлах ёстой, эс тэгвээс хүртээмжийн шинж чанарууд зөрчигдөх болно.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх