{"id":52541,"date":"2019-11-11T00:00:00","date_gmt":"2019-11-10T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost"},"modified":"2020-02-18T14:00:17","modified_gmt":"2020-02-18T11:00:17","slug":"rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","status":"publish","type":"post","link":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","title":{"rendered":"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/6557ce69c2b3070622feca8b3c228b09.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nW <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/471858\/\">W poprzednim artykule<\/a><\/noindex> Zajmiemy si\u0119 klasteryzacj\u0105 RabbitMQ w celu zapewnienia niezawodno\u015bci i du\u017cej dost\u0119pno\u015bci. Teraz dok\u0142adniej przyjrzymy si\u0119 Apache Kafka.<\/p>\n<p>Jednostk\u0105 replikacji jest tutaj partycja. Ka\u017cdy temat ma jedn\u0105 lub wi\u0119cej partycji. W ka\u017cdej partycji jest lider oraz followerzy lub ich brak. Podczas tworzenia tematu okre\u015bla si\u0119 liczb\u0119 partycji i wsp\u00f3\u0142czynnik replikacji. Zwykle warto\u015b\u0107 wynosi 3, co oznacza trzy repliki: jeden lider i dw\u00f3ch follower\u00f3w.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/36deb6d506223c2ee2ec147d5c215789.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 1. Cztery partycje rozdzielone mi\u0119dzy trzema brokerami.<\/i><\/p>\n<p>Wszystkie zapytania o odczyt i zapis trafiaj\u0105 do lidera. Followerzy okresowo wysy\u0142aj\u0105 do lidera zapytania o najnowsze wiadomo\u015bci. Konsumenci nigdy nie kontaktuj\u0105 si\u0119 z followerami, ci istniej\u0105 tylko dla nadmiarowo\u015bci i niezawodno\u015bci.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/715c51d75cb45863cfad4b37e81b9a9a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h1>Awaria partycji.<\/h1>\n<p>\nGdy broker ulega awarii, cz\u0119sto liderzy kilku partycji przestaj\u0105 dzia\u0142a\u0107. W ka\u017cdym z nich liderem zostaje follower z innego w\u0119z\u0142a. W rzeczywisto\u015bci nie zawsze tak jest, poniewa\u017c wp\u0142ywa na to r\u00f3wnie\u017c czynnik synchronizacji: czy s\u0105 synchronizowane followerzy, a je\u015bli nie, to czy przej\u015bcie na niesynchronizowan\u0105 replik\u0119 jest dozwolone. Ale na razie nie komplikujmy.<\/p>\n<p>Broker 3 wychodzi z sieci \u2014 i dla partycji 2 wybierany jest nowy lider na brokerze 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/b8cfce64cf6b848b0659de023f9d9b63.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 2. Broker 3 umiera, a jego follower na brokerze 2 zostaje nowym liderem partycji 2.<\/i><\/p>\n<p>Nast\u0119pnie broker 1 r\u00f3wnie\u017c odchodzi, a partycja 1 traci swojego lidera, kt\u00f3rego rol\u0119 przejmuje broker 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/9f5409c723da7ff059b93f9b23e7d5f6.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 3. Zosta\u0142 tylko jeden broker. Wszyscy liderzy znajduj\u0105 si\u0119 na jednym brokerze z zerow\u0105 nadmiarowo\u015bci\u0105.<\/i><\/p>\n<p>Gdy broker 1 powraca do sieci, dodaje czterech follower\u00f3w, zapewniaj\u0105c pewn\u0105 nadmiarowo\u015b\u0107 dla ka\u017cdej partycji. Ale wszyscy liderzy nadal pozostaj\u0105 na brokerze 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/f9c8e42f51258b7fd7f6f35dc7b8cc3b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 4. Liderzy pozostaj\u0105 na brokerze 2.<\/i><\/p>\n<p>Gdy broker 3 zostaje uruchomiony, wracamy do trzech replik w partycji. Ale wszyscy liderzy nadal s\u0105 na brokerze 2.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/9c8c02be4161f8468b5dbc1e3f6ecb3a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 5. Niezbalansowane rozmieszczenie lider\u00f3w po przywr\u00f3ceniu broker\u00f3w 1 i 3.<\/i><\/p>\n<p>Kafka ma narz\u0119dzie do lepszego przekszta\u0142cania lider\u00f3w ni\u017c RabbitMQ. Tam trzeba by\u0142o u\u017cywa\u0107 dodatkowych wtyczek lub skrypt\u00f3w, kt\u00f3re zmienia\u0142y polityki na migracj\u0119 g\u0142\u00f3wnego w\u0119z\u0142a, zmniejszaj\u0105c nadmiarowo\u015b\u0107 w trakcie migracji. Ponadto przy du\u017cych kolejach trzeba by\u0142o pogodzi\u0107 si\u0119 z niedost\u0119pno\u015bci\u0105 w czasie synchronizacji.<\/p>\n<p>Kafka ma koncepcj\u0119 'preferowanych replik' na leadera. Gdy tworzone s\u0105 partycje tematu, Kafka stara si\u0119 r\u00f3wnomiernie roz\u0142o\u017cy\u0107 lider\u00f3w po w\u0119z\u0142ach i oznacza tych pierwszych lider\u00f3w jako preferowanych. Z czasem, z powodu restart\u00f3w serwer\u00f3w, awarii i problem\u00f3w z \u0142\u0105czno\u015bci\u0105, liderzy mog\u0105 znale\u017a\u0107 si\u0119 na innych w\u0119z\u0142ach, jak w opisanym powy\u017cej skrajnym przypadku.<\/p>\n<p>Aby to naprawi\u0107, Kafka oferuje dwie opcje:<\/p>\n<ul>\n<li>Opcja <i>auto.leader.rebalance.enable=true<\/i> pozwala w\u0119z\u0142owi kontrolerowi automatycznie przypisa\u0107 lider\u00f3w z powrotem do preferowanych replik, przywracaj\u0105c w ten spos\u00f3b r\u00f3wnomierne roz\u0142o\u017cenie.\n<\/li>\n<li>Administrator mo\u017ce uruchomi\u0107 skrypt <i>kafka-preferred-replica-election.sh<\/i> aby przypisa\u0107 r\u0119cznie.<\/li>\n<\/ul>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/831930b06809637018fecb6d7d5a558d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 6. Repliki po rebalance<\/i><\/p>\n<p>To by\u0142a uproszczona wersja awarii, ale rzeczywisto\u015b\u0107 jest bardziej skomplikowana, chocia\u017c nie ma tutaj nic zbyt trudnego. Wszystko sprowadza si\u0119 do zsynchronizowanych replik (In-Sync Replicas, ISR).<\/p>\n<h1>Zsynchronizowane repliki (ISR)<\/h1>\n<p>\nISR to zestaw replik partycji, kt\u00f3ry jest uwa\u017cany za 'zsynchronizowany'. Jest tu lider, ale mog\u0105 nie by\u0107 \u017cadne followery. Follower uznawany jest za zsynchronizowany, je\u015bli dok\u0142adnie skopiowa\u0142 wszystkie wiadomo\u015bci lidera przed up\u0142ywem interwa\u0142u <i>replica.lag.time.max.ms<\/i>.<\/p>\n<p>Follower jest usuwany z zestawu ISR, je\u015bli:<\/p>\n<ul>\n<li>nie z\u0142o\u017cy\u0142 zapytania o pobranie w ci\u0105gu interwa\u0142u <i>replica.lag.time.max.ms<\/i> (uznawany za martwego)\n<\/li>\n<li>nie zd\u0105\u017cy\u0142 zaktualizowa\u0107 si\u0119 w ci\u0105gu interwa\u0142u <i>replica.lag.time.max.ms<\/i> (uznawany za wolnego)<\/li>\n<\/ul>\n<p>\nFollowery sk\u0142adaj\u0105 zapytania o pobranie w interwale <i>replica.fetch.wait.max.ms<\/i>, kt\u00f3ry domy\u015blnie wynosi 500 ms.<\/p>\n<p>Aby wyra\u017anie wyja\u015bni\u0107 cel ISR, nale\u017cy spojrze\u0107 na potwierdzenia od producenta i niekt\u00f3re scenariusze awarii. Producenci mog\u0105 zdecydowa\u0107, kiedy broker wysy\u0142a potwierdzenie:<\/p>\n<ul>\n<li>acks=0, potwierdzenie nie jest wysy\u0142ane\n<\/li>\n<li>acks=1, potwierdzenie jest wysy\u0142ane po tym, jak lider zapisze wiadomo\u015b\u0107 w swoim lokalnym dzienniku\n<\/li>\n<li>acks=all, potwierdzenie jest wysy\u0142ane po tym, jak wszystkie repliki w ISR zapisa\u0142y wiadomo\u015b\u0107 w lokalnych dziennikach<\/li>\n<\/ul>\n<p>\nW terminologii Kafki, je\u015bli ISR zachowa\u0142o wiadomo\u015b\u0107, nast\u0119puje jej \u201ecommit\u201d. Acks=all to najbezpieczniejsza opcja, ale wi\u0105\u017ce si\u0119 z dodatkowym op\u00f3\u017anieniem. Rozwa\u017cmy dwa przyk\u0142ady awarii i spos\u00f3b, w jaki r\u00f3\u017cne opcje 'acks' wsp\u00f3\u0142dzia\u0142aj\u0105 z koncepcj\u0105 ISR.<\/p>\n<h3>Acks=1 i ISR<\/h3>\n<p>\nW tym przyk\u0142adzie zobaczymy, \u017ce je\u015bli lider nie oczekuje na potwierdzenie ka\u017cdej wiadomo\u015bci od wszystkich obserwator\u00f3w, to przy awarii lidera mo\u017ce doj\u015b\u0107 do utraty danych. Przej\u015bcie do niesynchronizowanego obserwatora mo\u017ce by\u0107 dozwolone lub zabronione w ustawieniach. <i>unclean.leader.election.enable<\/i>.<\/p>\n<p>W tym przyk\u0142adzie producent ustawia warto\u015b\u0107 acks=1. Partycja jest roz\u0142o\u017cona pomi\u0119dzy wszystkie trzy broker\u00f3w. Broker 3 jest op\u00f3\u017aniony, zsynchronizowa\u0142 si\u0119 z liderem osiem sekund temu i obecnie ma 7456 wiadomo\u015bci op\u00f3\u017anienia. Broker 1 op\u00f3\u017ani\u0142 si\u0119 o zaledwie jedn\u0105 sekund\u0119. Nasz producent wysy\u0142a wiadomo\u015b\u0107 i szybko otrzymuje z powrotem ack, bez obci\u0105\u017cenia ze strony wolnych lub martwych obserwator\u00f3w, kt\u00f3rych lider nie oczekuje.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/f194e6309b732b772574392eff482a8b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 7. ISR z trzema replikami<\/i><\/p>\n<p>Broker 2 ulega awarii, a producent otrzymuje b\u0142\u0105d po\u0142\u0105czenia. Po przej\u015bciu liderstwa do brokera 1 tracimy 123 wiadomo\u015bci. Obserwator na brokerze 1 by\u0142 w ISR, ale nie by\u0142 w pe\u0142ni zsynchronizowany z liderem, gdy ten uleg\u0142 awarii.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/367f219daebafefe585059f67fdedf6f.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 8. Podczas awarii tracone s\u0105 wiadomo\u015bci<\/i><\/p>\n<p>W konfiguracji <i>bootstrap.servers<\/i> producent wymienia kilku broker\u00f3w i mo\u017ce zapyta\u0107 innego brokera, kto sta\u0142 si\u0119 nowym liderem partycji. Nast\u0119pnie nawi\u0105zuje po\u0142\u0105czenie z brokerem 1 i kontynuuje wysy\u0142anie wiadomo\u015bci.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/ba45c51f4ce1f63f10b2fa0e1487b223.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 9. Wysy\u0142anie wiadomo\u015bci wznawiane po kr\u00f3tkiej przerwie<\/i><\/p>\n<p>Broker 3 op\u00f3\u017ania si\u0119 jeszcze bardziej. Wysy\u0142a \u017c\u0105dania pobrania, ale nie mo\u017ce si\u0119 zsynchronizowa\u0107. Mo\u017ce to by\u0107 spowodowane wolnym po\u0142\u0105czeniem sieciowym mi\u0119dzy brokerami, problemami z przechowywaniem itp. Zostaje usuni\u0119ty z ISR. Teraz ISR sk\u0142ada si\u0119 z jednej repliki \u2014 lidera! Producent dalej wysy\u0142a wiadomo\u015bci i otrzymuje potwierdzenia.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/592c74632e3a8d80c2b4fc15bde5d401.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 10. Obserwator na brokerze 3 usuni\u0119ty z ISR<\/i><\/p>\n<p>Broker 1 ulega awarii, a rola lidera przechodzi do brokera 3 z utrat\u0105 15286 wiadomo\u015bci! Producent otrzymuje b\u0142\u0105d po\u0142\u0105czenia. Przej\u015bcie do lidera poza ISR by\u0142o mo\u017cliwe tylko dzi\u0119ki ustawieniu <i>unclean.leader.election.enable=true<\/i>. Je\u015bli jest ustawione na <i>false<\/i>, to przej\u015bcie by nie mia\u0142o miejsca, a wszystkie \u017c\u0105dania odczytu i zapisu zosta\u0142yby odrzucone. W takim przypadku czekamy na powr\u00f3t brokera 1 z jego nietkni\u0119tymi danymi w replikacji, kt\u00f3ra ponownie przejmie liderstwo.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/30f01ca715ccc194890ae061a3ef7396.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 11. Broker 1 ulega awarii. Podczas awarii traci si\u0119 du\u017c\u0105 ilo\u015b\u0107 wiadomo\u015bci<\/i><\/p>\n<p>Producent \u0142\u0105czy si\u0119 z ostatnim brokerem i zauwa\u017ca, \u017ce ten jest teraz liderem sekcji. Zaczyna wysy\u0142a\u0107 wiadomo\u015bci do brokera 3.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/986532d9b22b6514b6039c8460b1beb4.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 12. Po kr\u00f3tkiej przerwie wiadomo\u015bci znowu s\u0105 wysy\u0142ane do sekcji 0.<\/i><\/p>\n<p>Zauwa\u017cyli\u015bmy, \u017ce opr\u00f3cz kr\u00f3tkich przerw na ustanowienie nowych po\u0142\u0105cze\u0144 i szukanie nowego lidera, producent nieprzerwanie wysy\u0142a\u0142 wiadomo\u015bci. Taka konfiguracja zapewnia dost\u0119pno\u015b\u0107 kosztem sp\u00f3jno\u015bci (bezpiecze\u0144stwa danych). Kafka utraci\u0142a tysi\u0105ce wiadomo\u015bci, ale nadal przyjmowa\u0142a nowe wpisy.<\/p>\n<h3>Acks=all i ISR<\/h3>\n<p>\nPowt\u00f3rzmy ten scenariusz jeszcze raz, ale z <i>acks=all<\/i>. Op\u00f3\u017anienie brokera 3 wynosi \u015brednio cztery sekundy. Producent wysy\u0142a wiadomo\u015b\u0107 z <i>acks=all<\/i>, a teraz nie dostaje szybkiej odpowiedzi. Lider czeka, a\u017c wiadomo\u015b\u0107 zostanie zapisana przez wszystkie repliki w ISR.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/95b1abdc92e699f7bc41ebab249a2e08.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 13. ISR z trzema replikami. Jedna dzia\u0142a wolno, co prowadzi do op\u00f3\u017anienia zapisu.<\/i><\/p>\n<p>Po czterech sekundach dodatkowego op\u00f3\u017anienia broker 2 wysy\u0142a ack. Wszystkie repliki s\u0105 teraz w pe\u0142ni zaktualizowane.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/64356dc8d2641a3e22947126dd047f39.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 14. Wszystkie repliki przechowuj\u0105 wiadomo\u015bci i wysy\u0142aj\u0105 ack.<\/i><\/p>\n<p>Broker 3 teraz jeszcze bardziej si\u0119 op\u00f3\u017ania i zostaje usuni\u0119ty z ISR. Op\u00f3\u017anienie znacznie si\u0119 zmniejsza, poniewa\u017c w ISR nie ma ju\u017c wolnych replik. Broker 2 czeka teraz tylko na brokera 1, kt\u00f3ry ma \u015brednie op\u00f3\u017anienie 500 ms.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/5d3bd67dc53cb868fa40b358ed483a1d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 15. Replika na brokerze 3 zostaje usuni\u0119ta z ISR.<\/i><\/p>\n<p>Nast\u0119pnie broker 2 awaryjnie ko\u0144czy prac\u0119, a liderstwo przechodzi do brokera 1 bez utraty wiadomo\u015bci.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/e3f0417aa7714ea5eae8a8e8d61662bd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 16. Broker 2 awaryjnie ko\u0144czy prac\u0119.<\/i><\/p>\n<p>Producent znajduje nowego lidera i zaczyna wysy\u0142a\u0107 mu wiadomo\u015bci. Op\u00f3\u017anienie znowu si\u0119 zmniejsza, poniewa\u017c teraz ISR sk\u0142ada si\u0119 z jednej repliki! Dlatego opcja <i>acks=all<\/i> nie dodaje nadmiarowo\u015bci.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/fec9aae9977757d5f61c2909ceae0536.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 17. Replika na brokerze 1 przejmuje liderstwo bez utraty wiadomo\u015bci.<\/i><\/p>\n<p>Nast\u0119pnie broker 1 awaryjnie ko\u0144czy prac\u0119, a liderstwo przechodzi do brokera 3 z utrat\u0105 14238 wiadomo\u015bci!<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/730b3951fb75ab3a782fc6d064615212.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 18. Broker 1 umiera, a przej\u015bcie liderstwa z ustawieniem unclean prowadzi do znacznej utraty danych.<\/i><\/p>\n<p>Nie musieliby\u015bmy ustawia\u0107 opcji <i>unclean.leader.election.enable<\/i> na warto\u015b\u0107 <i>true<\/i>. Domy\u015blnie wynosi ona <i>false<\/i>. Ustawienie <i>acks=all<\/i> z <i>unclean.leader.election.enable=true<\/i> zapewnia dost\u0119pno\u015b\u0107 z pewnym dodatkowym bezpiecze\u0144stwem danych. Ale jak widzisz, nadal mo\u017cemy straci\u0107 wiadomo\u015bci.<\/p>\n<p>Ale co, je\u015bli chcemy zwi\u0119kszy\u0107 bezpiecze\u0144stwo danych? Mo\u017cna ustawi\u0107 <i>unclean.leader.election.enable = false<\/i>, ale to niekoniecznie ochroni nas przed utrat\u0105 danych. Je\u015bli lider mocno upadnie i zabierze ze sob\u0105 dane, wiadomo\u015bci i tak b\u0119d\u0105 utracone, a dost\u0119pno\u015b\u0107 b\u0119dzie stracona, dop\u00f3ki administrator nie przywr\u00f3ci sytuacji do normy.<\/p>\n<p>Lepiej zagwarantowa\u0107 nadmiarowo\u015b\u0107 wszystkich wiadomo\u015bci, w przeciwnym razie zrezygnowa\u0107 z zapisu. Wtedy przynajmniej z perspektywy brokera utrata danych mo\u017ce nast\u0105pi\u0107 tylko w przypadku dw\u00f3ch lub wi\u0119cej jednoczesnych awarii.<\/p>\n<h3>Acks=all, min.insync.replicas i ISR<\/h3>\n<p>\nZ konfiguracj\u0105 topika <i>min.insync.replicas<\/i> zwi\u0119kszamy poziom bezpiecze\u0144stwa danych. Przejd\u017amy jeszcze raz przez ostatni\u0105 cz\u0119\u015b\u0107 poprzedniego scenariusza, ale tym razem z <i>min.insync.replicas=2<\/i>.<\/p>\n<p>Zatem broker 2 ma lidera repliki, a follower na brokerze 3 zosta\u0142 usuni\u0119ty z ISR.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/5831463293f1837d3232756894e97162.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 19. ISR z dw\u00f3ch replik<\/i><\/p>\n<p>Broker 2 upada, a liderstwo przechodzi do brokera 1 bez utraty wiadomo\u015bci. Ale teraz ISR sk\u0142ada si\u0119 tylko z jednej repliki. To nie spe\u0142nia minimalnej liczby do zapis\u00f3w, i dlatego broker odpowiada na pr\u00f3b\u0119 zapisu b\u0142\u0119dem. <i>NotEnoughReplicas<\/i>.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/6b2ee477f4c33ec84f3068b792814e5d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 20. Liczba ISR o jeden ni\u017csza ni\u017c wskazana w min.insync.replicas<\/i><\/p>\n<p>Ta konfiguracja po\u015bwi\u0119ca dost\u0119pno\u015b\u0107 na rzecz sp\u00f3jno\u015bci. Zanim potwierdzimy wiadomo\u015b\u0107, zapewniamy, \u017ce jest zapisywana przynajmniej na dw\u00f3ch replikach. To daje producentowi znacznie wi\u0119ksz\u0105 pewno\u015b\u0107. Tutaj utrata wiadomo\u015bci jest mo\u017cliwa tylko w przypadku jednoczesnego upadku dw\u00f3ch replik w kr\u00f3tkim czasie, zanim wiadomo\u015b\u0107 zostanie zreplikowana na dodatkowego followera, co jest ma\u0142o prawdopodobne. Ale je\u015bli jeste\u015b super paranoikiem, mo\u017cesz ustawi\u0107 wsp\u00f3\u0142czynnik replikacji na 5, a <i>min.insync.replicas<\/i> na 3. Wtedy jednocze\u015bnie musz\u0105 upa\u015b\u0107 trzy brokery, aby utraci\u0107 zapis! Oczywi\u015bcie za tak\u0105 niezawodno\u015b\u0107 zap\u0142acisz dodatkowym op\u00f3\u017anieniem.<\/p>\n<h1>Gdy dost\u0119pno\u015b\u0107 jest konieczna dla bezpiecze\u0144stwa danych<\/h1>\n<p>\nJak w <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/471858\/\">w przypadku RabbitMQ<\/a><\/noindex>, czasami dost\u0119pno\u015b\u0107 jest konieczna dla bezpiecze\u0144stwa danych. Musisz pomy\u015ble\u0107 o tym:<\/p>\n<ul>\n<li>Czy wydawca mo\u017ce po prostu zwr\u00f3ci\u0107 b\u0142\u0105d, a wy\u017csza us\u0142uga lub u\u017cytkownik spr\u00f3bowa\u0107 p\u00f3\u017aniej?\n<\/li>\n<li>Czy wydawca mo\u017ce zapisa\u0107 wiadomo\u015b\u0107 lokalnie lub w bazie danych, aby spr\u00f3bowa\u0107 ponownie p\u00f3\u017aniej?<\/li>\n<\/ul>\n<p>\nJe\u015bli odpowied\u017a brzmi nie, optymalizacja dost\u0119pno\u015bci zwi\u0119ksza bezpiecze\u0144stwo danych. Utracisz mniej danych, je\u015bli wybierzesz dost\u0119pno\u015b\u0107 zamiast rezygnacji z zapisu. Tak wi\u0119c wszystko sprowadza si\u0119 do znalezienia r\u00f3wnowagi, a decyzja zale\u017cy od konkretnej sytuacji.<\/p>\n<h1>Sens ISR<\/h1>\n<p>\nZestaw ISR pozwala wybra\u0107 optymaln\u0105 r\u00f3wnowag\u0119 mi\u0119dzy bezpiecze\u0144stwem danych a op\u00f3\u017anieniem. Na przyk\u0142ad zapewnia dost\u0119pno\u015b\u0107 w przypadku awarii wi\u0119kszo\u015bci replik, minimalizuj\u0105c wp\u0142yw martwych lub wolnych replik z perspektywy op\u00f3\u017anienia.<\/p>\n<p>Sami wybieramy warto\u015b\u0107 <i>replica.lag.time.max.ms<\/i> zgodnie z naszymi potrzebami. W zasadzie ten parametr oznacza, jakie op\u00f3\u017anienie jeste\u015bmy gotowi zaakceptowa\u0107 przy <i>acks=all<\/i>. Warto\u015b\u0107 domy\u015blna wynosi dziesi\u0119\u0107 sekund. Je\u015bli to dla Ciebie zbyt d\u0142ugo, mo\u017cesz j\u0105 zmniejszy\u0107. W takim przypadku wzro\u015bnie cz\u0119sto\u015b\u0107 zmian w ISR, poniewa\u017c followery b\u0119d\u0105 cz\u0119\u015bciej usuwane i dodawane.<\/p>\n<p>W RabbitMQ to po prostu zestaw lustrzanych replik, kt\u00f3re nale\u017cy zreplikowa\u0107. Wolne lustra wprowadzaj\u0105 dodatkowe op\u00f3\u017anienie, a odpowiedzi martwych luster mo\u017cna oczekiwa\u0107 a\u017c do wyga\u015bni\u0119cia czasu \u017cycia pakiet\u00f3w, kt\u00f3re sprawdzaj\u0105 dost\u0119pno\u015b\u0107 ka\u017cdego w\u0119z\u0142a (net tick). ISR to interesuj\u0105cy spos\u00f3b na unikni\u0119cie tych problem\u00f3w z wyd\u0142u\u017conym op\u00f3\u017anieniem. Jednak ryzykujemy utrat\u0119 nadmiarowo\u015bci, poniewa\u017c ISR mo\u017ce skr\u00f3ci\u0107 si\u0119 tylko do lidera. Aby temu zapobiec, u\u017cyj ustawienia <i>min.insync.replicas<\/i>.<\/p>\n<h1>Gwarancja po\u0142\u0105czenia klient\u00f3w<\/h1>\n<p>\nW ustawieniach <i>bootstrap.servers<\/i> producenta i konsumenta mo\u017cna wskaza\u0107 kilku broker\u00f3w do po\u0142\u0105czenia z klientami. Pomys\u0142 polega na tym, \u017ce w przypadku awarii jednego w\u0119z\u0142a pozostaje kilka rezerwowych, z kt\u00f3rymi klient mo\u017ce nawi\u0105za\u0107 po\u0142\u0105czenie. To niekoniecznie liderzy partycji, a po prostu punkt wyj\u015bciowy dla wst\u0119pnego za\u0142adowania. Klient mo\u017ce zapyta\u0107 ich, na kt\u00f3rym w\u0119\u017ale znajduje si\u0119 lider partycji do odczytu\/zapisu.<\/p>\n<p>W RabbitMQ klienci mog\u0105 \u0142\u0105czy\u0107 si\u0119 z dowolnym w\u0119z\u0142em, a wewn\u0119trzne routowanie kieruje zapytanie tam, gdzie trzeba. Oznacza to, \u017ce mo\u017cesz ustawi\u0107 przed RabbitMQ r\u00f3wnowa\u017cnik obci\u0105\u017cenia. Kafka wymaga, aby klienci \u0142\u0105czyli si\u0119 z w\u0119z\u0142em, na kt\u00f3rym znajduje si\u0119 lider odpowiadaj\u0105cej partycji. W takiej sytuacji r\u00f3wnowa\u017cnik obci\u0105\u017cenia nie mo\u017ce by\u0107 ustawiony. Lista <i>bootstrap.servers<\/i> jest krytycznie wa\u017cna, aby klienci mogli kierowa\u0107 si\u0119 do odpowiednich w\u0119z\u0142\u00f3w i znajdowa\u0107 je po awarii.<\/p>\n<h1>Architektura konsensusu Kafka<\/h1>\n<p>\nDo tej pory nie om\u00f3wili\u015bmy, jak klaster dowiaduje si\u0119 o awarii brokera i jak wybierany jest nowy lider. Aby zrozumie\u0107, jak Kafka radzi sobie z podzia\u0142ami sieciowymi, najpierw nale\u017cy zrozumie\u0107 architektur\u0119 konsensusu.<\/p>\n<p>Ka\u017cdy klaster Kafka jest uruchamiany wraz z klastrem Zookeeper \u2014 to us\u0142uga rozproszonego konsensusu, kt\u00f3ra pozwala systemowi osi\u0105gn\u0105\u0107 konsensus w okre\u015blonym stanie, k\u0142ad\u0105c priorytet na sp\u00f3jno\u015b\u0107 nad dost\u0119pno\u015bci\u0105. Aby zatwierdzi\u0107 operacje odczytu i zapisu, wymagane jest uzyskanie zgody wi\u0119kszo\u015bci w\u0119z\u0142\u00f3w Zookeeper.<\/p>\n<p>Zookeeper przechowuje stan klastra:<\/p>\n<ul>\n<li>List\u0119 temat\u00f3w, partycji, konfiguracji, aktualne repliki lidera, preferowane repliki.\n<\/li>\n<li>Cz\u0142onkowie klastra. Ka\u017cdy broker pinguje klaster Zookeeper. Je\u015bli nie otrzyma pinga w okre\u015blonym czasie, Zookeeper uznaje brokera za niedost\u0119pnego.\n<\/li>\n<li>Wyb\u00f3r g\u0142\u00f3wnych i zapasowych w\u0119z\u0142\u00f3w dla kontrolera.<\/li>\n<\/ul>\n<p>\nW\u0119ze\u0142 kontrolera to jeden z broker\u00f3w Kafka, kt\u00f3ry odpowiada za wyb\u00f3r lider\u00f3w replik. Zookeeper wysy\u0142a kontrolerowi powiadomienia o cz\u0142onkostwie w klastrze i zmianach w tematach, a kontroler musi dzia\u0142a\u0107 zgodnie z tymi zmianami.<\/p>\n<p>Na przyk\u0142ad, we\u017amy nowy temat z dziesi\u0119cioma partiami i wsp\u00f3\u0142czynnikiem replikacji 3. Kontroler musi wybra\u0107 lidera dla ka\u017cdej partii, staraj\u0105c si\u0119 optymalnie roz\u0142o\u017cy\u0107 lider\u00f3w pomi\u0119dzy brokerami. <\/p>\n<p>Dla ka\u017cdej partii kontroler:<\/p>\n<ul>\n<li>aktualizuje informacje w Zookeeper na temat ISR i lidera;\n<\/li>\n<li>wysy\u0142a polecenie LeaderAndISRCommand do ka\u017cdego brokera, kt\u00f3ry przechowuje replik\u0119 tej partii, informuj\u0105c broker\u00f3w o ISR i liderze.<\/li>\n<\/ul>\n<p>\nGdy broker z liderem ulega awarii, Zookeeper wysy\u0142a powiadomienie do kontrolera, kt\u00f3ry wybiera nowego lidera. Ponownie, kontroler najpierw aktualizuje Zookeeper, a nast\u0119pnie wysy\u0142a polecenie do ka\u017cdego brokera, informuj\u0105c ich o zmianie w przyw\u00f3dztwie.<\/p>\n<p>Ka\u017cdy lider jest odpowiedzialny za zbi\u00f3r ISR. Konfiguracja <i>replica.lag.time.max.ms<\/i> okre\u015bla, kto tam wejdzie. Gdy zmienia si\u0119 ISR, lider przekazuje Zookeeper nowe informacje.<\/p>\n<p>Zookeeper jest zawsze informowany o jakichkolwiek zmianach, aby w przypadku awarii przyw\u00f3dztwo p\u0142ynnie przesz\u0142o do nowego lidera.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/3adb1d204b28e3ed85bef3530fa2b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 21. Konsensus Kafka<\/i><\/p>\n<h1>Protok\u00f3\u0142 replikacji<\/h1>\n<p>\nZrozumienie szczeg\u00f3\u0142\u00f3w replikacji pomaga lepiej zrozumie\u0107 potencjalne scenariusze utraty danych.<\/p>\n<h3>Zapytania o pobieranie, Log End Offset (LEO) i Highwater Mark (HW)<\/h3>\n<p>\nRozpatrzyli\u015bmy, \u017ce followerzy okresowo wysy\u0142aj\u0105 liderowi zapytania o pobranie (fetch). Domy\u015blny interwa\u0142 wynosi 500 ms. R\u00f3\u017cni si\u0119 to od RabbitMQ, w kt\u00f3rym replikacja jest inicjowana przez mastera, a nie przez lustro kolejki. Master wysy\u0142a zmiany do luster.<\/p>\n<p>Lider i wszyscy followerzy przechowuj\u0105 offset ko\u0144ca logu (Log End Offset, LEO) oraz znacznik Highwater (HW). Znacznik LEO przechowuje offset ostatniej wiadomo\u015bci w lokalnej replicie, a HW \u2014 offset ostatniego komitu. Pami\u0119taj, \u017ce aby status \u201ekomit\u201d m\u00f3g\u0142 zosta\u0107 uznany, wiadomo\u015b\u0107 musi by\u0107 zapisana we wszystkich replikach ISR. Oznacza to, \u017ce LEO zazwyczaj nieznacznie wyprzedza HW.<\/p>\n<p>Gdy lider otrzymuje wiadomo\u015b\u0107, zapisuje j\u0105 lokalnie. Follower wysy\u0142a zapytanie o pobranie, przekazuj\u0105c swoje LEO. Nast\u0119pnie lider wysy\u0142a pakiet wiadomo\u015bci, zaczynaj\u0105c od tego LEO, a tak\u017ce przesy\u0142a aktualne HW. Gdy lider uzyskuje informacj\u0119, \u017ce wszystkie repliki zapisa\u0142y wiadomo\u015b\u0107 z danym offsetem, przesuwa znacznik HW. Tylko lider mo\u017ce przesun\u0105\u0107 HW, a wi\u0119c wszyscy followerzy poznaj\u0105 aktualn\u0105 warto\u015b\u0107 w odpowiedziach na swoje zapytania. Oznacza to, \u017ce followerzy mog\u0105 pozostawa\u0107 w tyle za liderem zar\u00f3wno w kwestii wiadomo\u015bci, jak i znajomo\u015bci HW. Konsumenci otrzymuj\u0105 wiadomo\u015bci tylko do aktualnego HW.<\/p>\n<p>Zauwa\u017c, \u017ce \u201ezapisany\u201d (persisted) oznacza zapisany w pami\u0119ci, a nie na dysku. Dla wydajno\u015bci Kafka synchronizuje dane na dysk w okre\u015blonym interwale. RabbitMQ tak\u017ce ma taki interwa\u0142, ale potwierdzi publikacj\u0119 dopiero po zapisaniu wiadomo\u015bci na dysku przez mastera i wszystkie lustra. Deweloperzy Kafki, ze wzgl\u0119d\u00f3w wydajno\u015bciowych, zdecydowali si\u0119 na wysy\u0142anie ack, zaraz po zapisaniu wiadomo\u015bci w pami\u0119ci. Kafka zak\u0142ada, \u017ce nadmiarowo\u015b\u0107 zrekompensuje ryzyko kr\u00f3tkoterminowego przechowywania potwierdzonych wiadomo\u015bci tylko w pami\u0119ci.<\/p>\n<h1>Awaria lidera<\/h1>\n<p>\nGdy lider ulegnie awarii, Zookeeper informuje kontrolera, a ten wybiera now\u0105 replik\u0119 lidera. Nowy lider ustawia nowy znacznik HW zgodnie ze swoim LEO. Nast\u0119pnie followerzy otrzymuj\u0105 informacj\u0119 o nowym liderze. W zale\u017cno\u015bci od wersji Kafki, follower wybierze jeden z dw\u00f3ch scenariuszy:<\/p>\n<ol>\n<li>Skr\u00f3ci lokalny log do znanego HW i wy\u015ble do nowego lidera zapytanie o wiadomo\u015bci po tym znaczniku.\n<\/li>\n<li>Wy\u015ble zapytanie do lidera, aby uzyska\u0107 HW w momencie jego wyboru na lidera, a nast\u0119pnie obetnie log do tego offsetu. Nast\u0119pnie zacznie wykonywa\u0107 okresowe zapytania o pr\u00f3bki, zaczynaj\u0105c od tego offsetu.<\/li>\n<\/ol>\n<p>\nObserwuj\u0105cemu mo\u017ce by\u0107 potrzebne obci\u0119cie logu z nast\u0119puj\u0105cych powod\u00f3w:<\/p>\n<ul>\n<li>Gdy nast\u0119puje awaria lidera, pierwszy obserwuj\u0105cy z zestawu ISR, zarejestrowany w Zookeeper, wygrywa wybory i staje si\u0119 liderem. Wszyscy obserwuj\u0105cy w ISR, chocia\u017c uznawani za 'zsynchronizowanych', mogli nie otrzyma\u0107 od by\u0142ego lidera kopii wszystkich wiadomo\u015bci. Mo\u017ce si\u0119 zdarzy\u0107, \u017ce wybrany obserwuj\u0105cy nie ma najnowszej kopii. Kafka gwarantuje, \u017ce mi\u0119dzy replikami nie ma rozbie\u017cno\u015bci. Dlatego, aby unikn\u0105\u0107 rozbie\u017cno\u015bci, ka\u017cdy obserwuj\u0105cy musi obci\u0105\u0107 sw\u00f3j log do warto\u015bci HW nowego lidera w momencie jego wyboru. To kolejny pow\u00f3d, dla kt\u00f3rego konfiguracja <i>acks=all<\/i> jest tak wa\u017cna dla sp\u00f3jno\u015bci.\n<\/li>\n<li>Wiadomo\u015bci s\u0105 okresowo zapisywane na dysku. Je\u015bli wszystkie w\u0119z\u0142y klastra zawiod\u0105 jednocze\u015bnie, na dyskach pozostan\u0105 repliki o r\u00f3\u017cnych offsetach. Mo\u017ce si\u0119 zdarzy\u0107, \u017ce gdy brokerzy zn\u00f3w wejd\u0105 do sieci, nowy lider, kt\u00f3ry zostanie wybrany, znajdzie si\u0119 za swoimi obserwuj\u0105cymi, poniewa\u017c zapisa\u0142 si\u0119 na dysk wcze\u015bniej ni\u017c inni.<\/li>\n<\/ul>\n<p><\/p>\n<h3>Ponowne po\u0142\u0105czenie z klastrem<\/h3>\n<p>\nPodczas ponownego po\u0142\u0105czenia z klastrem repliki zachowuj\u0105 si\u0119 tak samo jak przy awarii lidera: sprawdzaj\u0105 replik\u0119 lidera i obcinaj\u0105 sw\u00f3j log do jego HW (w momencie wyboru). Dla por\u00f3wnania, RabbitMQ traktuje ponownie pod\u0142\u0105czone w\u0119z\u0142y jako zupe\u0142nie nowe. W obu przypadkach broker odrzuca jakikolwiek istniej\u0105cy stan. Je\u015bli u\u017cywana jest automatyczna synchronizacja, mistrz musi zreplikowa\u0107 absolutnie ca\u0142\u0105 bie\u017c\u0105c\u0105 zawarto\u015b\u0107 do nowego lustra w trybie 'niech ca\u0142y \u015bwiat poczeka'. Podczas tej operacji mistrz nie akceptuje \u017cadnych operacji odczytu ani zapisu. Takie podej\u015bcie powoduje problemy w du\u017cych kolejkach.<\/p>\n<p>Kafka to rozproszony dziennik, kt\u00f3ry generalnie przechowuje wi\u0119cej wiadomo\u015bci ni\u017c kolejka RabbitMQ, w kt\u00f3rej dane s\u0105 usuwane z kolejki po ich odczytaniu. Aktywne kolejki powinny pozostawa\u0107 stosunkowo ma\u0142e. Jednak Kafka to dziennik z w\u0142asn\u0105 polityk\u0105 przechowywania, kt\u00f3ra mo\u017ce ustala\u0107 okres w dniach lub tygodniach. Podej\u015bcie polegaj\u0105ce na blokowaniu kolejki i pe\u0142nej synchronizacji jest absolutnie niedopuszczalne dla rozproszonego dziennika. Zamiast tego, followery Kafki po prostu przycinaj\u0105 sw\u00f3j dziennik do HW lidera (w momencie jego wyboru), je\u015bli ich kopia wyprzedza lidera. W bardziej prawdopodobnym przypadku, gdy follower jest w tyle, po prostu zaczyna wysy\u0142a\u0107 zapytania o pobranie, zaczynaj\u0105c od swojego obecnego LEO.<\/p>\n<p>Nowe lub do\u0142\u0105czone followery zaczynaj\u0105 poza ISR i nie bior\u0105 udzia\u0142u w zatwierdzeniach. Po prostu dzia\u0142aj\u0105 obok grupy, odbieraj\u0105c wiadomo\u015bci tak szybko, jak to mo\u017cliwe, a\u017c dogoni\u0105 lidera i wejd\u0105 do ISR. Nie ma tu blokady i nie ma potrzeby odrzucania wszystkich swoich danych.<\/p>\n<h1>Naruszenie sp\u00f3jno\u015bci<\/h1>\n<p>\nKafka ma wi\u0119cej komponent\u00f3w ni\u017c RabbitMQ, dlatego w tym przypadku zestaw zachowa\u0144 jest bardziej skomplikowany, gdy w klastrze wyst\u0119puj\u0105 problemy z \u0142\u0105czno\u015bci\u0105. Jednak Kafka zosta\u0142a pierwotnie zaprojektowana z my\u015bl\u0105 o klastrach, wi\u0119c rozwi\u0105zania s\u0105 bardzo dobrze przemy\u015blane.<\/p>\n<p>Poni\u017cej przedstawiono kilka scenariuszy naruszenia \u0142\u0105czno\u015bci:<\/p>\n<ul>\n<li>Scenariusz 1. Follower nie widzi lidera, ale nadal widzi Zookeeper.\n<\/li>\n<li>Scenariusz 2. Lider nie widzi \u017cadnego followera, ale nadal widzi Zookeeper.\n<\/li>\n<li>Scenariusz 3. Follower widzi lidera, ale nie widzi Zookeeper.\n<\/li>\n<li>Scenariusz 4. Lider widzi follower\u00f3w, ale nie widzi Zookeeper.\n<\/li>\n<li>Scenariusz 5. Follower jest ca\u0142kowicie odizolowany od innych w\u0119z\u0142\u00f3w Kafki oraz od Zookeeper.\n<\/li>\n<li>Scenariusz 6. Lider jest ca\u0142kowicie odizolowany od innych w\u0119z\u0142\u00f3w Kafki oraz od Zookeeper.\n<\/li>\n<li>Scenariusz 7. W\u0119ze\u0142 kontrolera Kafki nie widzi innego w\u0119z\u0142a Kafki.\n<\/li>\n<li>Scenariusz 8. Kontroler Kafki nie widzi Zookeeper.<\/li>\n<\/ul>\n<p>\nDla ka\u017cdego scenariusza przewidziane jest specjalne zachowanie.<\/p>\n<h3>Scenariusz 1. Follower nie widzi lidera, ale nadal widzi Zookeeper<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/5f51ae679933b2b5a69e21831465d121.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 22. Scenariusz 1. ISR z trzech replik<\/i><\/p>\n<p>Naruszenie \u0142\u0105czno\u015bci odcina brokera 3 od broker\u00f3w 1 i 2, ale nie od Zookeeper. Broker 3 nie mo\u017ce ju\u017c wysy\u0142a\u0107 \u017c\u0105da\u0144 o pobranie. Po up\u0142ywie czasu <i>replica.lag.time.max.ms<\/i> jest usuwany z ISR i nie bierze udzia\u0142u w commitach. Gdy tylko sp\u00f3jno\u015b\u0107 zostanie przywr\u00f3cona, wznowi zapytania o pobranie i do\u0142\u0105czy do ISR, gdy dogoni lidera. Zookeeper b\u0119dzie nadal odbiera\u0142 pingi i uznawa\u0142, \u017ce broker jest \u017cywy i zdrowy.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/976b7ff080ee6a6d76a165f614f40e95.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 23. Scenariusz 1. Broker jest usuwany z ISR, je\u015bli nie otrzyma zapytania o pobranie w czasie interwa\u0142u replica.lag.time.max.ms<\/i><\/p>\n<p>Nie ma \u017cadnego logicznego podzia\u0142u (split-brain) ani wstrzymania w\u0119z\u0142a, jak w RabbitMQ. Zamiast tego zmniejsza si\u0119 nadmiarowo\u015b\u0107. <\/p>\n<h3>Scenariusz 2. Lider nie widzi \u017cadnego followera, ale nadal widzi Zookeepera<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/ff6aaa053d73e8b7c97111979bcf97aa.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 24. Scenariusz 2. Lider oraz dw\u00f3ch follower\u00f3w<\/i><\/p>\n<p>Zaburzenie \u0142\u0105czno\u015bci sieciowej oddziela lidera od follower\u00f3w, ale broker nadal widzi Zookeepera. Jak w pierwszym scenariuszu, ISR si\u0119 kurczy, ale tym razem tylko do lidera, poniewa\u017c wszyscy followerzy przestaj\u0105 wysy\u0142a\u0107 zapytania o pobranie. Ponownie, nie ma \u017cadnego logicznego podzia\u0142u. Zamiast tego nast\u0119puje utrata nadmiarowo\u015bci dla nowych wiadomo\u015bci, dop\u00f3ki sp\u00f3jno\u015b\u0107 nie zostanie przywr\u00f3cona. Zookeeper nadal odbiera pingi i uznaje, \u017ce broker jest \u017cywy i zdrowy.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/3c69e8327da241407f76719fc022c37a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 25. Scenariusz 2. ISR skurczy\u0142 si\u0119 tylko do lidera<\/i><\/p>\n<h3>Scenariusz 3. Follower widzi lidera, ale nie widzi Zookeepera<\/h3>\n<p>\nFollower jest oddzielony od Zookeepera, ale nie od brokera z liderem. W efekcie follower nadal wysy\u0142a zapytania o pobranie i jest cz\u0142onkiem ISR. Zookeeper przestaje otrzymywa\u0107 pingi i rejestruje awari\u0119 brokera, ale poniewa\u017c to tylko follower, po przywr\u00f3ceniu nie ma \u017cadnych konsekwencji.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/1183bcfe45a3225ae3ef1a0651f61350.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 26. Scenariusz 3. Follower nadal wysy\u0142a zapytania o pobranie do lidera<\/i><\/p>\n<h3>Scenariusz 4. Lider widzi follower\u00f3w, ale nie widzi Zookeepera<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/b3bf27fcb0eb806b27ad00f098e50a26.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 27. Scenariusz 4. Lider oraz dw\u00f3ch follower\u00f3w<\/i><\/p>\n<p>Lider jest oddzielony od Zookeepera, ale nie od broker\u00f3w z followerami. <\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/82d9f2e5868566678befc414d1885bfd.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 28. Scenariusz 4. Lider jest izolowany od Zookeepera<\/i><\/p>\n<p>Po pewnym czasie Zookeeper zarejestruje awari\u0119 brokera i powiadomi o tym kontrolera. Ten wybierze nowego lidera spo\u015br\u00f3d follower\u00f3w. Jednak oryginalny lider nadal b\u0119dzie uwa\u017ca\u0142, \u017ce jest liderem i b\u0119dzie kontynuowa\u0142 przyjmowanie zapis\u00f3w z <i>acks=1<\/i>. Followerzy ju\u017c mu nie wysy\u0142aj\u0105 zapyta\u0144 o pobranie, wi\u0119c uzna ich za martwych i spr\u00f3buje skurczy\u0107 ISR do samego siebie. Ale poniewa\u017c nie ma po\u0142\u0105czenia z Zookeeperem, nie b\u0119dzie w stanie tego zrobi\u0107, a w tym momencie zrezygnuje z dalszego przyjmowania zapis\u00f3w. <\/p>\n<p>Wiadomo\u015bci <i>acks=all<\/i> nie otrzymaj\u0105 potwierdzenia, poniewa\u017c najpierw ISR obejmuje wszystkie repliki, a wiadomo\u015bci do nich nie docieraj\u0105. Kiedy pierwotny lider spr\u00f3buje usun\u0105\u0107 je z ISR, nie b\u0119dzie w stanie tego zrobi\u0107 i w og\u00f3le przestanie przyjmowa\u0107 jakiekolwiek wiadomo\u015bci.<\/p>\n<p>Klienci wkr\u00f3tce zauwa\u017caj\u0105 zmian\u0119 lidera i zaczynaj\u0105 wysy\u0142a\u0107 zapisy na nowy serwer. Gdy sie\u0107 zostaje przywr\u00f3cona, pierwotny lider widzi, \u017ce nie jest ju\u017c liderem, i tn\u0119 sw\u00f3j log do warto\u015bci HW, kt\u00f3r\u0105 mia\u0142 nowy lider w momencie awarii, aby unikn\u0105\u0107 rozbie\u017cno\u015bci log\u00f3w. Nast\u0119pnie zacznie wysy\u0142a\u0107 zapytania do nowego lidera. Wszystkie zapisy pierwotnego lidera, kt\u00f3re nie zosta\u0142y zreplikowane do nowego lidera, zostan\u0105 utracone. Oznacza to, \u017ce wiadomo\u015bci, kt\u00f3re nie zosta\u0142y potwierdzone przez pierwotnego lidera w te kilka sekund, gdy dzia\u0142a\u0142o dw\u00f3ch lider\u00f3w, zostan\u0105 utracone.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/d88d6f33c13dccb814c0f206ec72512b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 29. Scenariusz 4. Lider na brokerze 1 staje si\u0119 obserwatorem po przywr\u00f3ceniu sieci.<\/i><\/p>\n<h3>Scenariusz 5. Obserwator jest ca\u0142kowicie odizolowany zar\u00f3wno od innych w\u0119z\u0142\u00f3w Kafka, jak i od Zookeepra.<\/h3>\n<p>\nObserwator jest ca\u0142kowicie izolowany zar\u00f3wno od innych w\u0119z\u0142\u00f3w Kafka, jak i od Zookeepra. Po prostu zostaje usuni\u0119ty z ISR, a\u017c sie\u0107 zostanie przywr\u00f3cona, a potem dogania pozosta\u0142ych.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/b092607f777014fd945f18734dd7f4e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 30. Scenariusz 5. Izolowany obserwator zostaje usuni\u0119ty z ISR.<\/i><\/p>\n<h3>Scenariusz 6. Lider jest ca\u0142kowicie odizolowany zar\u00f3wno od innych w\u0119z\u0142\u00f3w Kafka, jak i od Zookeepra.<\/h3>\n<p>\n<img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/bb808d534dbf65748eb0b481f86b4926.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 31. Scenariusz 6. Lider i dw\u00f3ch obserwator\u00f3w.<\/i><\/p>\n<p>Lider jest ca\u0142kowicie odizolowany od swoich obserwator\u00f3w, kontrolera i Zookeepra. Przez kr\u00f3tki okres b\u0119dzie nadal przyjmowa\u0107 zapisy z <i>acks=1<\/i>.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/6fda78bcd26ef6b916579d447e9fb1f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 32. Scenariusz 6. Izolacja lidera od innych w\u0119z\u0142\u00f3w Kafka i Zookeepra.<\/i><\/p>\n<p>Nie otrzymuj\u0105c zapyta\u0144 po up\u0142ywie <i>replica.lag.time.max.ms<\/i>, spr\u00f3buje skompresowa\u0107 ISR do samego siebie, ale nie b\u0119dzie w stanie tego zrobi\u0107, poniewa\u017c nie ma po\u0142\u0105czenia z Zookeperem, wtedy przestanie przyjmowa\u0107 zapisy. <\/p>\n<p>W mi\u0119dzyczasie Zookeeper oznaczy izolowanego brokera jako martwego, a kontroler wybierze nowego lidera.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/73d611a411fc64d835af2c714e9eba0a.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 33. Scenariusz 6. Dw\u00f3ch lider\u00f3w.<\/i><\/p>\n<p>Pierwotny lider mo\u017ce przyjmowa\u0107 zapisy przez kilka sekund, ale nast\u0119pnie przestaje przyjmowa\u0107 jakiekolwiek wiadomo\u015bci. Klienci aktualizuj\u0105 si\u0119 co 60 sekund z najnowszymi metadanymi. Zostan\u0105 poinformowani o zmianie lidera i zaczn\u0105 wysy\u0142a\u0107 zapisy do nowego lidera.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/ae99380c8a84fac15f440b699b9c552b.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 34. Scenariusz 6. Producenci prze\u0142\u0105czaj\u0105 si\u0119 do nowego lidera.<\/i><\/p>\n<p>Wszystkie potwierdzone zapisy dokonane przez pierwotnego lidera od momentu utraty sp\u00f3jno\u015bci zostan\u0105 utracone. Gdy sie\u0107 zostanie przywr\u00f3cona, pierwotny lider przez Zookeeper odkryje, \u017ce ju\u017c nie jest liderem. Nast\u0119pnie przytnije sw\u00f3j dziennik do HW nowego lidera w momencie wyboru i zacznie wysy\u0142a\u0107 zapytania jako follower.<\/p>\n<p><img decoding=\"async\" alt=\"RabbitMQ vs Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107\" src=\"\/wp-content\/uploads\/2019\/11\/10f0983a829b03ca9bbc62e12cbf8a5d.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Rys. 35. Scenariusz 6. Pierwotny lider staje si\u0119 followerem po przywr\u00f3ceniu sp\u00f3jno\u015bci sieci<\/i><\/p>\n<p>W tej sytuacji przez kr\u00f3tki czas mo\u017ce wyst\u0119powa\u0107 logiczny podzia\u0142, ale tylko je\u015bli <i>acks=1<\/i> i <i>min.insync.replicas<\/i> r\u00f3wnie\u017c 1. Logicznym podzia\u0142 ko\u0144czy si\u0119 automatycznie albo po przywr\u00f3ceniu sieci, gdy pierwotny lider zdaje sobie spraw\u0119, \u017ce ju\u017c nie jest liderem, albo gdy wszyscy klienci zrozumiej\u0105, \u017ce lider si\u0119 zmieni\u0142 i zaczn\u0105 pisa\u0107 do nowego lidera - w zale\u017cno\u015bci od tego, co wydarzy si\u0119 wcze\u015bniej. W ka\u017cdym razie dojdzie do utraty niekt\u00f3rych wiadomo\u015bci, ale tylko z <i>acks=1<\/i>.<\/p>\n<p>Istnieje inna wersja tego scenariusza, w kt\u00f3rej tu\u017c przed podzia\u0142em sieci followerzy zostaj\u0105 w tyle, a lider zmniejsza ISR do jednego siebie. Nast\u0119pnie izoluje si\u0119 z powodu utraty sp\u00f3jno\u015bci. Wybierany jest nowy lider, ale pierwotny lider nadal przyjmuje zapisy, nawet <i>acks=all<\/i>, poniewa\u017c w ISR nie ma nikogo opr\u00f3cz niego. Te zapisy zostan\u0105 utracone po przywr\u00f3ceniu sieci. Jedynym sposobem na unikni\u0119cie takiej sytuacji jest <i>min.insync.replicas = 2<\/i>.<\/p>\n<h3>Scenariusz 7. W\u0119ze\u0142 kontrolera Kafka nie widzi innego w\u0119z\u0142a Kafka<\/h3>\n<p>\nOg\u00f3lnie rzecz bior\u0105c, po utracie po\u0142\u0105czenia z w\u0119z\u0142em Kafka, kontroler nie b\u0119dzie w stanie przekaza\u0107 mu \u017cadnych informacji dotycz\u0105cych zmiany lidera. W najgorszym przypadku doprowadzi to do kr\u00f3tkoterminowego logicznego podzia\u0142u, jak w scenariuszu 6. Najcz\u0119\u015bciej broker po prostu nie stanie si\u0119 kandydatem na lidera w przypadku awarii ostatniego.<\/p>\n<h3>Scenariusz 8. Kontroler Kafka nie widzi Zookeepera<\/h3>\n<p>\nOd od\u0142\u0105czonego kontrolera Zookeeper nie otrzyma pinga i wybierze nowy w\u0119ze\u0142 Kafka na kontrolerze. Pierwotny kontroler mo\u017ce nadal przedstawia\u0107 si\u0119 jako taki, ale nie otrzymuje powiadomie\u0144 od Zookeepera, wi\u0119c nie ma \u017cadnych zada\u0144 do wykonania. Gdy tylko sie\u0107 zostanie przywr\u00f3cona, zrozumie, \u017ce ju\u017c nie jest kontrolerem, lecz sta\u0142 si\u0119 zwyk\u0142ym w\u0119z\u0142em Kafka.<\/p>\n<h3>Wnioski z scenariuszy<\/h3>\n<p>\nWidoczne jest, \u017ce utrata \u0142\u0105czno\u015bci obserwator\u00f3w nie prowadzi do utraty wiadomo\u015bci, a jedynie tymczasowo zmniejsza nadmiarowo\u015b\u0107, a\u017c do momentu przywr\u00f3cenia sieci. Mo\u017ce to oczywi\u015bcie prowadzi\u0107 do utraty danych, je\u015bli stracone zostan\u0105 jeden lub kilka w\u0119z\u0142\u00f3w.<\/p>\n<p>Je\u015bli z powodu utraty \u0142\u0105czno\u015bci lider od\u0142\u0105czy si\u0119 od Zookeepera, mo\u017ce to prowadzi\u0107 do utraty wiadomo\u015bci z <i>acks=1<\/i>. Brak \u0142\u0105czno\u015bci z Zookeeperem powoduje kr\u00f3tkotrwa\u0142y podzia\u0142 logiczny z dwoma liderami. Problem ten rozwi\u0105zuje parametr <i>acks=all<\/i>.<\/p>\n<p>Parametr <i>min.insync.replicas<\/i> w dw\u00f3ch lub wi\u0119cej replikach zapewnia dodatkowe gwarancje, \u017ce takie kr\u00f3tkoterminowe scenariusze nie doprowadz\u0105 do utraty wiadomo\u015bci, jak w scenariuszu 6.<\/p>\n<h1>Podsumowanie dotycz\u0105ce utraty wiadomo\u015bci<\/h1>\n<p>\nWymie\u0144my wszystkie sposoby, w jakie mo\u017cna straci\u0107 dane w Kafka:<\/p>\n<ul>\n<li>Jakakolwiek awaria lidera, je\u015bli wiadomo\u015bci by\u0142y potwierdzane za pomoc\u0105 <i>acks=1<\/i>\n<\/li>\n<li>Jakikolwiek nieczysty (unclean) transfer lidera, czyli na obserwatora poza ISR, nawet z <i>acks=all<\/i>\n<\/li>\n<li>Izolacja lidera od Zookeepera, je\u015bli wiadomo\u015bci by\u0142y potwierdzane za pomoc\u0105 <i>acks=1<\/i>\n<\/li>\n<li>Pe\u0142na izolacja lidera, kt\u00f3ry ju\u017c skurczy\u0142 grup\u0119 ISR tylko do siebie. Zostan\u0105 utracone wszystkie wiadomo\u015bci, nawet <i>acks=all<\/i>. To prawda tylko w przypadku, je\u015bli <i>min.insync.replicas=1<\/i>.\n<\/li>\n<li>Jednoczesne awarie wszystkich w\u0119z\u0142\u00f3w danego segmentu. Poniewa\u017c wiadomo\u015bci s\u0105 potwierdzane z pami\u0119ci, niekt\u00f3re mog\u0105 jeszcze nie zosta\u0107 zapisane na dysku. Po ponownym uruchomieniu serwer\u00f3w mo\u017ce brakowa\u0107 niekt\u00f3rych wiadomo\u015bci.<\/li>\n<\/ul>\n<p>\nNieczystych transfer\u00f3w lidera mo\u017cna unikn\u0105\u0107, albo ich zabraniaj\u0105c, albo zapewniaj\u0105c nadmiarowo\u015b\u0107 na poziomie co najmniej dw\u00f3ch. Najbardziej solidna konfiguracja to po\u0142\u0105czenie <i>acks=all<\/i> i <i>min.insync.replicas<\/i> wi\u0119cej ni\u017c 1.<\/p>\n<h1>Bezpo\u015brednie por\u00f3wnanie niezawodno\u015bci RabbitMQ i Kafka<\/h1>\n<p>\nAby zapewni\u0107 niezawodno\u015b\u0107 i wysok\u0105 dost\u0119pno\u015b\u0107, obie platformy wdra\u017caj\u0105 system replikacji pierwotnej i wt\u00f3rnej. Jednak RabbitMQ ma swoje s\u0142abe miejsce. Po ponownym po\u0142\u0105czeniu po awarii w\u0119z\u0142y zrzucaj\u0105 swoje dane, a synchronizacja zostaje zablokowana. Ten podw\u00f3jny cios podwa\u017ca trwa\u0142o\u015b\u0107 du\u017cych kolejek w RabbitMQ. B\u0119dziesz musia\u0142 pogodzi\u0107 si\u0119 albo z ograniczeniem nadmiarowo\u015bci, albo z d\u0142ugotrwa\u0142ymi blokadami. Zmniejszenie nadmiarowo\u015bci zwi\u0119ksza ryzyko masowej utraty danych. Ale je\u015bli kolejki s\u0105 ma\u0142e, to w celu zapewnienia nadmiarowo\u015bci z kr\u00f3tkimi okresami niedost\u0119pno\u015bci (kilka sekund) mo\u017cna poradzi\u0107 sobie z pomoc\u0105 ponownych pr\u00f3b po\u0142\u0105czenia.<\/p>\n<p>W Kafka nie ma takiego problemu. Odrzuca dane tylko w punkcie niezgodno\u015bci lidera i obserwatora. Wszystkie wsp\u00f3lne dane s\u0105 zachowywane. Ponadto replikacja nie blokuje systemu. Lider nadal przyjmuje wpisy, podczas gdy nowy obserwator go dogania, wi\u0119c dla devops\u00f3w do\u0142\u0105czanie lub ponowne \u0142\u0105czenie klastra staje si\u0119 trywialnym zadaniem. Oczywi\u015bcie nadal istniej\u0105 problemy, takie jak przepustowo\u015b\u0107 sieci podczas replikacji. Je\u015bli jednocze\u015bnie dodano kilku obserwator\u00f3w, mo\u017cna napotka\u0107 limit przepustowo\u015bci.<\/p>\n<p>RabbitMQ przewy\u017csza Kafka w niezawodno\u015bci w przypadku jednoczesnej awarii wielu serwer\u00f3w w klastrze. Jak ju\u017c wspomnieli\u015bmy, RabbitMQ wysy\u0142a potwierdzenie do publikacji dopiero po zapisaniu wiadomo\u015bci na dysku u lidera i wszystkich lustrzanych. Jednak wprowadza to dodatkowe op\u00f3\u017anienie z dw\u00f3ch powod\u00f3w:<\/p>\n<ul>\n<li>fsync co kilka setek milisekund\n<\/li>\n<li>Awari\u0119 lustra mo\u017cna zauwa\u017cy\u0107 dopiero po up\u0142ywie czasu \u017cycia pakiet\u00f3w, kt\u00f3re sprawdzaj\u0105 dost\u0119pno\u015b\u0107 ka\u017cdego w\u0119z\u0142a (net tick). Je\u015bli lustro spowalnia lub pada, dodaje to op\u00f3\u017anienie.<\/li>\n<\/ul>\n<p>\nKafka stawia na to, \u017ce je\u015bli wiadomo\u015b\u0107 jest przechowywana na kilku w\u0119z\u0142ach, mo\u017cna potwierdza\u0107 wiadomo\u015bci, gdy tylko trafi\u0105 do pami\u0119ci. Z tego powodu istnieje ryzyko utraty wiadomo\u015bci wszelkiego rodzaju (nawet <i>acks=all<\/i>, <i>min.insync.repliki=2<\/i>) w przypadku jednoczesnej awarii.<\/p>\n<p>Og\u00f3lnie rzecz bior\u0105c, Kafka wykazuje wy\u017csz\u0105 wydajno\u015b\u0107 i jest pierwotnie zaprojektowana dla klastr\u00f3w. Liczb\u0119 obserwator\u00f3w mo\u017cna zwi\u0119kszy\u0107 do 11, je\u015bli jest to potrzebne dla niezawodno\u015bci. Wsp\u00f3\u0142czynnik replikacji 5 i minimalna liczba replik w synchronizowanym stanie <i>min.insync.replicas=3<\/i> sprawi\u0105, \u017ce utrata wiadomo\u015bci stanie si\u0119 bardzo rzadkim zjawiskiem. Je\u015bli twoja infrastruktura jest w stanie zapewni\u0107 taki wsp\u00f3\u0142czynnik replikacji i poziom redundancji, mo\u017cesz wybra\u0107 t\u0119 opcj\u0119.<\/p>\n<p>Klastrowanie RabbitMQ jest dobre dla ma\u0142ych kolejek. Ale nawet ma\u0142e kolejki mog\u0105 szybko urosn\u0105\u0107 przy du\u017cym ruchu. Gdy kolejki staj\u0105 si\u0119 du\u017ce, trzeba podj\u0105\u0107 trudn\u0105 decyzj\u0119 mi\u0119dzy dost\u0119pno\u015bci\u0105 a niezawodno\u015bci\u0105. Klastrowanie RabbitMQ najlepiej nadaje si\u0119 do nietypowych sytuacji, gdzie zalety elastyczno\u015bci RabbitMQ przewy\u017cszaj\u0105 wszelkie wady jego klastrowania.<\/p>\n<p>Jednym z antidotum na luk\u0119 RabbitMQ w odniesieniu do du\u017cych kolejek jest podzia\u0142 ich na wiele mniejszych. Je\u015bli nie wymagasz pe\u0142nego uporz\u0105dkowania ca\u0142ej kolejki, a jedynie odpowiednich wiadomo\u015bci (na przyk\u0142ad wiadomo\u015bci od konkretnego klienta), lub w og\u00f3le nie chcesz niczego porz\u0105dkowa\u0107, to taka opcja jest akceptowalna: zobacz m\u00f3j projekt <noindex><a rel=\"nofollow\" href=\"https:\/\/jack-vanlightly.com\/blog\/2018\/7\/22\/creating-consumer-groups-in-rabbitmq-with-rebalanser-part-1\">Rebalanser<\/a><\/noindex> do podzia\u0142u kolejki (projekt jest jeszcze na wczesnym etapie). <\/p>\n<p>Na koniec nie zapominaj o szeregu b\u0142\u0119d\u00f3w w mechanizmach klastrowania i replikacji zar\u00f3wno RabbitMQ, jak i Kafka. Z czasem systemy sta\u0142y si\u0119 bardziej dojrza\u0142e i stabilne, ale \u017cadna wiadomo\u015b\u0107 nigdy nie b\u0119dzie w 100% chroniona przed utrat\u0105! Ponadto w centrach danych mog\u0105 wyst\u0105pi\u0107 awarie na du\u017c\u0105 skal\u0119!<\/p>\n<p>Je\u015bli co\u015b przeoczy\u0142em, zrobi\u0142em b\u0142\u0105d lub si\u0119 nie zgadzasz z kt\u00f3rymkolwiek z tez, nie wahaj si\u0119 napisa\u0107 komentarza lub skontaktowa\u0107 si\u0119 ze mn\u0105.<\/p>\n<p>Cz\u0119sto pytaj\u0105 mnie: \u201eCo wybra\u0107, Kafka czy RabbitMQ?\u201d, \u201eKt\u00f3ra platforma jest lepsza?\u201d. Prawda jest taka, \u017ce to naprawd\u0119 zale\u017cy od Twojej sytuacji, obecnego do\u015bwiadczenia itd. Nie chc\u0119 wyra\u017ca\u0107 swojego zdania, poniewa\u017c by\u0142oby zbyt du\u017cym uproszczeniem poleca\u0107 jak\u0105\u015b jedn\u0105 platform\u0119 do wszystkich zastosowa\u0144 i mo\u017cliwych ogranicze\u0144. Napisa\u0142em ten cykl artyku\u0142\u00f3w, aby\u015b m\u00f3g\u0142 wyrobi\u0107 sobie w\u0142asn\u0105 opini\u0119.<\/p>\n<p>Chc\u0119 powiedzie\u0107, \u017ce oba systemy s\u0105 liderami w tej dziedzinie. Mo\u017ce jestem troch\u0119 stronniczy, poniewa\u017c na podstawie swoich projekt\u00f3w bardziej ceni\u0119 takie rzeczy jak gwarantowane uporz\u0105dkowanie wiadomo\u015bci i niezawodno\u015b\u0107. <\/p>\n<p>Widzia\u0142em inne technologie, kt\u00f3rym brakuje tej niezawodno\u015bci i gwarantowanego uporz\u0105dkowania, a potem patrz\u0119 na RabbitMQ i Kafka \u2014 i dostrzegam niesamowit\u0105 warto\u015b\u0107 obu tych system\u00f3w.<br \/>\n<br \/>\u0179r\u00f3d\u0142o: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/itsumma\/blog\/474984\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e RabbitMQ \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438. \u0422\u0435\u043f\u0435\u0440\u044c \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u043f\u043e\u043a\u043e\u043f\u0430\u0435\u043c\u0441\u044f \u0432 Apache Kafka. \u0417\u0434\u0435\u0441\u044c \u0435\u0434\u0438\u043d\u0438\u0446\u0435\u0439 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0430\u0437\u0434\u0435\u043b (partition). \u0423 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430 \u043e\u0434\u0438\u043d \u0438\u043b\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432. \u0412 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u0435\u0441\u0442\u044c \u043b\u0438\u0434\u0435\u0440 \u0441 \u0444\u043e\u043b\u043b\u043e\u0432\u0435\u0440\u0430\u043c\u0438 \u0438\u043b\u0438 \u0431\u0435\u0437 \u043d\u0438\u0445. \u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0442\u043e\u043f\u0438\u043a\u0430 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u043e\u0432 \u0438 \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u0438. \u041e\u0431\u044b\u0447\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 3, \u044d\u0442\u043e [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-52541","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"pl_PL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-11-10T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:00:17+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47RabbitMQ kontra Kafka: odporno\u015b\u0107 na awarie i wysoka dost\u0119pno\u015b\u0107 | ProHoster","description":"W","canonical_url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pl_PL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47RabbitMQ \u043f\u0440\u043e\u0442\u0438\u0432 Kafka: \u043e\u0442\u043a\u0430\u0437\u043e\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c \u0438 \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c | ProHoster","og:description":"\u0412","og:url":"https:\/\/prohoster.info\/pl\/blog\/administrirovanie\/rabbitmq-protiv-kafka-otkazoustojchivost-i-vysokaya-dostupnost","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-11-10T21:00:00+00:00","article:modified_time":"2020-02-18T11:00:17+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52541","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 03:57:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:41:24","updated":"2026-01-24 03:57:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/52541","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/comments?post=52541"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/posts\/52541\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/media?parent=52541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/categories?post=52541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pl\/wp-json\/wp\/v2\/tags?post=52541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}