二、zookeeper--基本原則

I.概要

1、基本的な概要

飼育係は、分散アプリケーションApacheプロジェクトへの協調的なサービスを提供するために、分散型のオープンソースです。HadoopのとHBaseの重要な要素。これは、分散アプリケーションのための一貫したサービスを提供することです。


2、ZK何を提供

ファイルシステムの通知メカニズム、クラスタ管理メカニズム:それはZK、ZKが、実際には3つしか物事を持つ多くの機能を実現することができますが。

(1)ファイルシステム

次のようにZKデータ構造は、構造、ファイルシステムに似て記憶されています。 B40C2E97AC6E4DB1B216DAFA24C5BC61?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                          図1.1 ZKファイルシステム

各ノードが呼び出されるのznodeは、それぞれのznodeのKVと同様の構造であり、各ノードは名前のキーに対応し、各ノードは、対応するキー値に類似し、対応するデータに格納されています。それぞれのznodeは、以下の複数の子ノードを有することができ、したがって、継続、およびLinuxファイルシステムと同様のフレームワークを構成しています。

(2)通知メカニズム

クライアントは、ノードの変更(子ノード、またはノードの値を増加させる可能性が高いが変更、など)のノード(話すの背後にある時計のメカニズム)、上で聴くとき、ZKクライアントノードのリスナーを通知します。フォローアップのプロセスは、クライアントのどのように処理ロジックを確認してください。

(3)クラスタ管理機構

自身ZK書き込み要求を担当するリーダーノードでクラスタ構成、で、要求に応答する責任もっとフォロワーをお読みください。そして時にリーダーノード障害は、自動的に選挙のメカニズムに従ってフォロワーの残りの部分から新しいリーダーを選出します。


3つの機能

1)飼育係:クラスターからなるリーダー(リーダー)、よりフォロワー(フォロワ)。 2)リーダーを開始し、解像度に投票する責任があり、それは、システムのステータスを更新します。 3)クライアント要求を受信するためのフォロワーは選挙リーダープロセスに投票する、クライアントに結果を返します。 4)奇数クラスタサーバーノードがあれば、生き残るために半分以上のように、飼育係クラスタは通常のサービスすることができるであろう。 一貫した5)グローバルデータ:各サーバがデータの同一のコピーを保持し、それがどのサーバ、データが一致しているように接続されているかどうかをクライアント。 6)更新要求、それらが送信された順序で実行する同じクライアントからの更新要求を注文します。 7)データ更新アトミック名、成功か失敗のどちらかのデータ更新。 特定の時間枠内に8)実名、クライアントは最新のデータを読み取ることができます。


概念と原則の二つ、ZK

1、ノードZK分類の役割

リーダー: 1.データを復元する。 2.学習者は、ハートビートを維持し、要求を受信し、学習者の学習要求メッセージタイプを決定する; 3.Learnerメッセージタイプは、メッセージに応じて、メッセージを再検証PINGメッセージは、要求メッセージ、ACKメッセージでありますタイプは、異なる処理が行われます。 PINGメッセージは、ハートビート学習者指し、REQUESTメッセージは、書き込み要求および同期要求を含むフォロワ送信オファー情報、であるACKメッセージは、その後、提案をコミットよりフォロワの半分を通るよりも、提案された応答のフォロワーであり、メッセージが再検証しますSESSIONは、効果的な時間を延長します。

フォロワー: 1)リーダー要求(PINGメッセージは、要求メッセージ、ACKメッセージ、再検証メッセージ)を送信; | 2)リーダーメッセージを受信して処理するステップと、 3)クライアント要求受信、リーダーに送信された書き込み要求として扱わ場合。 4)クライアントが結果を返します。

フォロワーメッセージリーダーから複数のメッセージ処理ループです: 1)PINGメッセージ:ハートビートメッセージ 2)提案メッセージ:リーダーは、提案はフォロワーの投票が必要です開始した 最新の提案についてのサーバー情報:3)メッセージCOMMIT 4)UPTODATEメッセージを:同期が完了したことを示す メッセージ再検証)5:結果を再検証するためによると、閉じられたセッションが受け入れるメッセージを再検証するために許可されるリーダー 。6)SYNCメッセージ:SYNCは、最新の義務を取得するには、メッセージが最初にクライアントによって開始された、クライアントに結果を返しますアップデート。

オブザーバー:と従動似ていますが、ではないが、投票や選挙に参加し 、学習者:フォロワーと観測者を総称して

図2に示すように、ノードZKのタイプ

