ZooKeeperたたは分散ロックサヌビスを蚘述する

免責事項先月、ZooKeeperで敎理し、名前から考えられるように、ロックサヌビスに぀いおではなく、実際にそれに぀いおの投皿を䜓系化したいず思いたした。 行こう

マルチスレッドプログラミングから分散システムのプログラミングに移行するず、倚くの暙準的な手法が機胜しなくなりたす。 これらの手法の1぀は同期化されたす。スコヌプが1぀のプロセスに制限されおいるため、分散システムの異なるノヌドで動䜜するだけでなく、同じマシン䞊の異なるアプリケヌションむンスタンス間でも動䜜したせん。 ロックには別のメカニズムが必芁であるこずがわかりたす。

分散ロックサヌビスを芁求するのは合理的です。
  1. ネットワヌクの点滅状態での䜜業胜力分散システムの最初のルヌルは、ネットワヌクが分散システムに぀いお誰も話さないこずに察しお信頌できないこずです 
  2. 単䞀障害点がない

ZooKeeperは、このようなサヌビスの䜜成を支揎したす。

画像 りィキペディアによるず、 ZooKeeperは分散構成および同期サヌビスであり 、あなたのこずは知りたせんが、この定矩からはあたりわかりたせん。 私の経隓を振り返るず、 ZooKeeperの代替定矩を提䟛できたす。これは、次のプロパティを持぀分散キヌ/倀ストレヌゞです。

なじみのないシステムに慣れるには、たず提䟛するAPIから始める必芁がありたす。

サポヌトされおいる操䜜


存圚するznodeの存圚を確認し、そのメタデヌタを返したす
䜜成するznodeを䜜成したす
削陀するznodeを削陀したす
getDataznodeに関連付けられたデヌタを取埗したす
setData新しいデヌタをznodeに関連付けたす
getChildren指定されたznodeの子を取埗したす
同期する接続しおいるクラスタヌノヌドずりィザヌドの同期を埅機しおいたす。

これらの操䜜は、次のグルヌプに分類できたす。
コヌルバックキャス
存圚する削陀する
getDatasetData
getChildren䜜成する
同期する

コヌルバック -コヌルバックを瀺すこずができる読み取り専甚操䜜。コヌルバックは、芁求された゚ンティティが倉曎されたずきに機胜したす。 コヌルバックは1回しか機胜したせん。倀を垞に監芖する必芁がある堎合は、むベントハンドラヌに垞に再サむンむンする必芁がありたす 。

CAS-曞き蟌み芁求。 ZooKeeperの競合アクセスの問題は、compare-and-swapによっお解決されたした。バヌゞョンは各znodeに保存されたす。倉曎する堎合、znodeがすでに倉曎されおいるかどうかを瀺す必芁がありたす。バヌゞョンが䞀臎しないため、クラむアントは察応する䟋倖を受け取りたす。 このグルヌプの操䜜では、倉曎するオブゞェクトのバヌゞョンを指定する必芁がありたす。

create-新しいznodeキヌ/倀のペアを䜜成し、キヌを返したす。 匕数ずしお瀺されおいる堎合、キヌが返されるのは奇劙に思えたすが、実際には、ZooKeeperにキヌのプレフィックスを付けお、znodeがシヌケンシャルであるず蚀うこずができ、その埌、アラむメントされた数倀がプレフィックスに远加され、結果がキヌずしお䜿甚されたす 同じ接頭蟞を持぀順次znodeを䜜成するこずにより、キヌが蟞曞グラフィックの意味で増加するシヌケンスを圢成するこずが保蚌されたす 。

シリアルznodeに加えお、 䞀時znodeを䜜成できたす。これは、䜜成したクラむアントが切断されるずすぐに削陀されたす ZooKeeperのクラスタヌずクラむアント間の接続は長時間開いたたたになるこずを思い出したす。 ゚フェメラルznodeには子を含めるこずはできたせん。

Znodeは、䞀時的でもシヌケンシャルでもかたいたせん。

sync-クラむアントが接続されおいるクラスタヌノヌドをマスタヌず同期したす。 同期は迅速か぀自動的に行われるため、氞久に呌び出さないでください。 い぀電話をかけるかに぀いおは、以䞋で説明したす。

連続する䞀時的なznodeずそれらの削陀のサブスクリプションに基づいお、分散ロックシステムを簡単に䜜成できたす。

分散ロックシステム


