Ця стаття є дзеркальною статтею машинного перекладу, будь ласка, натисніть тут, щоб перейти до оригінальної статті.

Вид: 10939|Відповідь: 1

Кілька способів використання розподілених замків (redis, zookeeper, база даних)

[Копіювати посилання]
Опубліковано 30.08.2018 15:04:32 | | | |
П: Один сервісний сервер, одна база даних, операція: запит на поточний баланс користувача, віднімання 3% поточного балансу як плату за обробку

Синхронізовано
замок
DB Lock

Питання: Два сервісні сервери, одна база даних, операція: запит на поточний баланс користувача, віднімання 3% поточного балансу як плату за обробку
Розподілені шлюзи

Який розподілений замок нам потрібен?
Він може гарантувати, що в розподіленому кластері застосунків один і той самий метод може виконуватися лише одним потоком на одній машині одночасно.

Якщо цей замок є реентрантним (уникайте глухих кутів)

Цей замок найкраще підходить для блокування (подумайте, чи хочете ви його відповідно до потреб вашого бізнесу)

Цей замок найкраще має бути справедливим (подумайте, чи хочете ви його відповідно до потреб бізнесу)

Доступні функції фіксації та блокування

Ефективність замків захоплення та відпускання краща

1. Розподілені блокування на основі баз даних

Розподілені блокування на основі реалізацій на основі таблиць

Коли ми хочемо заблокувати метод, виконуємо наступний SQL:
вставити у methodLock(method_name,desc) значення ('method_name','desc')
Оскільки ми встановили обмеження на унікальність method_name, якщо одночасно подається кілька запитів до бази даних, база даних гарантує, що лише одна операція може бути успішною, тоді можна припустити, що потік, який успішно отримав метод блокування і може виконати вміст тіла методу.

Коли метод виконується, якщо ви хочете зняти блокування, потрібно виконати наступний Sql:
видалити з methodLock, де method_name ='method_name'

Ця проста реалізація вище має такі проблеми:

  • Цей блок залежить від доступності бази даних, яка є однією точкою і призводить до того, що бізнес-система стане недоступною, коли база даних буде закрита.
  • Цей блокування не має терміну дії, і після невдалої операції розблокування запис блокування залишається в базі даних, а інші потоки більше не зможуть отримати цей блокування.
  • Це блокування може бути неблокуючим лише тому, що операція вставки даних безпосередньо повідомляє про помилку після невдачі вставки. Потоки, які не отримують блокування, не потраплять у чергу і повинні знову активувати операцію захоплення блокування, щоб отримати блокування знову.
  • Замок не є реентрантним, і той самий потік не може отримати замок знову, доки його не буде звільнено. Тому що дані в даних вже існують.
  • Цей замок — несправедливий, і всі нитки, що чекають на замок, конкурують за нього випадковістю.


Звісно, ми можемо вирішити вищезазначені проблеми й іншими способами.

  • Чи є база даних однією точкою? Створіть дві бази даних, і дані будуть синхронізовані в обох напрямках. Після того, як покладіть слухавку, швидко перейдіть до резервної бібліотеки.
  • Немає терміну придатності? Просто виконуйте заплановане завдання, щоб регулярно очищати дані тайм-ауту в базі даних.
  • Не блокує? Робіть певний цикл, поки вставка не буде успішною, а потім результат повернеться.
  • Нереентрант? Додайте поле до таблиці бази даних для запису інформації про хост і поток машини, яка зараз отримує блокування, а наступного разу, коли отримаєте блокування, спочатку запитайте до бази даних, якщо дані про хост і потік поточної машини є в базі, ви можете безпосередньо призначити блокування йому.
  • Несправедливо? Створіть ще одну проміжну таблицю для фіксації всіх потоків, що чекають на блокування, і відсортуйте їх за часом створення, і лише перша створена таблиця може отримати замок


Розподілені замки на основі ексклюзивних замків

