天天看點

ZooKeeper分布式一緻性協調服務架構+過半數存貨原則

zookeeper

什麼是zookeeper?

分布式一緻性協調服務架構

換言之,也可以zookeeper看成一個小型的分布式檔案系統,

但是與FastDFS不同,zookeeper隻适合用來存儲一些小型的資料或者配置資訊

提供配置資訊管理,命名服務,分布式同步

zookeeper安裝

1.zookeeper是純java的是以需要JDK環境

2.單機安裝-配置data/log路徑後啟動即可

zookeeper的檔案系統

檔案系統的資料結構

zookeeper底層是一個樹形結構,用來存儲資料

和Linux,Window等系統不同,Linux和Window中有檔案和檔案夾的概念,檔案夾下面才能有檔案,檔案下面不能有檔案,檔案夾本身不存放資料,檔案本身用來進行資料存儲;

zookeeper中的結點,沒有檔案夾和檔案之分,所有結點都可以進行資料存儲,同時也可以擁有子節點;

每個結點稱之為ZNode

ZNode的分類

1.臨時節點-ephemeral:

臨時節點由某個用戶端建立,如果該用戶端斷開了和zookeeper伺服器的連接配接,則該臨時節點就會自動删除;

注意:臨時節點不能有子節點

2.持久性節點-persistent:

持久化的節點會永久存在于檔案系統中,除非用戶端顯示的删除該節點;該節點是最常見的節點;

3.順序節點:

3.1臨時順序節點-ephemeral_sequential:

和臨時節點有相同的特點,唯一的差別在于該節點名稱會自動維護一個編号

3.2持久順序節點-persistent_sequential:

和持久化的節點由相同的特點,唯一的差別在于該節點名稱會自動維護一個編碼

zookeeper檔案系統操作指令

1…/zkCli.sh ip -p port;

進入指令行

2.ls path;

檢視某個路徑下的子節點情況,在zookeeper中隻能寫絕對路徑,所有的路徑都必須從/出發

3.create -s(順序節點) -e(臨時節點) path(路徑) data(資料) acl(權限);

建立新節點,資料不能為空

4.get path;

檢視指定路徑對應的節點資料(資料部分+描述部分)

5.set path data [version]

修改指定節點的資料

6.delete path data

删除指定節點的資料

Java如何操作zookeeper

引入依賴然後,建立 zookeeper對象操作即可

zookeeper的通知(watch)機制

什麼是通知機制?

用戶端可以選擇對某個ZNode進行監聽,當這個ZNode發生變化時(本身的添加删除,修改以及子ZNode的變化),會主動通知監聽了這個ZNode的用戶端,zookeeper的通知機制有一次性觸發原則,ZNode發生變化後,一旦通知了用戶端,則斷開用戶端的監聽,如果需要繼續監聽節點的變化,則必須重新發起監聽

監聽方法

自定義類MyWatch實作Wathcer接口,實作zookeeper的通知回調方法

//判斷abc是否存在,并設定一個監聽
//可以監聽到節點建立,節點的内容修改,節點的删除
//但是不能監聽到子節點的變化
zookeeper.exists("/abc",new MyWatch());

//無法監聽到節點的建立,如果abc不存在則報錯
//可以監聽目前節點的内容修改,删除
zookeeper.getData("/abc",new MyWatch(),null);

//無法監聽到節點的建立,如果abc不存在則報錯
//無法監聽節點本身的變化
//可以監聽子節點的變化,子節點的添加和删除
//但是不包含内容變化,也不包括孫子節點的變化
zookeeper.getChildren("/abc",new MyWatch());
           
watch類型

1.資料watch

exists();

getData();

2.孩子watch

getChildren();

注意:不同的API監聽的動作不同

事件類型

None:斷開連接配接

NodeCreated:t添加

NodeDeleted:删除

NodeDataChanged:隻和版本号有關

NodeChildrenChanged:子節點建立或删除

ZooKeeper的運用場景(重點)

1.配置檔案統一管理

對分布式系統來說,有很多服務部署在不同的伺服器上,不同的伺服器有自己一套配置,如果需要配置進行調整,則需要對多台伺服器逐個的修改,是不便于管理的

在zookeeper中建立/Configuration持久化節點,将配置資訊放在其中

每個用戶端都監聽(Watch機制)該持久節點,如果有新的配置資訊,開發者隻需要上傳到zookeeper這個節點上(更新節點的配置資料),一旦節點内容修改,每個應用都會得到zookeeper的通知,然後從中獲得新的配置資訊,在系統中完成配置更新;

2.叢集管理

所謂叢集管理無在乎兩點:是否有機器退出和加入,選舉master

在某些叢集中可能需要其他叢集伺服器的狀态,比如有機器加入或退出叢集等,這個時候就可以通過zookeeper進行叢集的統一管理

所有機器約定在父目錄/GroupMembers下建立臨時節點,每一個節點就代表一台機器,然後監聽父目錄節點的子節點的變化消息

一旦有機器添加和删除,每個機器都會收到通知,接受通知後,每個機器可以在查詢節點資訊,就可以知道哪個節點添加或者删除,就知道哪個機器進入或退出了,然後進行叢集的配置

master選舉的話我們一般通過在父節點建立順序臨時節點,選擇編号最小的機器即可

3.分布式鎖

實作方式:

1.保持獨占:單程序

我們把zookeeper上的一個znode看做一把鎖,所有的用戶端同時建立一個lock臨時節點,通過createNode()方法,誰建立成功,誰就獲得鎖了;業務操作結束後,釋放鎖删除該節點即可,就算用戶端斷開臨時節點也會删除是以不用擔心會形成死鎖;