ショートノード--ephemeral: クライアントとサーバーが切断され、ノードが削除された、独自に作成すること。プロセス内の他のノードにこの一時的に、切断されていないクライアントに表示されています。前記ノードは短く、短い番号と共通ノードに分割することができます。ephemeral_sequential呼ばれるシリアル番号と短いノードは、ノードの名前は順序を示す数字の文字列で最終になりますあります

永続ノード--persistent: 作成したノードは、クライアントとサーバーが切断されている場合でも、永続的になります。同様のバンドは、通常のシリアル番号に分割し、上記差


選挙のリーダーの3、ZK原則

まず、いくつかの概念で始まる: zxidを: 各修正は、(選挙などを発生する)、数字のzxid文字列があるだろうのデータZKとZKのステータスを変更、トランザクションの増加に伴って、それぞれが、インクリメンタルになります。だから、zxid小さなトランザクションは確かに最初に発生しました。

MYID(SID): 設定ファイルで指定した各サーバーノードZK番号は、それがグローバルに一意にする必要があります。

いくつかの州のZK: looking--は、リーダーを探していると述べ 、現在の選挙リーダーはleading-- 以下-選出されたリーダーの後、指導者との間でデータを同期させると従動する新しいという 観測を:オブザーバーは、選挙結果を受け入れています

以下の公式を話す選挙プロセス: リーダー選挙基づいPaxosアルゴリズムは、アルゴリズムの原理をよく見ないで、我々は単に選挙プロセスについて話しています。 (1)まず、投票のラウンド:他のノードにブロードキャストすべての生きZKノードが自分自身に投票し、投票結果を。現在のノードの最新zxidとSID:この時間は、他のノードの状況を知らないので、投票用紙上の2件の重要なメッセージがあります。同じ、SID、SID大きな選出されたリーダーをzxid場合は、新しいノードzxid大きいよりは、それほど大きなzxidノードは最初のリーダーとして選出され、データを持っています。sidはグローバルに一意であるので、この原理に基づいているためと、唯一のリーダーを選択することができます。 (2)投票の他のノードを受信すると、zxidとSIDの票を得、(1)最新の選択の原則を比較によると、その後、投票用紙を更新し、新しい投票用紙と投票を送った「最初のマーク2票。」各ノードは、一般的に矛盾し、異なるノードが遅れることで、時間内の他のノードポイントの票を受け取るので、我々はそれが選挙の投票が表示されるの異なるラウンドにつながる、それを注意してください。だから、ノードは、その後追い出し、彼の票が投じられた票の彼らの現在のラウンドよりも大きな倍を受け、その後、直接現在の投票用紙を更新したとき。投票の過半数がどのノードを発見した場合、各ノードは、(投票の時間で)票の統計情報をアーカイブされます、ノードは、キャストの最新(zxix、SID)票であり続けるだろう。 (3)複数の(2)工程の後、投票のノードアーカイブ場合は、より多くの票ノードの半分以上、それは投票を停止することを発見しました。ノードは、統計調査結果をアーカイブした場合、それは彼らのリーダーは、彼らは私がリーダーだ、他のノードがブロードキャスト言うだろうことが判明しました。 (4)他のリーダー・ノードが新しいメッセージを受信し、それがリーダーとフォロワーのデータの同期を開始します。


図4に示すように、メタ情報STATのノード

我々はSTATパスを使用するか、メタ情報のノードを表示するには、パスの方法を取得すると、情報項目の多くがあるでしょう、そして、各項目は何それはそれを意味するのでしょうか?

1)作成したこのzxid用のznodeを引き起こすzxidトランザクションノード作成czxid- 各変更ZooKeeperの状態がZooKeeperのトランザクションIDであり、タイムスタンプのzxid形態を、受信します。 総トランザクションIDは、すべての注文のZooKeeperに変更されます。zxid2よりzxid1が少ない場合には、各変更は、その後zxid2前に発生zxid1、ユニークzxidを持っています。 2)CTIME -ミリ秒のznode)は1970年から(作成する 3)mzxid -のznode最終更新zxidを 。4)のmtime -ミリ秒のznode最後に変更(1970)から 5)pZxid-のznode最終更新サブノードzxid 6)cversion -のznode子ノード番号変更、のznodeの子ノード番号修正 7)dataversion -のznodeデータ変更番号 8)aclVersion -のznode変更アクセス制御リスト番号 9)ephemeralOwner-ノードが一時的である場合、これはのznodeの所有者でありますセッションID。そうでない場合は、一時的なノードは0です。 データ長10)のdataLength-のznode 11)するnumChildrenは-子供の数のznodeノード


5、ZKの書き込み処理

D6828F1A7C514E3FAD2104EBD001E3C9?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                       図2.1 ZK書込データフロー