Окрім додавання та видалення записів у таблиці даних, розподілені блокування також можуть бути реалізовані за допомогою блокувань, що йдуть у комплекті з даними.

Ми також використовуємо таблицю даних, яку щойно створили. Розподілені блокування можуть бути реалізовані через ексклюзивні блокування баз даних. Рушій InnoDB на базі MySQL може використовувати такі методи для реалізації операцій блокування:

Якщо додати оновлення після запиту, база даних додасть ексклюзивне блокування до таблиці бази даних під час процесу запиту. Коли до запису додається ексклюзивний замок, інші потоки більше не можуть додати ексклюзивний замок до запису на цій лінії.

Можна припустити, що потік, який отримує ексклюзивне блокування, може отримати розподілене блокування, і коли блокування отримано, бізнес-логіку методу можна виконати, а потім розблокувати за допомогою наступних методів:

публічний void unlock(){ connection.commit(); }

через connection.commit(); операція для розблокування замка.

Цей метод ефективно вирішує згадані вище проблеми неможливості розблокувати замок і заблокувати його.

Блокування замків? Оператор для оновлення повертається одразу після успішного виконання і залишається заблокованим, доки не завершиться успішно.

Сервіс відключений після блокування, не можна звільнити? Таким чином, база даних знімає блокування сама після відключення сервісу.

Однак це все ще не вирішує безпосередньо проблему одноточкової бази даних, реентрантності та справедливого блокування.

Підсумовуючи спосіб використання бази даних для реалізації розподілених блокувань, обидва з яких базуються на таблиці в базі даних: одне — визначити, чи існує блокування за наявністю записів у таблиці, а інше — реалізувати розподілені блокування через ексклюзивне блокування бази даних.

Переваги розподіленого блокування в базах даних

Безпосередньо за допомогою бази даних це легко зрозуміти.

Недоліки впровадження розподілених блокувань у базах даних

Виникають різні проблеми, і все рішення ставатиме дедалі складнішим у процесі розв'язання проблеми.

Керування базою даних вимагає певних накладних витрат, а також враховувати питання продуктивності.

2. Розподілені блокування на основі кешу

Порівняно з розподіленим блокуванням на основі бази даних, реалізація на основі кешу працюватиме краще за продуктивністю.

Наразі існує багато продуктів для зрілого кешування, зокрема Redis, memcached тощо. Тут ми візьмемо Redis як приклад для аналізу схеми використання кешу для реалізації розподілених блокувань.

В Інтернеті існує багато пов'язаних статей про реалізацію розподілених блокувань на основі Redis, а основний метод реалізації — використання методу Jedis.setNX.

Існує також кілька проблем із наведеною вище реалізацією:

1. Проблема з одним балом.

2. Цей блокування не має терміну дії, якщо операція розблокування не завершується, запис блокування постійно перебуватиме в redis, і інші потоки більше не можуть отримати блокування.

3. Цей замок може бути лише неблокуючим і повертається безпосередньо незалежно від успіху чи невдачі.

4. Цей замок не є реентранним, після отримання нитки він не може знову отримати замок перед тим, як його відпустити, оскільки використаний ключ уже існує в redis. операції setNX більше не можуть виконуватися.

5. Це блокування несправедливе, всі потоки, що чекають, починають операції setNX одночасно, і щасливі потоки можуть отримати блокування.

Звісно, є й способи її розв'язати.

  • Сьогодні основні сервіси кешування підтримують розгортання кластерів для вирішення задач однієї точки через кластеризацію.
  • Немає терміну придатності? Метод setExpire для redis підтримує вхідний час закінчення, і дані автоматично видаляються після досягнення цього часу.
  • Не блокує? під час багаторазової страти.
  • Хіба неможливо знову увійти? Після того, як потік отримає блокування, збережіть поточну інформацію про хост і потік, і перевірте, чи є ви власником поточного замка, перш ніж отримати його наступного разу.
  • Несправедливо? Помістіть усі очікувані потоки в чергу перед тим, як потік отримає блокування, а потім отримати замок за принципом «перший прийшов — перший вийшов».


