В: Един сървър за обслужване, една база данни, операция: запитване на текущия баланс на потребителя, приспадване на 3% от текущия баланс като такса за обработка
Синхронизирано ключалка DB заключване
В: Два сървъра за услуги, една база данни, операция: запитване на текущия баланс на потребителя, приспадване на 3% от текущия баланс като такса за обработка Разпределени заключвания
Какъв вид разпределен катинар ни е необходим? Той може да гарантира, че в разпределен клъстер на приложения един и същ метод може да се изпълнява само от една нишка на една машина едновременно.
Ако тази заключване е реентрантна (избягвайте задънени моменти)
Тази катинарка е най-добра да бъде блокираща (помислете дали искате тази според нуждите на вашия бизнес)
Тази катинарка е най-добра да е справедлива (помислете дали искате тази или не, според нуждите на бизнеса).
Има много достъпни функции за заключване и заключване
Производителността на заключванията за прихващане и освобождаване е по-добра
1. Разпределени заключвания, базирани на бази данни
Разпределени заключвания, базирани на реализации, базирани на таблици
Когато искаме да заключим метод, изпълняваме следния SQL: вмъкнете в methodLock(method_name,desc) стойности ('method_name','desc')
Тъй като сме поставили ограничение за уникалност на method_name, ако няколко заявки се подават към базата данни едновременно, базата данни ще гарантира, че само една операция може да бъде успешна, тогава можем да приемем, че нишката, която успешно е получила метода, заключва метода и може да изпълни съдържанието на тялото на метода.
Когато методът се изпълни, ако искате да освободите заключването, трябва да изпълните следния Sql: изтрий от methodLock, където method_name ='method_name'
Тази проста реализация по-горе има следните проблеми:
- Това заключване зависи от наличността на базата данни, която е една точка и ще направи бизнес системата недостъпна, след като базата данни бъде прекъсната.
- Тази заключване няма срок на годност и след като операцията по отключване се провали, записът остава в базата данни и другите нишки вече няма да могат да я получат.
- Това заключване може да бъде само неблокиращо, тъй като операцията за вмъкване на данни директно ще докладва грешка, след като вмъкването се провали. Нишки, които не получават заключвания, няма да влязат в опашката и ще трябва да задействат операцията за заключване отново, за да получат заключването отново.
- Заключването не се реентира и същата нишка не може да я получи отново, докато не бъде освободена. Защото данните в данните вече съществуват.
- Този катинар е несправедлив и всички нишки, които чакат да го отключат, се конкурират за него по късмет.
Разбира се, можем да решим горните проблеми и по други начини.
- Базата данни една точка ли е? Изградете две бази данни и данните ще бъдат синхронизирани и в двете посоки. След като затворите, бързо превключите към резервната библиотека.
- Няма срок на годност? Просто изпълнявайте планирана задача, за да почиствате данните за тайм-аут в базата данни на редовни интервали.
- Без блокиране? Правете цикъл с времето, докато вмъкването успее и тогава резултатът е успешен.
- Не-реентрант? Добави поле в таблицата на базата данни, за да записваш информацията за хоста и нишката на машината, която в момента получава заключването, след което следващия път, когато получиш заключването, първо направи запитване в базата данни, ако информацията за хоста и нишките на текущата машина може да се намери в базата данни, можеш директно да му зададеш заключването.
- Несправедливо? Създайте друга междинна таблица, за да записвате всички нишки, чакащи заключването, и ги сортирайте според времето на създаване, като само първата създадена може да получи заключването
Разпределени ключалки, базирани на ексклузивни ключалки
Освен добавянето и изтриването на записи в таблицата с данни, разпределените заключвания могат да бъдат реализирани и с помощта на заключванията, които идват с данните.
Също така използваме таблицата с базата данни, която току-що създадохме. Разпределените заключвания могат да бъдат реализирани чрез ексклузивни заключвания върху бази данни. InnoDB, базиран на MySql, може да използва следните методи за реализиране на операции за заключване:
Ако добавите за актуализация след заявката, базата данни ще добави изключителна заключваща опция към таблицата на базата данни по време на процеса на заявка. Когато към запис се добави ексклузивен катинар, другите нишки вече не могат да добавят ексклузивно заключване към записа на този ред.
Можем да предположим, че нишката, която получава изключителната заключваща връзка, може да получи разпределената заключваща връзка, а когато заключването се получи, бизнес логиката на метода може да се изпълни и след това да се отключи чрез следните методи:
Public void unlock(){ connection.commit(); }
чрез connection.commit(); операция за освобождаване на заключалката.
Този метод може ефективно да реши гореспоменатите проблеми относно невъзможността да се освободи ключалката и да се блокира.
Блокиране на ключалки? Изявлението for update се връща веднага след успешно изпълнение и остава блокирано, докато не успее.
Услугата е прекратена след заключване, не може ли да бъде освободена? По този начин базата данни освобождава заключването сама след като услугата спре.
Въпреки това, това все още не решава директно проблема с единичната точка в базата данни, реентрантността и справедливото заключване.
За да обобщим начина, по който се използва базата данни за реализиране на разпределени заключвания, които и двете разчитат на таблица в базата данни, едната е да се определи дали има заключване по наличието на записи в таблицата, а другата е да се реализират разпределени заключвания чрез изключителната заключване на базата данни.
Предимства на разпределеното заключване в бази данни
Директно с помощта на базата данни е лесно за разбиране.
Недостатъци на внедряването на разпределени заключвания в бази данни
Ще има различни проблеми, а цялото решение ще става все по-сложно в процеса на решаване на проблема.
Работата с базата данни изисква определени разходи и трябва да се вземат предвид проблеми с производителността.
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 ms. Това ви позволява да изтекнете възможно най-скоро при достъп до redis възел след изключването му и намалява нормалната употреба на заключването. 3. Клиентът изчислява колко време отнема за получаване на заключването, като извади времето, получено в стъпка 1, с текущото време, само когато клиентът получи повече от 3 възела от заключването и времето за заключване е по-малко от времето за изтичане на заключването, клиентът получава разпределената заключваща връзка. 4. Времето на клиента да получи заключването е зададеното време за заключване минус времето, отделено за получаване на ключалката, изчислено в стъпка 3. 5. Ако клиентът не успее да получи заключването, той ще изтрие всички заключвания поотделно. С помощта на алгоритъма Redlock може да се гарантира, че разпределената услуга за заключване все още може да работи и при закачване на до 2 възела, което значително подобрява наличността в сравнение с предишната заключване на база данни и кеш заключване.
Въпреки това, разпределен експерт написа статия "Как да се направи разпределено заключване", в която поставя под въпрос коректността на Redlock.
Експертът спомена, че има два аспекта, които трябва да се вземат предвид при разглеждане на разпределени заключвания: производителност и коректност.
Ако използвате високопроизводителна разпределена заключване и коректността не е необходима, тогава използването на кеш заключване е достатъчно.
Ако използвате много надежден разпределен катинар, трябва да вземете предвид строги въпроси за надеждността. Редлок, от друга страна, не отговаря на правилността. Защо не? Експертите изброяват няколко аспекта.
В наши дни много програмни езици използват виртуални машини с функции на GC, при Full GC програмата спира обработката на GC, понякога Full GC отнема много време, а дори програмата има няколко минути забавяне – статията дава пример с HBase, HBase, понякога GC за няколко минути, което води до изтичане на наема. Например, на фигурата по-долу, клиент 1 получава заключване и е на път да обработи споделен ресурс, а когато е на път да обработи споделен ресурс, пълният 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 отговори, като написа блог след като видя статията на експерта. Авторът учтиво благодари на експерта и изрази несъгласието си с мнението му.
Дискусията на автора на REDIS за използването на токени за решаване на проблема с тайм-аута на заключването може да се обобщи в следните пет точки:
Точка 1, използването на разпределени заключвания обикновено е така, че няма друг начин да контролирате споделените ресурси, експертите използват токени, за да гарантират обработката на споделените ресурси, след което няма нужда от разпределени заключвания. Точка 2: За генериране на токени, за да се гарантира надеждността на токените, получени от различни клиенти, услугата, която генерира токени, все още се нуждае от разпределени заключвания, за да се гарантира надеждността на услугата. Точка 3, за начина, по който експертите казват, че самоувеличаващите се токени, авторът на redis смята, че това е напълно излишно – всеки клиент може да генерира уникален UUID като токен и да зададе споделения ресурс в състояние, което само клиентът с uuid може да обработва, така че другите клиенти да не могат да обработват споделения ресурс, докато клиентът, който я получи, не освободи заключването. Както е показано на фигурата по-горе, ако клиентът на токен 34 изпрати GC по време на процеса на запис и причинява изтичане на заключването, друг клиент може да получи заключването на токен 35 и да започне да пише отново, което води до конфликт на заключване. Следователно редът на токените не може да се комбинира със споделени ресурси. Точка 5, авторът на redis вярва, че в повечето сценарии разпределените заключвания се използват за справяне с проблеми с актуализации в нетранзакционни сценарии. Авторът трябва да има предвид, че има ситуации, в които е трудно да се комбинират токени за обработка на споделени ресурси, затова трябва да разчиташ на заключвания, за да заключиш и обработиш ресурсите. Друг проблем с часовника, за който експертите говорят, е авторите на Redis също дават обяснение. Ако времето, необходимо за получаване на ключалката, е твърде дълго и надвишава стандартното време за изтичане на ключалката, тогава клиентът не може да я получи в момента и няма да има примери, предложени от експерти.
Лични чувства
Първият проблем, който обобщавам, е, че след като клиентът получи разпределена заключваща връзка, заключването може да бъде освободено след изтичане на времето по време на обработката на клиента. Преди, когато говореше за тайм-аута, зададен от заключването на базата данни от 2 минути, ако дадена задача заема заключване на поръчка повече от 2 минути, тогава другият търговски център може да получи това заключване, така че двата търговски центъра да обработват една и съща поръчка едновременно. При нормални обстоятелства задачата се обработва за секунди, но понякога таймаутът, зададен при присъединяване към RPC заявка, е твърде дълъг и има няколко такива заявки за тайм-аут в дадена задача, тогава е вероятно автоматичното време за отключване да бъде надвишено. Ако пишем на java, може да има Full GC по средата, така че след като заключването се отключи след тайм-аута, клиентът не може да го възприеме, което е много сериозно нещо. Не мисля, че това е проблем с самата заключалка, стига всяка разпределена заключваща връзка, спомената по-горе, да има характеристиките на освобождаване на тайм-аут, такъв проблем ще възникне. Ако използвате функцията за заключване, клиентът трябва да зададе таймаута и да предприеме действия съответно, вместо да продължава да обработва споделения ресурс. Алгоритъмът на Redlock връща времето за заключване, което клиентът може да заеме след като получи заключването, и клиентът трябва да обработи това време, за да спре задачата след това време.
Вторият проблем е, че разпределените експерти не разбират Redlock. Ключова характеристика на Redlock е, че времето за получаване на ключалката е общото време, през което заключването по подразбиране е тайм-аут, минус времето, необходимо за получаване на ключалката, така че времето, необходимо на клиента за обработка, е относително време, независимо от местното време.
От тази гледна точка коректността на Redlock може да бъде напълно гарантирана. Внимателен анализ на Redlock, в сравнение с redis на възел, основната характеристика на Redlock е по-високата надеждност, което е важна характеристика в някои ситуации. Но мисля, че Redlock са похарчили твърде много пари, за да постигнат надеждност.
- Първо, трябва да се разположат 5 възела, за да стане Redlock по-надежден.
- След това трябва да поискаш 5 възела, за да получиш заключването, и чрез метода Future можеш първо да поискаш до 5 възела едновременно и след това да събереш резултата от отговора, което може да съкрати времето за отговор, но все пак отнема повече време от едновъзлов redis lock.
- След това, тъй като трябва да се получат повече от 3 от 5-те възела, може да възникне конфликт на заключване, т.е. всички са получили 1-2 заключвания, и в резултат никой не може да получи заключването, този проблем авторът на Redis заимства същността на алгоритъма с рафта – чрез сблъсъка в случаен момент времето за конфликт може да се намали значително, но този проблем не може да бъде избегнат много добре, особено когато ключалката се придобива за първи път, така че времевата стойност за придобиване на ключалката се увеличава.
- Ако 2 от 5-те възела са изключени, наличността на заключването ще бъде значително намалена, първо, трябва да изчакате резултатите от тези два паднали възела да изтекат, преди да се върнете, а има само 3 възела, а клиентът трябва да получи заключванията на всички 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 Protocol, определя последователността на здравината, която Zookeeper може да поддържа.
В разпределена среда съхранението на данни, което отговаря на силна консистентност, практически не съществува и изисква всички възли да се обновяват синхронно при актуализиране на данните на един възел. Тази стратегия за синхронизация се появява в базата данни за синхронна репликация master-slave. Въпреки това, тази стратегия за синхронизация има твърде голямо влияние върху производителността на записа и рядко се среща на практика. Тъй като 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 Protocol, определя последователността на здравината, която Zookeeper може да поддържа.
В разпределена среда съхранението на данни, което отговаря на силна консистентност, практически не съществува и изисква всички възли да се обновяват синхронно при актуализиране на данните на един възел. Тази стратегия за синхронизация се появява в базата данни за синхронна репликация master-slave. Въпреки това, тази стратегия за синхронизация има твърде голямо влияние върху производителността на записа и рядко се среща на практика. Тъй като Zookeeper записва N/2+1 възли синхронно, а N/2 възлите не се обновяват синхронно, Zookeeper не е силно последователен.
Операцията за обновяване на данните на потребителя не гарантира, че следващите четения ще прочетат обновената стойност, но в крайна сметка ще покажат последователност. Жертването на консистентността не означава пълно игнориране на консистентността на данните, иначе данните са хаотични, така че независимо колко висока е наличността на системата, независимо колко добро е разпределението, те нямат стойност. Жертването на консистентността е просто това, че силната консистентност в релационни бази данни вече не е необходима, но стига системата да постигне евентуална последователност.
Дали Zookeeper отговаря на причинно-следствената последователност зависи от начина, по който клиентът е програмиран.
Практики, които не удовлетворяват причинната последователност
- Процес А записва парче данни в /z на Zookeeper и успешно връща
- Процес А информира процес B, че A е модифицирал данните на /z
- B чете данните на /z на Zookeeper
- Тъй като сървърът на Zookeeper, свързан с B, може да не е бил обновен с писмените данни на A, B няма да може да прочете писмените данни на A
Практики, които отговарят на причинно-следствената последователност
- Процес B слуша за промени в данни в /z в Zookeeper
- Процес A записва парче данни в /z на Zookeeper, и преди да се върне успешно, Zookeeper трябва да се обади на слушателя, регистриран на /z, и лидерът ще уведоми B за промяната в данните
- След като методът за отговор на събитието в процес Б бъде отговорен, той взема променените данни, така че Б определено ще може да получи променената стойност
- Причинната консистентност тук се отнася до причинната съгласуваност между лидер и B, тоест лидерът уведомява данните за промяна
Вторият механизъм за слушане на събития е и методът, който трябва да се използва за правилно програмиране на Zookeeper, така че Zookeeper трябва да отговаря на причинно-следствената консистентност
Затова, когато внедряваме разпределени заключвания, базирани на Zookeeper, трябва да използваме практиката за удовлетворяване на причинно-следствената последователност, т.е. нишките, които чакат заключването, слушат промените в заключването на Zookeeper, а когато заключването бъде освободено, Zookeeper ще уведоми чакащата нишка, която отговаря на условията за справедливо заключване.
Можете да използвате директно клиента на трета страна на Zookeeper, който капсулира услуга за заключване на реентрант.
Разпределените заключвания, реализирани със ZK, изглежда отговарят точно на това, което очаквахме от разпределена заключваща система в началото на тази статия. Въпреки това, това не е така, а разпределеното заключване, реализирано от Zookeeper, всъщност има недостатък, а именно производителността може да не е толкова висока, колкото тази на кеширащата услуга. Защото всеки път в процеса на създаване и освобождаване на заключване, моментните възли трябва динамично да се създават и унищожават, за да се реализира заключващата функция. Създаването и изтриването на възли в ZK може да се извършва само чрез лидер сървъра, след което данните се споделят с всички последователни машини.
Предимства на използването на Zookeeper за реализиране на разпределени заключвания Ефективно решават проблеми с единични точки, проблеми без повторно влизане, проблеми с неблокиране и неуспех при заключване при освобождаване. Тя е сравнително проста за реализиране.
Недостатъци на използването на Zookeeper за реализиране на разпределени заключвания Производителността не е толкова добра, колкото при използване на кеш за реализиране на разпределени заключвания. Необходимо е разбиране на принципите на ZK.
Сравнение на трите опции
От гледна точка на лекотата на разбиране (от ниско към високо) База данни > кеш > Zookeeper
От гледна точка на сложността на имплементацията (от ниска към висока) Zookeeper > кеш > бази данни
От гледна точка на представянето (от високо към ниско) Кеширане > база данни Zookeeper >=
От гледна точка на надеждността (от висока към ниска) Zookeeper > кеш > бази данни
|