zookeeper指北
zookeeper指北
1.zookeeper是什么
一個分布式協調服務框架,簡單點來說就是= 文件系統 + 監聽通知機制
定位更多的用到:服務注冊中心
2. zookeeper可以做什么
可以用來解決分布式應用中經常遇到的一些數據管理問題如:
分布式鎖
分布式鎖三個特點:多進程可見、互斥、可重入
利用zk所有寫入都順序經過leader實現分布式鎖。 具體實現思路:
注意:臨時節點只需要監聽前一個節點,可以防止羊群效應;使用臨時順序節點可以避免因為意外會話關閉,而節點沒有被刪除導致死鎖。
缺點: 性能有瓶頸,相當于單機,不支持大規模并發
自己實現上面代碼需要考慮很多細節異常處理,可以使用Curator框架實現。
/*** 使用 curator實現zk分布式鎖** Guava is to Java that Curator to Zookeeper** @author xuelongjiang* @description**/ public class CuratorDistributeLock {CuratorFramework client;InterProcessMutex lock;public CuratorDistributeLock() {RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);client = CuratorFrameworkFactory.newClient("127.0.0.1:2181",5000, 5000, retryPolicy);client.start();lock = new InterProcessMutex(client, "/goods/lock");}public boolean lock() {try {lock.acquire();return true;} catch (Exception e) {e.printStackTrace();}return false;}public void unlock() {try {lock.release();} catch (Exception e) {e.printStackTrace();}} }配置中心
可以用來管理公共的配置,當配置修改不需要重啟多臺服務器,只需要修改zk上保存的配置值,應用監聽到修改后更新值。
對應的配置中心還有:apollo(攜程阿波羅),etcd,spring-cloud-config, diamond, disconf, nacos
統一配置中心選型比較
服務注冊中心
分布式服務中,不同集群之間通信,為了便于管理,引入服務注冊中心。
直接通信:
集群A調用集群B,所以集群A每個實例保存了集群B所有的機器連接信息。
每次調用,集群A實例中通過負載均衡算法調用集群B中其中一臺。
當集群B中某臺機器失效了,依然還會調用。
使用注冊中心
集群B中的實例上線后,保存機器群到ZK的節點,集群A從ZK的節點讀取當前
有效的機器,當集群B中有機器下線了,zk刪除對應的節點,集群A的所有實例監聽到
變化更新自己緩存的集群B的機器信息
注冊中心介紹介紹
統一命名服務(分布式唯一Id生成器)
利用zk中順序節點的特性,制作分布式的序列號生成器(Id生成器)。
在DB沒有拆表的時候可以利用db主鍵唯一性生成id,但是當拆表后,同一個業務表
有多個,uuid也可以但是uuid時無序的很難理解,那么此時可以使用zk來獲取順序的id
zk實現命名服務
JNDI
JNDI: java naming and directory interface, 說白了就是把資源取個名字,再根據名字找資源
3. 實戰
創建設置讀取節點
創建如下節點:
--maven -------name:xue -------pass: 123創建節點:
create /maven/namecreate /maven/pass節點設置值:
set /maven/name xue set /maven/pass 123獲取節點值:
get /maven/name get /maven/pass創建四種類型節點
// 創建持久節點create /nodename //創建臨時節點create -e /nodename// 創建持久順序節點 create -s /nodename //創建臨時順序節點create -s -e /nodename臨時節點: 當前會話關閉后節點會自動被刪除
順序節點:節點從0000000000開始創建子節點,每次計數增加一
持久節點 + 臨時順序節點 可以實現分布式鎖
持久節點 + 臨時節點 可以實現服務注冊中心
配置文件參數解析
tickTime:
心跳時間,服務端之間或客戶端與服務端之間維持心跳的時間間隔,單位毫秒;
initLimit
服務端集群中連接到leader的follower初始化連接時最長能忍受多少個心跳時間間隔數,當超過initLimit*tickTime時間
后還沒有收到follower的返回信息,表示這個follower連接失敗
syncLimit
leader與follower之間發送消息,請求和應答時間長度,最長不能超過syncLimit*tickTime時間;
dataDir
zk保存數據的目錄,默認也將寫日志放在這個目錄下
clientPort
客戶端連接zk服務的端口,zk服務會監聽這個端口,接受客戶端的訪問s
server.n=B: C: D
n: 是一個數字,表示第幾號服務器
B: 集群的ip地址們(有幾臺就有幾號服務器)
C: 與leader服務器交換信息的端口
D: 如果leader掛了,用這個端口來選舉新leader
4. zk的架構及其角色
角色
- follower: 參與選leader的投票
- observer: 只同步leader的狀態,不參與選舉leader,加入observer的
目的為了擴展zk系統的讀能力
原子廣播: 保證各各個server之間狀態是統一的,實現這個機制的協議是zab協議
- 恢復模式:選主模式
- 廣播模式:同步leader的狀態給所有的learn
zid:64位 = 高32位(epoch標識當前的leader) + 低32位(用于遞增計數)
server的三種狀態:
zk特點:
5. zk原理
paxos算法
基于消息傳遞的一致性算法;paxos有一個前提:沒有拜占庭將軍問題,就是說
paxos只有一個可信的計算環境中才能成立,這個環境是不會被入侵所破壞的。
paxos場景
在一個小島上,有一定數量的議員,所有的事情由他們投票決定。島上每一次環境事務的變更都需要通過一個提議(proposal),每個提議都有一個編號(xid),這個編號一直增長,不能倒退,每次提議需要超過半數(n/2+1)的議員同意才能生效。每個議員只會同意大于當前編號的提議,小于的統一會拒絕。
paxos示例
現在我們開始運行一下這個算法,小島上有3個議員s1,s2,s3,所有議員的筆記本上編號都是0,現在s1提議電費1度/元,s1看了看自己當前最大的編號,然后發起1號提議,s2收到1號提議,看了看自己的筆記本當前 最大的編號是0,于是記錄這個提議,并告訴s1統一你的提案,此時s1統計收到了兩個議員的同意(自己和s2),已經大于當前一半的議員,提議生效,作為正式法令,廣播給所有的議員。這里可能有一個沖突,我們看看paxos如何解決的:還是這個小島有三個議員s1,s2,s3,和上面一樣,不同的是在s1發起提議的時候,s2也發起了,s1:發起1號提議電費1度/元;s2:發起1號提議電費2度/元,此時s3首先收到s1的提案,同意了s1的提案,s2的提議到達s3,s3發現自己當前已經同意了1號提議,直接拒絕,(每個議員只會同意大于自己記錄的最大編號)s1拿到了2票,大于集群一半,立即廣播所有集群,記錄下1號提議,此時所有議員的當前最大的編號都是1。
paxos與zk的對應
小島 --> zk集群
議員 --> zk server
提議 --> znode change(create, delete,setData)
提議編號 --> zid
正式法令 --> 所有node及其數據
實際上zk是有一個leader的概念,由他來發起提議(也就是所有寫操作都要轉到leader),為什么需要leader呢為了避免活鎖引入leader,
6.常見問題
zk寫為什么半數以上確認就可以了,那剩下的機器數據一直不同步怎么辦
一直不同步的機器leader會把其踢出集群,有session超時機制的,follower感知網絡出問題后會進入looking狀態,重新建立和leader的鏈接,然后同步有差異的數據。
cap:
一致性 consistemcy
可用性 availability
分區容錯性 partition tolerance
redis: ap
zk: cp
zk是一致性的嗎
zk核心算法paoxs是目前唯一的分布式一致性算法,zk滿足cap原則cp即一致性,分區容錯性(分布式應用基本是,同一份數據多處保存),但不是強一致性,只能滿足最終一致性。
zk使用zab協議進行leader與learn數據同步,Zab協議認為只要過半節點寫入成功,數據就算寫入成功,然后會告訴客戶端A數據寫入成功,如果這個時候客戶端B恰好訪問到還沒有同步最新數據的zk節點,那么
讀到的數據就是不一致性的,因此zk無法保證數據的強一致性,只能保證最終一致性,而且可以保證同一客戶端的順序一致性。
如何實現真正的強一致性?
zk既然不是強一致性的,那我們如何能保證兩個客戶端讀到的數據是一致性的呢,那就是sync方法,zk原生客戶端api和curator客戶端都提供了該sync方法,調用sync方法之后,zk集群會保證集群所有節點數據都是一致性的,此時客戶端再去任意節點讀取數據,都能讀到最新的數據
zk不保證強一致性的原因,我認為是可用性和一致性做了取舍。
分布式鎖zk和redis的區別
cap:
一致性 consistemcy
可用性 availability
分區容錯性 partition tolerance
zk保證cp, redis保證ap; zk鎖靠譜,就是性能不行,不適合c端用戶級別的鎖。
reids和zk應該都是base,zk也不是強一致性,讀也有可能讀到過期數據,也屬于最終
一致性,C還沒拉滿到強一致性(除非都讀leader),另外zk掛幾臺(沒超過一半)也
同樣可以繼續服務,A也有一定保障,
只能說Redis可用性拉高一點,一致性拉低一點
zk則一致性拉高一點,可用性拉低一點
為什么zk要部署奇數臺服務器
在zk集群中,如果宕掉了幾臺機器,剩下的機器大于集群總數的n/2,集群仍然可以繼續提供服務,zk集群最少是3臺機器組成,如果是2臺,其中一臺宕掉了,只剩下1臺,不大于集群總數的1/2,因此最少需要3臺集群,這里集群的容忍度是1,如果是4臺機器,宕掉一臺,還有3臺可以繼續提供服務,集群的容忍度還是1,從節約機器資源的角度看,沒必要部署偶數個服務,3臺的效果和4臺一樣,5臺的效果和6臺一樣。
參考
Zookeeper入門看這篇就夠了
zk官方文檔
七張圖徹底講清楚ZooKeeper分布式鎖的實現原理
3種Redis分布式鎖的對比
Zookeeper工作原理(詳細)
Zookeeper全解析——Paxos作為靈魂
Paxos算法詳解
死鎖、活鎖、饑餓
zookeeper是強一致性的嗎
ZooKeeper常見問題
總結
以上是生活随笔為你收集整理的zookeeper指北的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自然语言(NLP)处理流程—IF-IDF
- 下一篇: 《开源安全运维平台:OSSIM最佳实践》