Політика синхронізації кластера redis займає час, і можливо, що потік A отримує блокування після успішного встановлення NX, але це значення не оновлюється до сервера, де потік B виконує setNX, що спричинить проблеми з паралелізмом.

Сальваторе Санфіліппо, автор redis, запропонував алгоритм Redlock, який реалізує розподілене управління блокуванням (DLM), що є більш безпечним і надійним, ніж один вузол.

Алгоритм Redlock передбачає, що існує N redis вузлів, які незалежні один від одного, зазвичай встановлені на N=5, і ці N вузлів працюють на різних машинах для збереження фізичної незалежності.

Кроки алгоритму такі:

1. Клієнт отримує поточний час у мілісекундах.
2. Клієнт намагається отримати блокування з N вузлів (кожен вузол отримує блокування так само, як і кеш-блокування, згадане раніше), і N вузлів отримують блокування з однаковим ключем і значенням. Клієнт має встановити тайм-аут доступу до інтерфейсу, і час тайм-ауту інтерфейсу має бути значно меншим, ніж час блокування, наприклад, час автоматичного звільнення блокування становить 10 секунд, тоді час інтерфейсу встановлений приблизно на 5-50 мс. Це дозволяє якнайшвидше виходити на час доступу до вузла redis після його відключення і зменшує звичайне використання блокування.
3. Клієнт обчислює, скільки часу потрібно, щоб отримати блокування, віднімаючи час, отриманий на першому кроці, до поточного часу, і лише коли клієнт отримує більше 3 вузлів блокування, а час на отримання замка менший за час тайм-ауту замка, клієнт отримує розподілений замок.
4. Час, який клієнт отримає замок, дорівнює встановленому часу часу блокування мінус час, витрачений на отримання замка, розрахований на етапі 3.
5. Якщо клієнт не зможе отримати блокування, клієнт по черзі видаляє всі блокування.
За допомогою алгоритму Redlock можна гарантувати, що розподілений сервіс блокування все ще працюватиме навіть при підключенні до 2 вузлів, що значно покращує доступність порівняно з попереднім блокуванням бази даних і кешом.

Однак експерт із розподілених даних написав статтю «Як зробити розподілене блокування», у якій ставив під сумнів коректність Redlock.

Експерт зазначив, що при розгляді розподілених замків слід враховувати два аспекти: продуктивність і коректність.

Якщо ви використовуєте високопродуктивне розподілене блокування і правильність не потрібна, тоді достатньо використовувати кеш-блокування.

Якщо ви використовуєте високонадійний розподілений замок, то потрібно враховувати суворі питання надійності. Редлок, навпаки, не відповідає правильним вимогам. Чому ні? Експерти перелічують кілька аспектів.

Сьогодні багато мов програмування використовують віртуальні машини з функціями GC, у Full GC програма зупиняє обробку GC, іноді Full GC займає багато часу, і навіть програма має кілька хвилин затримки, у статті наведено приклад HBase, HBase, іноді GC на кілька хвилин, що призводить до тайм-ауту оренди. Наприклад, на рисунку нижче клієнт 1 отримує блокування і ось-ось почне обробляти спільний ресурс, а коли він готується до обробки спільного ресурсу, Full GC відбувається до закінчення терміну дії блокування. Таким чином, клієнт 2 знову отримує блокування і починає працювати з спільним ресурсом. Коли клієнт 2 обробляє, клієнт 1 завершує повний GC і починає обробку спільних ресурсів, так що обидва клієнти обробляють спільні ресурси.



Експерти запропонували рішення, як показано на рисунку нижче, це схоже на MVCC, який приносить токен до блокування, токен — це концепція версії, кожного разу, коли операція блокується після завершення, токен додається 1, приносити токен при обробці спільних ресурсів, лише вказана версія токена може обробляти спільний ресурс.