读是局部姓的,即client只需要从与它相连的follower上读取数据即可; 写请求时,follower会将请求转发给leader,leader通过transaction(事务)的形式广播执行,这个过程是怎样的呢? (1)leader 会给所有follower发送一个PROPOSAL提案消息 (2)一个follower接收到这次PROPOSAL消息,写到磁盘,发送给leader一个ACK消息,告知已经收到。 (3)当Leader收到法定人数(quorum)的follower的ACK时候,发送commit消息执行。 注意:只有发送commit之后,做的修改才会提交,不然是会回退的;如果发现写入超时,是会回退这个更新操作的。


6、监听器原理

1) 首先要有一个main()线程 2) 在main线程中创建ZK客户端,这时会创建两个线程,一个负责网络连接通信(connect),一个负责监听(listener) 3) 通过connect线程将注册的监听事件发送给ZK 4) 在ZK的注册监听器列表中将注册的监听事件添加到列表中 5) ZK监听到有数据或路径发生变化时,就会将这个消息通过connect线程发送给listener线程 6) Listener线程内部调用process()方法

命令行下:客户端使用类似 ls path watch 的方式来监听一个节点的子节点的变化 当节点的子节点发生变化时,会通知相应的客户端,会显示如下的信息:

WATCHER::

WatchedEvent state:SyncConnected type:NodeChildrenChanged path:/

WatchedEvent state:SyncConnected---事件状态:同步更新
type:NodeChildrenChanged---类型:节点的子节点改变
path:/--路径:/



三、应用场景

1、统一命名服务

9CC761843EBE4106B05AE07BC3760525?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                            图 3.1 zk统一命名服务

所谓命名服务就是对资源进行命名,用于更好地对资源进行定位。而zk本身的文件系统结构就可以创建以路径为名称的节点,用于存储服务器地址等信息。并且每个节点的名称都不会重复,严格按照文件系统的限制实现的。阿里巴巴开发的分布式服务框架DUBBO就是用zookeeper来作为其命名服务,维护全局的服务器列表,实现方式就是服务器启动时,在ZK的某个路径下创建一个代表自己的节点,节点的value存储的就是对应服务的服务地址(比如说URL地址)。


2、统一配置管理

36EBB12C1A77478AA11D412E6E3F52ED?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                图 3.2 zk统一配置管理

在集群中环境的服务中,同一个程序会分布在多台机器上运行,便于横向扩展。个程序一般都会需要一些配置信息,如果程序分散部署在多台机器上,要逐个改变配置就变得很困难。同时,目前各种分布式系统以及微服务的流行,如何有效管理不同组件的配置也是一项重要的问题。现在可以在zk上创建一个节点,将配置信息作为节点的值。然后相关的应用程序都监听这个节点。当节点中的数据发生变化时,zk就会通知这些监听的程序说:“有东西改变了”。这些监听者就会自动到zk上获取更改后的配置信息,接着后面如何处理就看具体的业务逻辑了。 其实这是用到了zk的watcher机制,也就是发布/订阅机制,客户端可以向zookeeper服务器注册watcher,订阅自己感兴趣的节点,当相应的节点发生变化时,zookeeper服务器就会向客户端发布通知。 类似的场景还会用在服务高可用中,比如有两台数据库服务器,一主一备。 0ED4F8C460174BA9B154DA0F445D16E8?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                    图3.3 zk统一配置管理--数据库主备

其中主备的数据中都运行一个zk的监控进程client,用于监控数据库服务的可用姓。当服务可用时,主备数据库的client会和zk建立持久会话,向zk发送心跳信息,表示自己正常运行。zk收到心跳信息,就会在节点上创建相应的节点,节点数据为当前可用的主数据的地址(实际上没有这么简单,这里只是简化了,便于理解)。如果任意一个数据库服务下线了,那么对应的在zk上的节点也会被删除。


3、服务动态上下线感知

BBF6DDACDCF24938B50E9E3D4CEA9A64?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                       图 3.4 zk服务动态上下线感知

对于一些复杂的分布式系统来说,系统中不同的组件非常多,即不同的服务很多。同一服务中还存在多台并发处理的服务器。那么如何知道这些服务哪些是可用的,哪些是不可用的呢?这就得用到zk了。 当服务上线时,会创建zkclient,并和zk保持持久会话,然后在zk的特定特定目录下创建一个临时znode(会话一断开,znode就消失)。而需要访问这些服务的客户端,就会监听在这个目录下(watcher机制),通过 getChildren() 这个api监听。当目录下的节点发生变化时,就意味着那些服务有下线或者上线了。这时候zk就会通知监听(订阅)该节点的客户端来获取最新的可用的服务列表。这样就可以动态上下线可用的服务。