実際、すべおが私たちの前に発明されたした-私たちは、レシピセクションの ZooKeeperりェブサむトに行き、そこでブロックアルゎリズムを探したす

  1. 「_locknode_ / guid-lock-」をプレフィックスずしお䜿甚しお䞀時的なシリアルznodeを䜜成したす。ここで、_locknode_はロックしおいるリ゜ヌスの名前、guidは新しく生成されたガむドです
  2. むベントにサブスクラむブせずに、子のリスト_locknode_を取埗したす
  3. 最初のステップで䜜成されたznodeのキヌに最小の数倀接尟蟞がある堎合アルゎリズムを終了したす-リ゜ヌスを取埗したした
  4. そうでない堎合、子ノヌドのリストをサフィックスで゜ヌトし、ステップ1で䜜成したものの前にリストにあるznodeのコヌルバックで呌び出しが存圚したす。
  5. falseになった堎合はステップ2に進み、そうでない堎合はむベントを埅っおステップ2に進みたす

マテリアルの同化を確認するには、自分で理解しおみおください。降順たたは昇順で、ステップ4でリストを゜ヌトする必芁がありたす。

ZooKeeperの操䜜䞭に操䜜が萜ちた堎合は、操䜜が成功したかどうかを確認できないため 、このチェックをアプリケヌションレベルで行う必芁がありたす。 これには、GUIDが必芁です。それを知っお、子に尋ねるず、新しいノヌドを䜜成したかどうかを簡単に刀断でき、操䜜を繰り返す䟡倀がありたす。

ちなみに、私はそうは蚀いたせんでしたが、シヌケンシャルzノヌドのサフィックスを蚈算するために、䞀意のプレフィックスシヌケンスではなく、zノヌドが䜜成される䞀意の芪シヌケンスを䜿甚しおいるこずを既に掚枬したず思いたす。

WTF


理論的には終了できたすが、実践が瀺しおいるように、最も興味深いものが始たりたす-wtf 'ki。 wtfずは、システムに関する私の盎感的なアむデアずその実際の動䜜ずの間の矛盟を意味したす。

WTF1-コヌドを裏返しにする


すべおのAPIメ゜ッドは、チェック枈み䟋倖をスロヌし、それを凊理するように匷制できたす。 分散システムの最初のルヌルはネットワヌクが信頌できないずいうこずなので、これは銎染みのない、しかし正しいです。 飛ぶ可胜性のある䟋倖の1぀は、接続の切断ネットワヌクの点滅です。 接続が倱われたクラスタヌノヌドCONNECTIONLOSSず混同しないでください。この堎合、クラむアントは保存されたセッションずコヌルバック別の接続たたは埅機で埩元し、この堎合、クラスタヌからの接続ずすべおのコヌルバックの損倱SESSIONEXPIREDを匷制的に閉じたすコンテキストを埩元するタスクはプログラマヌにありたす。 しかし、私たちはトピックから離れたした...

りむンクを凊理する方法 実際、 クラスタヌずの接続を開くずき、他の人のように䞀床だけではなく、繰り返し呌び出され、倱われた接続ず埩元された接続に関するむベントを配信するコヌルバックを瀺したす 。 接続が倱われたずきに刀明したす。蚈算を䞀時停止し、目的のむベントが到着したら続行する必芁がありたす。

これは䜕かを思い出させたすか 䞀方で-むベント、他方では-私の意芋では、継続ずモナドのどこかで、プログラムの流れで「遊ぶ」必芁性。

䞀般に、プログラムのステップは次の圢匏で蚭蚈したした。

public interface Task { Task continueWith(Task continuation); //     void run(Executor context, Object arg); //   void error(Executor context, Exception error); //  ,    -   } 

゚グれキュヌタヌはどこですか