Потім експерт також зазначив, що алгоритм покладається на місцевий час, а Redis використовує метод getTimeOfDay для визначення часу замість монотонного годинника при обробці терміну дії ключа, що також призводить до неточностей у часі. Наприклад, у сценарії два клієнти 1 і клієнт 2 мають 5 вузлів redis (A, B, C, D і E).

1. Клієнт 1 успішно отримує блокування від A, B і C і отримує тайм-аут мережі блокування від D і E.
2. Такт вузла C неточний, що спричиняє тайм-аут блокування.
3. клієнт 2 успішно отримує блокування від C, D і E і отримує тайм-аут мережі блокування з A і B.
4. Таким чином, і клієнт 1, і клієнт 2 отримують блокування.
Підсумовуючи два моменти, які експерти висловлюють щодо недоступності Редлока:

1. GC та інші сценарії можуть виникнути в будь-який момент, через що клієнт отримує блокування, а тайм-аут обробки змушує іншого клієнта отримати блокування. Експерти також запропонували рішення для використання самоінкрементуючих токенів.
2. Алгоритм покладається на локальний час, і годинник буде неточним, через що два клієнти отримують блокування одночасно.
Отже, висновок експертів полягає в тому, що Redlock може нормально працювати лише у межах обмеженої затримки мережі, обмеженого переривання програми та обмеженого діапазону тактових помилок, але межі цих трьох сценаріїв не можуть бути підтверджені, тому експерти не рекомендують використовувати Redlock. Для сценаріїв із високими вимогами до коректності експерти рекомендують Zookeeper, про який буде обговорено пізніше використання Zookeeper як розподіленого замка.

Відповідь автора Redis

Автор Redis відповів, написавши блог після перегляду статті експерта. Автор ввічливо подякував експерту, а потім висловив незгоду з його поглядом.

Я попросив аналіз у оригінальній специфікації Redlock тут:http://redis.io/topics/distlock.Тож дякую, Мартіне. Однак я не погоджуюся з таким аналізом.


Обговорення автором REDIS щодо використання токенів для розв'язання проблеми тайм-ауту блокування можна підсумувати у наступних п'яти пунктах:

Пункт 1: використання розподілених блокувань зазвичай полягає в тому, що немає іншого способу контролювати спільні ресурси, експерти використовують токени для забезпечення обробки спільних ресурсів, тоді розподілені блокування не потрібні.
Пункт 2: Для генерації токенів, щоб забезпечити надійність токенів, отриманих різними клієнтами, сервіс, що генерує токени, все одно потребує розподілених блокувань для забезпечення надійності сервісу.
Пункт 3: щодо того, як експерти кажуть про самоінкрементуючі токени, автор Redis вважає, що це абсолютно непотрібно: кожен клієнт може згенерувати унікальний uuid як токен і встановити спільний ресурс у стані, який може обробити лише клієнт з uuid, щоб інші клієнти не могли обробляти спільний ресурс, доки клієнт, який отримує блокування, не зніме блокування.
Як показано на рисунку вище, якщо клієнт токена 34 надсилає GC під час процесу запису і спричиняє тайм-аут блокування, інший клієнт може отримати блокування токена 35 і почати запис знову, що призведе до конфлікту блокування. Отже, порядок токенів не може бути поєднаний із спільними ресурсами.
Пункт 5, автор redis вважає, що в більшості випадків розподілені блокування використовуються для вирішення проблем оновлення у нетранзакційних сценаріях. Автор має на увазі, що є ситуації, коли важко поєднувати токени для обробки спільних ресурсів, тому доводиться покладатися на блокування ресурсів і їх обробку.
Ще одна проблема з годинником, про яку говорять експерти, — автори Redis також дають пояснення. Якщо час, необхідний для отримання замка, надто довгий і перевищує стандартний тайм-аут, клієнт не може отримати замок у цей момент, і експерти не запропонують прикладів.