4、统一集群管理

zk可以用于保存其他业务集群中每个节点的状态信息,特别是一些主从结构的集群中。当发生故障转移时,可以从zk获取当前每个节点的状态信息。典型的比如 HBase的master节点的选举,就是通过zk协调状态实现的。 集群每个节点会在对应的一个znode下创建自己对应的子znode,用于保存自己的状态。然后每个节点都监听在这个znode下,也就是监听每个节点状态的变化。正常情况下,如果一个集群不发生故障,zk中保存的所有节点信息是不会变化的。如果zk中发生变化,意味着集群有故障发生。后续集群可借助zk中的节点状态数据来进行下一步的故障处理,比如选举新的master等操作。


5、软负载均衡

810787B2B65E482890CD0A87EE69195D?方法=ダウンロード&shareKey = f5d578df9d0edfd741465a81695e3422

                                                   图3.5 zk软负载均衡

每个到服务列表下注册的服务节点,相应的znode下的数据会保存服务地址,以及当前处理的访问数。当客户端来获取服务列表时,可以根据访问数选择比较少的一个服务节点进行请求的分发。达到一定的负载均衡的作用。


6、分布式锁

在一些资源的使用上,为了防止不同的请求的读写相互产生干扰,有了锁的概念。比如并发情况下,购买一件限量的商品。为了保证商品的数量是安全的,就需要用到锁机制。 锁分为共享锁(也叫读锁)和排他锁(也叫写锁)。获取共享锁时,所有事务都可以对数据进行读取,但是都不能修改数据。获取排他锁时,只有当前事务可以读取和修改数据,其他事务不可以。 在分布式系统中,对某些资源的限制就必须采用分布式锁,这种锁比起传统的非分布式锁复杂。可以使用zk来实现,实现方式也很多,下面讲一种。

首先,需要获取锁的人要在zk的特定目录下创建一个临时节点,并标明是读锁还是写锁。那么,这个目录下所有的节点都是想要获取锁的人。接下来就监听在这个目录下,有通知了,就表示有新的人要获取锁了。因为有很多人想获取锁,那么就要有个先后顺序,顺序由节点的顺序决定。 接着,就是节点的顺序问题了,如果都是读锁,那么顺序不影响;如果都是写锁,就得严格按照节点的顺序来决定获取写锁的顺序;如果两种锁混杂,节点的顺序是会影响到获取锁的顺序的。对于这样的场景,实现逻辑是这样的: (1)如果当前需要获取读锁,则判断该节点前面是否有比自己序号小的写节点,如果有,那么肯定得先等那个写节点获取写锁释放之后才轮到自己;如果没有,那么表示在自己前面的都是读锁,大家可以不用等待,可以一起获取读锁了。 (2)如果当前需要获取写锁,就需要看自己是不是序号最小的节点了,如果不是,那么意味着前面的写节点和读节点,无论是哪个,都不能让自己获取到写锁的。 最后,因为创建的节点都是临时节点,所以只要断开会话,就会自动删除,也就实现了锁的释放。


7、队列管理

分布式系统中,非常重要的一个组件就是消息队列,可以实现应用解耦,异步消息,流量消减。首先传统的用户请求都是请求者直接发给服务器,服务器处理完成之后在将结果返回给请求者,这样会导致一个问题就是请求者在发出请求后会阻塞住,在收到服务器回复之前什么都干不了,而如果引入了消息队列,那么这个处理的流程就会变成请求者先把请求发给消息队列,然后服务器在从消息队列获得需要处理的消息,处理完成之后在将结果返回给请求者,这种方式下,请求者只要把请求发给消息队列就可以干其他事情了,这样就实现了请求的异步处理,也解除了请求者和服务器之间的耦合。 而在典型的大流量场景中,大量请求涌入到服务器时,会造成服务的瘫痪,所以需要有有个限流措施,但是又不至于丢失请求。所以需要一个组件将请求暂存,然后以一定的速度转发给服务器进行处理,这个组件就是消息队列。这种做法称为流量消减。 还有典型的抢购场景中,大量抢购请求会涌入到服务器中,为了防止服务器崩溃。可以使用消息队列,并将队列的大小设置为抢购数量的大小,超过则返回失败,也就抢不到东西了。成功的就会暂存在队列中,给服务器慢慢处理。 ZKキューは、特定のディレクトリ内のノード、ストレージ要求を作成するだけです。サーバは、順次要求ノードのディレクトリから読み出され、処理結果を返します。処理後のノードの完全な欠失です。



おすすめ

転載: blog.51cto.com/kinglab/2447330