2.控制時序:加鎖排隊

建立一個父節點,所有的用戶端在它下面建立順序臨時節點,我們保證編号最小的獲得這個鎖就可以了

4.命名服務(服務的發現和注冊)

Dubbo使用的就是這個場景,基于ZooKeeper注冊中心,命名服務

假設有一個A服務需要調用B服務,但是AB是兩個互相獨立的服務,A先完成,B還沒有完成

A就可以主動獲得zookeeper某個節點"/name",A就可以不需要再管了,B一旦完成,B直接去"/name"節點上将位址加入其中,A服務就監聽到了節點内容的修改,就能夠調用該位址

對于叢集的負載均衡在父節點下面添加子節點就可以實作

Dubbo+ZooKeeper

在zookeeper的根目錄下有/dubbo節點

/dubbo節點下面就是我們釋出的服務節點

各個服務節點下面就有我們的服務資訊,消費者,提供者,配置資訊各種節點…

服務者節點中就存放了我們需要的調用位址,消費者一旦啟動就會去其中獲得調用位址,并且消費者也有位址但沒有實際作用;

ZooKeeper叢集,leader-follower

ZooKeeper叢集由N台機器搭建,這些機器中一定會存在一個leader,其他的機器都是follower,所有用戶端都可以随意連接配接叢集中的任一機器;

對于内容修改操作,所有的follower都會收到leader的指令,由leader發起投票,票數超過一半以上則送出指令

叢集搭建兩種方式

僞叢集模式

單機機器中啟動多個ZooKeeper程序,并組成叢集

步驟:

1.将單機裝的zookeeper檔案複制兩份

2.在zookeeper/data中建立myid檔案并編寫id編碼

3.修改zookeeper/conf/zoo.cfg核心配置檔案port,以及data/log路徑,還要配置

server.1=127.0.0.1:2888:3888

server.2=127.0.0.2:2889:3889

server.3=127.0.0.3:2890:3890

(這兩個端口是叢集内部通訊的端口)

真實叢集就是不需要修改配置port和data路徑

然後配置server的時候ip不一緻

4.啟動叢集

./zkServer.sh status 檢視服務狀态,可知道leader/follower角色

叢集模式

過半數存活原則

在zookeeper叢集中,當存活的機器數量超過總機器的一半的時候,整個叢集才能正常工作,否則拒絕通路

基于過半數存活原則,zookeeper的叢集機器數量一定是奇數台,因為2N+1和2N+2的容災能力是一樣的,基于成本考慮2N+1台的選擇方案更優

為什麼zookeeper需要設計一個過半數存活機制?

為了防止網絡腦裂,保證資料的強一緻性

因為整個叢集中,有可能因為網絡問題"腦裂",導緻整個叢集分為2個甚至多個叢集,如果沒有過半數存活機制,那麼整個zookeeper會變成多個叢集,那麼zookeeper提供的資料無法再保證資料一緻性;

zookeeper叢集角色

1.Leader上司者

2.Learner學習者:

Follower跟随者:

ObServer觀察者:功能和追随者一緻,響應用戶端的指令,不能參加選舉和投票環節

3.Client用戶端

ZAB協定-原子消息廣播協定

ZooKeeper作為高可用的一緻性協調架構

自然的ZooKeeper也有着一緻性算法的實作,ZooKeeper使用的是ZAB協定作為資料一緻性的算法,ZAB(ZooKeeper Atomic Broadcast )

ZAB基礎

Leader選舉;

在ZooKeeper中所有的事務請求都由一個主伺服器也就是Leader來處理,其他伺服器為Follower,Leader将用戶端的事務請求轉換為事務Proposal,并且将Proposal分發給叢集中其他所有的Follower,然後Leader等待Follwer回報,當有過半數(>=N/2+1)的Follower回報資訊後,Leader将再次向叢集内Follower廣播Commit資訊,Commit為将之前的Proposal送出;

ZAB協定的狀态

Looking:選舉狀态

Leading:上司狀态

Following:跟随狀态

zookeeper配置詳解

核心配置檔案zoo.cfg

tickTime:心跳間隔時間,預設為2000ms

zookeeper中使用的基本時間機關, 毫秒值。

dataDir:資料目錄。

修改為zookeeper安裝目錄下的data目錄,data目錄自己建立,當然也可以指定為别的目錄。

initLimit:連接配接逾時時間

Follower初始化連接配接時和Leader連接配接的逾時時間。預設為10(10 * 2000ms(tickTime))

zookeeper叢集中的包含多台server,其中一台為leader,其餘的server為follower。

initLimit參數配置初始化連接配接時,follower和leader之間的最長心跳時間。

syncLimit:消息通信逾時時間

該參數配置leader和follower之間發送消息,請求和應答的最大時間長度。

此時該參數設定為2,說明時間限制為2倍tickTime,即4000ms

叢集配置詳解

server.serverid=serverhost:leader_listent_port:quorum_port

serverid:myid

是目前zookeeper伺服器的id(myid檔案中寫的編号)。

leader_listen_port:上司監聽端口

通常叫做原子廣播端口,是該伺服器一旦成為leader之後需要監聽的端口,用于接收來自follower的請求。

quorum_port:選舉端口

通常叫做選舉端口,是叢集中的每一個伺服器在最開始選舉leader時監聽的端口,用于伺服器互相之間通信選舉leader。

繼續閱讀