Особисті почуття

Перша проблема, яку я підсумовую, полягає в тому, що після отримання клієнтом розподіленого блокування блокування може бути звільнене після тайм-ауту під час обробки клієнтом. Раніше, коли йшлося про тайм-аут, встановлений блокуванням бази даних у 2 хвилини, якщо завдання займає блокування ордеру більше 2 хвилин, інший торговий центр може отримати це блокування, щоб обидва торгові центри могли одночасно обробляти один і той самий ордер. Зазвичай завдання обробляється за секунди, але іноді тайм-аут, встановлений при приєднанні до RPC-запиту, занадто довгий, і в завданні є кілька таких запитів, тоді, ймовірно, час автоматичного розблокування буде перевищено. Якщо ми пишемо на Java, може бути повний GC посередині, тож після розблокування блокування після тайм-ауту клієнт не може його сприйняти, що є дуже серйозною проблемою. Я не думаю, що це проблема самого замка, якщо будь-який розподілений замок, згаданий вище, має характеристики тайм-ауту, така проблема виникає. Якщо ви використовуєте функцію блокування тайм-ауту, клієнт повинен встановити час блокування і діяти відповідно, замість того, щоб продовжувати обробку спільного ресурсу. Алгоритм Redlock повертає час блокування, який клієнт може зайняти після отримання блокування, і клієнт повинен обробити цей час, щоб зупинити завдання після цього часу.

Друга проблема полягає в тому, що розподілені експерти не розуміють Redlock. Ключова особливість Redlock полягає в тому, що час отримання замка — це загальний час, який замок за замовчуванням входить на тайм-аут, мінус час, необхідний для отримання замка, тому час, необхідний клієнту для обробки, є відносним незалежно від місцевого часу.

З цієї точки зору правильність Redlock може бути цілком гарантована. Ретельний аналіз Redlock, порівняно з redis вузла, головною особливістю Redlock є вища надійність, що є важливою рисою в деяких сценаріях. Але, на мою думку, Redlock витратили занадто багато грошей, щоб досягти надійності.

  • По-перше, потрібно розгорнути 5 вузлів, щоб зробити Redlock більш надійним.
  • Потім потрібно запросити 5 вузлів, щоб отримати блокування, і за допомогою методу Future спочатку можна одночасно запросити до 5 вузлів, а потім зібрати результат відповіді, що скоротить час відповіді, але все одно займає більше часу, ніж блокування redis з одним вузлом.
  • Тоді, оскільки потрібно отримати більше ніж 3 із 5 вузлів, може виникнути конфлікт замків, тобто всі отримали 1-2 замки, і в результаті ніхто не може отримати замок, у цій задачі автор Редіс запозичує суть алгоритму рафту: через випадкове зіткнення час конфлікту можна значно скоротити, але цю проблему неможливо дуже добре уникнути, особливо коли замок отримано вперше, і часові витрати на отримання замка зростають.
  • Якщо 2 з 5 вузлів вимкнені, доступність блокування значно зменшиться, по-перше, потрібно чекати на завершення результатів цих двох збитих вузлів, перш ніж повернутися, а вузлів лише 3, і клієнт повинен отримати блокування всіх трьох вузлів, що також складніше.
  • Якщо існує мережевий розділ, може виникнути ситуація, коли клієнт ніколи не зможе отримати блокування.


Після аналізу багатьох причин, я вважаю, що найважливішим у проблемі Redlock є те, що Redlock вимагає від клієнтів забезпечення послідовності записів, а бекенд-5 вузлів є повністю незалежними, і всі клієнти мають керувати цими 5 вузлами. Якщо лідер є серед 5 вузлів, клієнт може синхронізувати дані лідера, доки клієнт отримує блокування від лідера, щоб уникнути проблем, таких як розбиття, тайм-аути та конфлікти. Тому, щоб забезпечити коректність розподілених блокувань, я вважаю, що використання розподіленої координаційної служби з високою послідовністю може краще вирішити проблему.