 public interface Executor { void execute(Task task, Object arg, Timer timeout); // timeout     / TimeoutException  error ,   real-time } 

必芁なコンビネヌタを远加するず、次のプログラムをビルドできたす。どこかでステップのべき等性を䜿甚し、どこかで明瀺的にゎミをクリヌンアップしたす

画像


Executorを実装するずきに、ラッパヌ関数をZooKeeperクラスに远加しお、すべおのむベントのハンドラヌであり、Watcher呌び出すむベントハンドラヌ自䜓を決定したす。 実装内に、3぀のBlockingQueueずそれらを読み取る3぀のスレッドを配眮したした。その結果、むベントが到着するずeventQueueに远加されるため、ZooKeeper内のすべおのWatcherは1぀のスレッドで動䜜し、 、したがっお、1぀のむベントを凊理するず、他のすべおのむベントがブロックされ、ZooKeeper自䜓がブロックされる堎合がありたす 。 taskQueueの2番目のタヌンでは、匕数ずずもにTask'iが远加されたす。 これらのキュヌeventQueueおよびtaskQueueは、それぞれフロヌ、eventThreadおよびtaskThreadに割り圓おられ、これらのスレッドはキュヌを読み取り、各着信オブゞェクトをJobにラップしお、実際にタスクコヌドたたはハンドラヌを実行する独自のスレッドを持぀jobQueueに入れたすメッセヌゞ。 接続に倱敗した堎合、taskThreadスレッドは䞭断され、ネットワヌクが䞊昇した堎合、再開されたす。 1぀のスレッドでシャッフルずハンドラヌのコヌドを実行するず、ロックを心配する必芁がなくなり、ビゞネスロゞックが容易になりたす。

WTF2-メむンサヌバヌ


ZooKeeperでは、サヌバヌクラスタヌがメむンであり、クラむアントには実質的に暩利がないず蚀えたす。 時々これは絶察になりたす、䟋えば... ZooKeeper構成にはセッションタむムアりトなどのパラメヌタヌがあり、クラスタヌずクラむアント間の接続がどれだけ消えるかを決定したす。最倧倀を超えるず、このクラむアントのセッションが閉じられ、このクラむアントのすべおの䞀時znodeが削陀されたす; 接続が埩元されるず、クラむアントはSESSIONEXPIREDむベントを受け取りたす。 そのため、接続が倱われCONNECTIONLOSS、セッションタむムアりトを超えるず、愚かに埅機しお䜕もしたせんが、アむデアによれば、セッションがデッドであるず掚枬し、SESSIONEXPIREDをハンドラヌにスロヌできたす。

この動䜜のため、開発者はある時点で髪を匕き裂きたす。たずえば、ZooKeeperサヌバヌを䞊げお接続しようずしたしたが、蚭定に誀りがあり、間違ったアドレスたたはポヌトをノックするず、䞊蚘の動䜜に埓いたす。 、MySQLなどの堎合のように、クラむアントがCONNECTED状態になり、゚ラヌメッセヌゞが衚瀺されなくなるたで埅぀だけです。

興味深いこずに、このシナリオを䜿甚するず、本番環境でZooKeeperをシヌムレスに曎新できたす。

ちなみに、この動䜜のために、゚グれキュヌタタむマヌに枡すのは、あたり長く接続できない堎合にタスクの実行をキャンセルするからです。

WTF3-Intオヌバヌフロヌ


䞊蚘のアルゎリズムに埓っおロックを実装し、このビゞネスを高負荷の生産で開始したずしたす。たずえば、1日あたり10 MMのロックを取埗するずしたす。 箄1幎埌、あなたは地獄にいるこずに気づく-ロックは動䜜しなくなりたす。 実際には、1幎埌にzversionカりンタヌのcversionがオヌバヌフロヌし、連続するznode名の単調に増加するシヌケンスの原則に違反するこずになりたす。これがロックの実装の基瀎ずなりたす。

どうする 定期的に_locknode_を削陀/再䜜成する必芁がありたす-関連付けられたカりンタヌがリセットされ、単調なシヌケンスの原則に再床違反したすが、実際には、 znodeは子がない堎合にのみ削陀でき 、今では_versionnode_ cversionがリセットされる理由を掚枬したす子がなく、ロックアルゎリズムに圱響したせん。

WTF4-クォヌラム曞き蟌みが読み取りではない


ZooKeeperが曞き蟌み芁求に察しおOKを返した堎合、これはデヌタがクォヌラム クラスタヌ内のほずんどのマシン、3台のマシンの堎合、クォヌラムは2で構成されおいるに曞き蟌たれたこずを意味したすが 、ナヌザヌの読み取り時には、接続先のマシンからデヌタを受け取りたす。 ぀たり、ナヌザヌが叀いデヌタを受け取ったずきに状況が発生する可胜性がありたす。

ZooKeeper以倖の方法で顧客が通信しない堎合、ZooKeeperのすべおの操䜜は厳密に順序付けられ 、埅機する方法を陀いおむベントが発生したこずを確認する方法がないため、これは問題ではありたせん。 なぜこれがすべお順調であるのかを自分で掚枬しおください。 実際、クラむアントは、誰も圌に倉曎を加えなかったずしおも、デヌタが曎新されたこずを知っおいる堎合がありたす-圌が自分で倉曎を加えた堎合、ZooKeeperは曞き蟌みの䞀貫性の読み取りをサポヌトしおいるため、これは問題ではありたせん。

それでも、あるクラむアントがZooKeeper通信チャネルを介しおデヌタの䞀郚の倉曎を発芋した堎合、匷制同期が圌を助けたす-これがsyncコマンドの目的です。

性胜


ほずんどの分散キヌ/倀ストレヌゞは、分散を䜿甚しお倧量のデヌタを栌玍したす。 すでに曞いたように、ZooKeeperがそれ自䜓に保存するデヌタはRAMのサむズを超えおはなりたせん。なぜそれが分散されるのか尋ねられたす-信頌性を確保するために䜿甚されたす。 蚘録のためにクォヌラムを取埗する必芁があるこずを思い出しお、3台のマシンのクラスタヌを䜿甚するず、1台のマシンず比范しおパフォヌマンスが15䜎䞋するこずは驚くこずではありたせん。

ZooKeeperのもう1぀の機胜は、氞続性を提䟛するこずです。ディスクぞの曞き蟌みにかかる時間が芁求凊理䞭に含たれるため、氞続性も必芁です。

そしお、パフォヌマンスぞの最埌の打撃は、芁求の厳密な順序によるものです-すべおの曞き蟌み芁求が1぀のクラスタヌマシンを通過するようにしたす。

私はロヌカルのラップトップでテストしたした、はい、それは非垞に䌌おいたす
画像
デノォプスボラット
Big Data Analyticは、文で「ベンチマヌク」ずいう単語を䜿甚しおいるdevopsの90が同じ文で「laptop」ずいう単語も䜿甚しおいるこずを瀺しおいたす。
しかし、ZooKeeperが高速ディスクず少量のデヌタを備えた単䞀ノヌド構成で最高のパフォヌマンスを発揮するこずは明らかであるため、SSDずi7を搭茉したX220はこれに最適です。 䞻に曞き蟌み芁求をテストしたした。

パフォヌマンスの䞊限は、集䞭的な蚘録䞭に1秒あたり玄1䞇回の操䜜でした。曞き蟌みに1ミリ秒かかりたす。したがっお、1぀のクラむアントから芋るず、サヌバヌは1秒あたり1䞇回の操䜜より速く実行できたせん。

これはどういう意味ですか ディスクに䌑たない状態10のレベルでのssdの䜿甚、忠実床のために、ramfsを介しおメモリにデヌタを配眮しようずしたした-パフォヌマンスが少し向䞊したした、CPUに遭遇したす。 合蚈で、ZooKeeperはサむトの䜜成者が瀺した数の2倍しか遅いこずがわかりたせん。これは、すべおを取埗する方法を知っおいるこずを考えるず悪くありたせん。

たずめ


ここで曞いたすべおのこずにもかかわらず、ZooKeeperは芋た目ほど悪くはありたせん。 私はその簡朔さ7チヌムのみが奜きです。プログラマAPIをプッシュしお、分散システムの開発における適切なアプロヌチに導く方法が奜きです。぀たり、 すべおの操䜜がシステムを䞀貫した状態のたたにする必芁があるため、い぀でもすべおが萜ちる可胜性がありたす 。 しかし、これらは私の印象であり、ZooKeeeperが䜜成されたタスクを解決するずいう事実ほど重芁ではありたせんクラスタヌ蚭定の保存、クラスタヌステヌタス接続されたノヌドの数、ノヌドステヌタスの監芖、ノヌド同期ブロック、バリアおよび分散システムノヌドの通信a-la jabber。

繰り返しになりたすが、ZooKeeperで開発する際に留意すべき点をリストしたす。


分散ロックに぀いお


䞊蚘のブロッキングアルゎリズムに戻るず、それは機胜せず、より正確には、クリティカルセクション内のアクションがブロッキングに䜿甚される同じZooKeeperクラスタヌでのみ発生するたでスムヌズに機胜したす。 なぜそう -自分で掚枬しおみおください。 そしお次の蚘事では、分散ロックをより正盎にし、クリティカルセクション内の操䜜のクラスをCASをサポヌトするキヌ/倀ストレヌゞに拡匵する方法を説明したす。

ZooKeeperの情報ぞのリンク


zookeeper.apache.org
outerthought.org/blog/435-ot.html
highscalability.com/zookeeper-reliable-scalable-distributed-coordination-system
research.yahoo.com/node/3280

Source: https://habr.com/ru/post/J144708/


All Articles