Знову виникає питання: скільки часу слід встановити термін дії? Як встановити час інвалідації, занадто короткий, і блокування автоматично знімається до виконання методу, тоді виникають проблеми з паралельністю. Якщо це займе занадто багато часу, інші різьби, які фіксують, можуть чекати довго.

Ця проблема також існує з використанням баз даних для реалізації розподілених блокувань.

Нинішній основний підхід до цієї проблеми полягає в тому, щоб встановити короткий тайм-аут для кожного отриманого блокування і запускати потік для оновлення часу блокування щоразу, коли він наближається до тайм-ауту. Закінчуйте цю тему одночасно з відпусканням замка. Наприклад, Redisson, офіційний розподілений компонент блокування Redis, використовує це рішення.

Переваги кешування для реалізації розподілених блокувань
Гарна гра.

Недоліки використання кешування для реалізації розподілених блокувань
Впровадження надто відповідальне, є надто багато факторів, які потрібно враховувати.

Розподілені замки на основі реалізації Zookeeper

Розподілені блокування на основі тимчасово впорядкованих вузлів Zookeeper.

Загальна ідея полягає в тому, що коли кожен клієнт блокує метод, унікальний миттєво впорядкований вузол генерується в каталозі заданого вузла, що відповідає методу на zookeeper. Спосіб визначити, чи отримати блокування, простий — потрібно лише визначити той, у кого найменший серійний номер у впорядкованому вузлі. Коли блокування знято, просто видаліть миттєвий вузол. Водночас це дозволяє уникнути проблеми глухих кутів, спричинених простоєм сервісу, які не можуть бути відпущені.

Подивимось, чи зможе Zookeeper вирішити згадані раніше проблеми.

  • Замок не відкривається? Використання Zookeeper ефективно вирішує проблему незвільнення блокування, оскільки при створенні блокування клієнт створює тимчасовий вузол у ZK, і коли клієнт отримує блокування і раптово його вимикає (сесійне з'єднання розірвано), тимчасовий вузол автоматично видаляється. Інші клієнти можуть знову отримати замок.
  • Замки, що не блокують? Після зміни вузла Zookeeper повідомляє клієнта, і клієнт може перевірити, чи є вузол, який він створив, найменшим порядковим номером серед усіх вузлів.
  • Не можеш повернутися? Коли клієнт створює вузол, він безпосередньо записує інформацію про хост і поточний потік поточного клієнта на вузол, і наступного разу, коли ви хочете отримати блокування, ви можете порівняти їх із даними поточного найменшого вузла. Якщо інформація збігається з вашою власною, тоді ви можете безпосередньо отримати замок, а якщо він інший, створити тимчасовий послідовний вузол для участі в черзі.


Знову виникає питання: ми знаємо, що Zookeeper потрібно розгортати у кластерах, чи виникнуть проблеми синхронізації даних, як у кластерах Redis?

Zookeeper — це розподілений компонент, який гарантує слабку узгодженість, тобто остаточну послідовність.

Zookeeper використовує протокол синхронізації даних, який називається Quorum Based Protocol. Якщо в кластері Zookeeper є N серверів Zookeeper (N зазвичай непарний, 3 можуть відповідати надійності даних і мають високу продуктивність читання та запису, а 5 мають найкращий баланс між надійністю даних і продуктивністю читання/запису), тоді операція запису користувача спочатку синхронізується з серверами N/2 + 1, а потім повертається користувачу, що спонукає користувача успішно записувати. Протокол синхронізації даних на основі протоколу Quorum Based визначає послідовність потужності, яку Zookeeper може підтримувати.

У розподіленому середовищі зберігання даних, яке відповідає сильній узгодженості, фактично відсутнє, і воно вимагає, щоб усі вузли оновлювалися синхронно при оновленні даних одного вузла. Ця стратегія синхронізації з'являється в базі даних синхронної реплікації майстер-слейв. Однак така стратегія синхронізації надто сильно впливає на продуктивність запису і рідко застосовується на практиці. Оскільки Zookeeper записує N/2+1 вузли синхронно, а N/2 не оновлюються синхронно, Zookeeper не є дуже послідовним.

Операція оновлення даних користувача не гарантує, що наступні читання прочитають оновлене значення, але зрештою покаже узгодженість. Жертва узгодженістю не означає повне ігнорування послідовності даних, інакше дані є хаотичними, тому незалежно від того, наскільки висока доступність системи, незалежно від того, наскільки хороший розподіл — це не має жодної цінності. Жертвувати послідовністю — це просто те, що сильна послідовність у реляційних базах даних більше не потрібна, але доки система зможе досягти її в кінцевому підсумку.

Питання з одним балом? Використання Zookeeper може ефективно розв'язати задачу однієї точки, ZK розгортається кластерами, доки більше половини машин у кластері виживають, сервіс можна надати зовнішньому світу.

Питання справедливості? Використання Zookeeper може вирішити проблему справедливих замків, тимчасові вузли, створені клієнтом у ZK, є впорядкованими, і щоразу, коли блокування знімається, ZK може повідомити найменший вузол про його отримання, забезпечуючи справедливість.

Знову виникає питання: ми знаємо, що Zookeeper потрібно розгортати у кластерах, чи виникнуть проблеми синхронізації даних, як у кластерах Redis?

Zookeeper — це розподілений компонент, який гарантує слабку узгодженість, тобто остаточну послідовність.

Zookeeper використовує протокол синхронізації даних, який називається Quorum Based Protocol. Якщо в кластері Zookeeper є N серверів Zookeeper (N зазвичай непарний, 3 можуть відповідати надійності даних і мають високу продуктивність читання та запису, а 5 мають найкращий баланс між надійністю даних і продуктивністю читання/запису), тоді операція запису користувача спочатку синхронізується з серверами N/2 + 1, а потім повертається користувачу, що спонукає користувача успішно записувати. Протокол синхронізації даних на основі протоколу Quorum Based визначає послідовність потужності, яку Zookeeper може підтримувати.

У розподіленому середовищі зберігання даних, яке відповідає сильній узгодженості, фактично відсутнє, і воно вимагає, щоб усі вузли оновлювалися синхронно при оновленні даних одного вузла. Ця стратегія синхронізації з'являється в базі даних синхронної реплікації майстер-слейв. Однак така стратегія синхронізації надто сильно впливає на продуктивність запису і рідко застосовується на практиці. Оскільки Zookeeper записує N/2+1 вузли синхронно, а N/2 не оновлюються синхронно, Zookeeper не є дуже послідовним.

Операція оновлення даних користувача не гарантує, що наступні читання прочитають оновлене значення, але зрештою покаже узгодженість. Жертва узгодженістю не означає повне ігнорування послідовності даних, інакше дані є хаотичними, тому незалежно від того, наскільки висока доступність системи, незалежно від того, наскільки хороший розподіл — це не має жодної цінності. Жертвувати послідовністю — це просто те, що сильна послідовність у реляційних базах даних більше не потрібна, але доки система зможе досягти її в кінцевому підсумку.

Чи відповідає Zookeeper причинно-наслідковій послідовності, залежить від того, як програмується клієнт.

Практики, які не задовольняють причинну послідовність

  • Процес A записує дані у /z Zookeeper і успішно повертається
  • Процес A інформує процес B, що A змінив дані /z
  • B зчитує дані Zookeeper /z
  • Оскільки сервер доглядача зоопарку, підключений до B, міг не бути оновлений письмовими даними A, то B не зможе прочитати дані A


Практики, що відповідають причинно-наслідковій послідовності

  • Процес B слухає зміни даних у /z на Zookeeper
  • Процес A записує фрагмент даних у /z Zookeeper, і перед успішним поверненням Zookeeper повинен зателефонувати слухачу, зареєстрованому на /z, і лідер повідомить B про зміну даних
  • Після того, як метод відповіді на подію процесу B отримує змінені дані, тож B точно зможе отримати змінене значення
  • Причинна послідовність тут стосується причинної узгодженості між лідером і B, тобто лідер повідомляє дані про зміну


Другий механізм прослуховування подій також є методом, який слід використовувати для правильного програмування Zookeeper, тому Zookeeper має відповідати причинно-наслідковій послідовності

Тому, коли ми впроваджуємо розподілені блокування на базі Zookeeper, слід використовувати практику задоволення причинно-наслідкової послідовності, тобто потоки, які чекають на блокування, слухають зміни в Zookeeper, а коли замок буде звільнений, Zookeeper повідомляє поток очікування, який відповідає умовам справедливого блокування.

Ви можете безпосередньо скористатися клієнтом третьої бібліотеки Zookeeper, який інкапсулює сервіс реентрантного блокування.

Розподілені блокування, реалізовані на ZK, здаються саме тим, що ми очікували від розподіленого блокування на початку цієї статті. Однак це не так, і розподілене блокування, реалізоване Zookeeper, насправді має недолік — продуктивність може бути не такою високою, як у кешуючого сервісу. Тому що кожного разу під час створення та звільнення блокування миттєві вузли потрібно динамічно створювати та знищувати, щоб реалізувати функцію блокування. Створення та видалення вузлів у ZK можна виконувати лише через сервер лідера, після чого дані передаються всім машинам-супутникам.

Переваги використання Zookeeper для реалізації розподілених замків
Ефективно розв'язують проблеми з однією точкою, проблеми з невходом у атмосферу, проблеми з неблокуванням і відмовою блокування при розблокуванні. Це відносно просто реалізувати.

Недоліки використання Zookeeper для реалізації розподілених замків
Продуктивність не така висока, як використання кешу для реалізації розподілених блокувань. Потрібне розуміння принципів ZK.

Порівняння трьох варіантів

З точки зору легкості розуміння (від низького до високого)
База даних > кеш > Zookeeper

З точки зору складності реалізації (від низького до високого)
Бази даних Zookeeper > кеш >

З точки зору продуктивності (від високого до низького)
Кешування > Zookeeper > база даних

З точки зору надійності (від високого до низького)
Бази даних Zookeeper > кеш >





Попередній:Різниця між весняними @Bean та @Service анотаціями
Наступний:Відеоурок вивчення мови C з нуля
 Орендодавець| Опубліковано 22.09.2020 17:34:33 |
[Справжній бій]. NET Core реалізує розподілені блокування на основі Redis
https://www.itsvse.com/thread-9391-1-1.html

.net/c# Реалізація розподіленого блокування Zookeeper [Вихідний код]
https://www.itsvse.com/thread-4651-1-1.html

Застереження:
Усе програмне забезпечення, програмні матеріали або статті, опубліковані Code Farmer Network, призначені лише для навчання та досліджень; Вищезазначений контент не повинен використовуватися в комерційних чи незаконних цілях, інакше користувачі несуть усі наслідки. Інформація на цьому сайті надходить з Інтернету, і спори щодо авторських прав не мають до цього сайту. Ви повинні повністю видалити вищезазначений контент зі свого комп'ютера протягом 24 годин після завантаження. Якщо вам подобається програма, будь ласка, підтримуйте справжнє програмне забезпечення, купуйте реєстрацію та отримайте кращі справжні послуги. Якщо є будь-яке порушення, будь ласка, зв'яжіться з нами електронною поштою.

Mail To:help@itsvse.com