ZooKeeper筆記——技術點彙總

目錄

· ZooKeeper安裝node

· 分佈式一致性理論mysql

    · 一致性級別算法

    · 集中式系統sql

    · 分佈式系統數據庫

    · ACID特性apache

    · CAP理論centos

    · BASE理論服務器

    · 一致性協議網絡

· ZooKeeper概況session

· ZooKeeper API

    · 命令

    · Java API

    · Curator

· ZooKeeper應用場景

    · 數據發佈/訂閱

    · 配置管理

    · 命名服務

    · 集羣管理

    · Master選舉

    · 分佈式鎖

    · 分佈式隊列

    · Hadoop

    · HBase

    · Kafka


 

ZooKeeper安裝

ID

Host Name

1

centos1

2

centos2

1. 配置機器名。

vi /etc/hosts
192.168.0.220 centos1
192.168.0.221 centos2

2. 安裝JDK並配置環境變量(JAVA_HOME、CLASSPATH、PATH)。

3. 配置文件。

tar zxvf zookeeper-3.4.8.tar.gz -C /opt/app/
cd /opt/app/zookeeper-3.4.8/
mkdir data/ logs/
vi conf/zoo.cfg # 集羣每臺機器的zoo.cfg配置必須一致。
tickTime=2000
dataDir=/opt/app/zookeeper-3.4.8/data/
dataLogDir=/opt/app/zookeeper-3.4.8/data_logs/
clientPort=2181
initLimit=5
syncLimit=2
server.1=centos1:2888:3888 # 每臺機器都要感知集羣的機器組成,配置格式爲「server.id=host:port:port」。id範圍1~255。
server.2=centos2:2888:3888
# 在dataDir目錄建立myid文件。根據zoo.cfg配置,id應與機器對應。如centos1的id爲1,centos2的id爲2.
echo 1 > data/myid
echo 2 > data/myid

4. 啓動、關閉。

bin/zkServer.sh start
bin/zkServer.sh stop
bin/zkServer.sh status

5. 驗證。

bin/zkCli.sh -server centos1:2181
[zk: centos1:2181(CONNECTED) 0] ls /
[zookeeper]
[zk: centos1:2181(CONNECTED) 1] create /helloworld 123
Created /helloworld
[zk: centos1:2181(CONNECTED) 2] ls /
[helloworld, zookeeper]
[zk: centos1:2181(CONNECTED) 3] quit
Quitting...
bin/zkCli.sh -server centos2:2181
[zk: centos2:2181(CONNECTED) 0] ls /
[helloworld, zookeeper]
[zk: centos2:2181(CONNECTED) 1] get /helloworld
123
cZxid = 0x100000008
ctime = Sat Jun 18 16:10:12 CST 2016
mZxid = 0x100000008
mtime = Sat Jun 18 16:10:12 CST 2016
pZxid = 0x100000008
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 3
numChildren = 0
[zk: centos2:2181(CONNECTED) 2] quit
Quitting...

分佈式一致性理論

一致性級別

1. 強一致性:寫入與讀出數據一致。用戶體驗好,但對系統影響較大。

2. 弱一致性:寫入後不承諾當即能夠讀到,也不承諾多久以後達到一致,但會盡量保證到某個時間級別(好比秒級)後數據一致。細分:

    a) 會話一致性:只保證同一個客戶端會話中寫入與讀出數據一致,其餘會話沒法保證。

    b) 用戶一致性:只保證同一個用戶中寫入與讀出數據一致,其餘用戶沒法保證。

    c) 最終一致性:保證在必定時間內,達到數據一致性。業界比較推崇的大型分佈式系統數據一致性。

集中式系統

1. 特色:部署結構簡單。

2. 問題:有明顯的單點問題。

分佈式系統

1. 定義:分佈式系統是一個硬件或軟件組件分佈在不一樣的網絡計算機上,彼此之間僅僅經過消息傳遞進行通訊和協調的系統(摘自《分佈式系統概念與設計》)。

2. 特色。

    a) 分佈性:多臺計算機在空間上隨意分佈,而且分佈狀況隨時變更。

    b) 對等性:無主/從之分,既無控制整個系統的主機,也無被控制的從機。

    c) 併發性:例如多個節點併發操做一些共享資源,諸如數據庫或分佈式存儲。

    d) 缺少全局時鐘:空間上隨意分佈的多個進程,因爲缺少全局時鐘序列控制,很難定義誰先執行誰後執行

    e) 故障老是會發生。

3. 副本(Replica):分佈式系統對數據和服務提供的一種冗餘方式。目的是爲了提升數據的可靠性和服務的可用性。

4. 併發:若是邏輯控制流在時間上重疊,那麼它們就是併發的。

5. 問題。

    a) 通訊異常:網絡光纖、路由器或DNS等硬件設備或系統致使網絡不可用;網絡正常時通訊延時大於單機,一般單機內存訪問延時時納秒數量級(約10ns),網絡通訊延時在0.1~1ms左右(105~106倍於內存訪問)。

    b) 網絡分區:俗稱「腦裂」。原書解釋有問題,摘一段來自網絡的解釋:「Imagine that you have 10-node cluster and for some reason the network is divided into two in a way that 4 servers cannot see the other 6. As a result you ended up having two separate clusters; 4-node cluster and 6-node cluster. Members in each sub-cluster are thinking that the other nodes are dead even though they are not. This situation is called Network Partitioning (aka Split-Brain Syndrome).」。每一個節點的加入與退出可看做特殊的網絡分區。

    c) 三態:三態即成功、失敗和超時。因爲網絡不可靠,可能會出現超時。超時的兩種狀況:1)請求(消息)並未被成功地發送到接收方;2)請求(消息)成功地被接收方接收後進行了處理,但反饋響應給發送方時消息丟失。

    d) 節點故障:每一個節點每時每刻均可能出現故障。

ACID特性

1. 事務(Transaction):由一系列對系統中數據進行訪問與更新的操做所組成的一個程序執行邏輯單元(Unit),狹義上的事務特指數據庫事務。

2. 原子性(Atomicity):

    a) 事務中各項操做只容許所有成功執行或所有執行失敗。

    b) 任何一項操做失敗都將致使事務失敗,同時其餘已執行的操做將被撤銷。

3. 一致性(Consistency):若是數據庫發生故障,事務還沒有完成被迫中斷,事務中已執行的寫操做不該該寫入數據庫。

4. 隔離性(Isolation):

    a) 一個事務的執行不能被其餘事務干擾。

    b) Read Uncommitted、Read Committed、Repeatable Read、Serializable4個隔離級別,隔離性依次增高,併發性依次下降。

    c) 4個隔離級別解決的隔離問題。

級別            \           問題

髒讀

重複讀

幻讀

Read Uncommitted

Read Committed

Repeatable Read

Serializable

5. 持久性(Durability):一旦事務執行成功,對數據庫的修改必須永久保存。

CAP理論

1. 內容:一個分佈式系統不可能同時知足一致性(Consistency)、可用性(Availability)和分區容錯性(Partion tolerance)這三個基本需求,最多隻能同時知足其中兩項。

2. 一致性:多個副本之間保持一致的特性。

3. 可用性:系統提供的服務必須一直處於可用狀態,對於用戶的每一個操做請求老是能在有限時間內返回結果。「有限時間內」是系統設計之初設定好的運行指標,一般不一樣系統會有很大不一樣。

4. 分區容錯性:遇到任何網絡分區故障時,仍然能提供一致性和可用性的服務。

5. 權衡(摘自網絡):

    a) 對於多數大型互聯網應用的場景,主機衆多、部署分散,並且如今的集羣規模愈來愈大,因此節點故障、網絡故障是常態,並且要保證服務可用性達到N個9,即保證P和A,捨棄C(退而求其次保證最終一致性)。雖然某些地方會影響客戶體驗,但沒達到形成用戶流程的嚴重程度。

    b) 對於涉及到錢財這樣不能有一絲讓步的場景,C必須保證。網絡發生故障寧肯中止服務,這是保證CA,捨棄P。貌似這幾年國內銀行業發生了不下10起事故,但影響面不大,報到也很少,廣大羣衆知道的少。還有一種是保證CP,捨棄A。例如網絡故障事只讀不寫。

BASE理論

1. BASE是Basically Available(基本可用)、Soft state(軟狀態)和Eventually consistency(最終一致性)的簡寫。

2. BASE核心思想:即便沒法作到強一致性(Strong consistency),但可根據應用的自身業務特色,採用適當方式達到最終一致性(Eventually consistency)。

3. BASE是對CAP中一致性和可用性權衡的結果,來源於對大規模互聯網系統分佈式時間總結。

4. 基本可用:不可預知故障時,容許損失部分可用性。好比響應時間的損失、功能的損失。

5. 軟狀態:容許系統中的數據存在中間狀態,並認爲該狀態不會影響系統總體可用性,即容許不一樣節點的數據副本同步存在延時。

6. 最終一致性:全部數據副本,在通過一段時間同步後,最終能達到一個一致性狀態。

一致性協議

1. 最著名的一致性協議和算法:二階段提交協議(2PC/Two-Phase Commit)、三階段提交協議(3PC/Three-Phase Commit)和Paxos算法。

2. 絕大多數關係數據庫採用2PC協議完成分佈式事務。

ZooKeeper概況

1. ZooKeeper是一個分佈式數據一致性解決方案,是Google Chubby(論文)的開源實現。

2. ZooKeeper採用ZAB(ZooKeeper Atomic Broadcast)一致性協議。

3. ZooKeeper保證以下分佈式一致性特性。

    a) 順序一致性:同一客戶端發起的請求,最終會嚴格按發起順序應用到ZooKeeper中。

    b) 原子性:全部請求的處理結果在整個集羣全部機器上的應用狀況是一致的。

    c) 單一視圖(Single System Image):客戶端鏈接ZooKeeper任意一個服務器,看到的數據模型都是一致的。

    d) 可靠性:應用了客戶端請求以後,引發的數據變動被永久保存。

    e) 實時性:僅保證在必定時間後,最終一致性。

4. ZooKeeper的設計目標。

    a) 簡單的數據模型:提供樹形結構的命令空間,樹上的數據節點稱爲ZNode。

    b) 能夠構建集羣。

    c) 順序訪問:客戶端每一個更新請求,都會分配一個全局惟一的遞增編號,這個編號反應了全部操做的前後順序。

    d) 高性能:全局數據存儲在內存,尤爲適用於讀爲主的應用場景。

5. 集羣角色。

    a) 沒有Master/Slave,而引入三種角色。

    b) Leader:爲客戶端提供讀、寫服務。經過Leader選舉過程產生。

    c) Follower:爲客戶端提供讀、寫服務,若是是寫請求則轉發給Leader。參與Leader選舉過程。

    d) Observer:與Follower相同,惟一區別是不參加Leader選舉過程。

6. 數據節點ZNode。

    a) 分爲持久節點和臨時節點(Ephemeral Node),臨時節點在客戶端會話失效後被移除,而持久節點在執行移除操做後才被移除。

    b) 順序節點(Sequence Node),被建立時ZooKeeper自動在其節點名後追加一個整型數字(惟一命名)。

7. 版本:每一個ZNode都有一個Stat數據結構,包含version(當前ZNode的版本)、cversion(當前ZNode子節點的版本)和aversion(當前ZNode的ACL版本)。

8. Watcher。

    a) 容許客戶端在指定節點上註冊一些Watcher,在這些特定事件觸發時,ZooKeeper將事件通知到註冊的客戶端上。

    b) 即Publish/Subscribe(發佈/訂閱)。

9. ACL(Access Control Lists)。

    a) ZooKeeper採用ACL策略進行權限控制,相似UNIX文件系統權限控制。

    b) CREATE:建立子節點權限。

    c) READ:獲取節點數據和子節點列表的權限。

    d) WRITE:更新節點數據的權限。

    e) DELETE:刪除子節點的權限。

    f) ADMIN設置節點ACL的權限。

10. 集羣組成。

    a) 「過半存貨便可用」指若是ZooKeeper集羣要對外可用,必需要有過半的機器正常工做而且彼此之間正常通訊。即若是搭建一個容許F臺機器宕機的集羣,則要部署2xF+1臺服務器。

    b) 6臺機器的集羣可用性上並不比5臺機器的集羣高,因此產生了「官方推薦服務器數爲奇數」的說法。

    c) 需澄清:任意服務器數的ZooKeeper集羣都能部署且正常運行。

ZooKeeper API

命令

1. 建立節點:create [-s] [-e] path data [acl],-s順序節點,-e臨時節點。

2. 列出子節點:ls path [watch]。

3. 獲取節點:get path [watch]。

4. 更新節點:set path data [version]。

5. 刪除節點:delete path [version]。

6. 刪除節點及其子節點:rmr path。

7. 舉例。

[zk: localhost:2181(CONNECTED) 0] create /test A
Created /test
[zk: localhost:2181(CONNECTED) 1] create /test/mynode B
Created /test/mynode
[zk: localhost:2181(CONNECTED) 2] create -s /test/snode 0
Created /test/snode0000000001
[zk: localhost:2181(CONNECTED) 3] create -s /test/snode 0
Created /test/snode0000000002
[zk: localhost:2181(CONNECTED) 4] create -s /test/snode 0
Created /test/snode0000000003
[zk: localhost:2181(CONNECTED) 5] ls /test
[snode0000000002, mynode, snode0000000001, snode0000000003]
[zk: localhost:2181(CONNECTED) 6] get /test/mynode
B
cZxid = 0x200000029
ctime = Sun Jun 19 00:04:05 CST 2016
mZxid = 0x200000029
mtime = Sun Jun 19 00:04:05 CST 2016
pZxid = 0x200000029
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0
[zk: localhost:2181(CONNECTED) 7] set /test/mynode C
cZxid = 0x200000029
ctime = Sun Jun 19 00:04:05 CST 2016
mZxid = 0x20000002d
mtime = Sun Jun 19 00:05:34 CST 2016
pZxid = 0x200000029
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 1
numChildren = 0
[zk: localhost:2181(CONNECTED) 8] delete /test/mynode
[zk: localhost:2181(CONNECTED) 9] ls /test
[snode0000000002, snode0000000001, snode0000000003]

Java API

待補充。

Curator

1. Curator是Netflix開源的一套ZooKeeper客戶端框架,解決了不少ZooKeeper客戶端很是底層的細節開發工做(如鏈接重連、反覆註冊Watcher、NodeExistsException異常等),是全世界最普遍的ZooKeeper客戶端之一。

2. Curator的API最大亮點在於遵循了Fluent設計風格。

3. Maven依賴配置。

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
    <version>2.10.0</version>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>2.10.0</version>
</dependency>

ZooKeeper應用場景

數據發佈/訂閱

ZooKeeper採用推拉結合的「發佈/訂閱」方式:客戶端向服務器註冊關注的節點,節點的數據變化時,服務器向客戶端發送Watcher事件通知,客戶端收到通知後主動到服務器獲取最新數據。

配置管理

1. 全局配置信息一般具有3個特性:

    a) 數據量比較小;

    b) 運行時數據內容動態變化;

    c) 集羣中個機器共享,配置一致。

2. 例如機器列表信息、運行時的開關配置、數據庫配置信息等。

3. 實現原理:「發佈/訂閱」(Watcher)。

4. 以數據庫切換舉例。

    a) 配置存儲:管理員建立ZNode存儲配置。

 1 import org.apache.curator.RetryPolicy;
 2 import org.apache.curator.framework.CuratorFramework;
 3 import org.apache.curator.framework.CuratorFrameworkFactory;
 4 import org.apache.curator.retry.ExponentialBackoffRetry;
 5 import org.apache.curator.utils.CloseableUtils;
 6 
 7 public class CreateConfig {
 8 
 9     public static void main(String[] args) throws Exception {
10         String path = "/configserver/app1/database_config";
11         String config = "jdbc.driver=com.mysql.jdbc.Driver\n"
12                 + "jdbc.url=jdbc:mysql://centos1:3306/test?useUnicode=true&characterEncoding=utf8\n"
13                 + "jdbc.username=test\n"
14                 + "jdbc.password=test\n";
15         
16         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
17         CuratorFramework client = null;
18         try {
19             client = CuratorFrameworkFactory.builder()
20                     .connectString("centos1:2181,centos2:2181")
21                     .sessionTimeoutMs(5000)
22                     .retryPolicy(retryPolicy)
23                     .build();    // Fluent
24             client.start();
25             client.create()
26                     .creatingParentContainersIfNeeded()
27                     .forPath(path, config.getBytes());
28         } finally {
29             CloseableUtils.closeQuietly(client);
30         }
31     }
32 
33 }

    b) 配置獲取:集羣機各機器啓動時獲取配置,並註冊該ZNode數據變動的Watcher。

 1 import org.apache.curator.RetryPolicy;
 2 import org.apache.curator.framework.CuratorFramework;
 3 import org.apache.curator.framework.CuratorFrameworkFactory;
 4 import org.apache.curator.framework.recipes.cache.NodeCache;
 5 import org.apache.curator.framework.recipes.cache.NodeCacheListener;
 6 import org.apache.curator.retry.ExponentialBackoffRetry;
 7 import org.apache.curator.utils.CloseableUtils;
 8 
 9 public class RunServer {
10 
11     public static void main(String[] args) throws Exception {
12         String path = "/configserver/app1/database_config";
13         
14         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
15         CuratorFramework client = null;
16         NodeCache nodeCache = null;
17         try {
18             client = CuratorFrameworkFactory.builder()
19                     .connectString("centos1:2181,centos2:2181")
20                     .sessionTimeoutMs(5000)
21                     .retryPolicy(retryPolicy)
22                     .build();
23             client.start();
24             byte[] data = client.getData()
25                     .forPath(path);
26             System.out.println("Get config when server starting.");
27             System.out.println(new String(data));
28             
29             // Register watcher
30             nodeCache = new NodeCache(client, path, false);
31             nodeCache.start(true);
32             final NodeCache nc = nodeCache;
33             nodeCache.getListenable().addListener(new NodeCacheListener() {
34 
35                 @Override
36                 public void nodeChanged() throws Exception {
37                     System.out.println("Get config when changed.");
38                     System.out.println(new String(nc.getCurrentData().getData()));
39                 }
40                 
41             });
42             
43             Thread.sleep(Long.MAX_VALUE);
44             
45         } finally {
46             CloseableUtils.closeQuietly(nodeCache);
47             CloseableUtils.closeQuietly(client);
48         }
49     }
50 
51 }

    c) 配置變動:管理員修改ZNode的數據(配置)。

 1 import org.apache.curator.RetryPolicy;
 2 import org.apache.curator.framework.CuratorFramework;
 3 import org.apache.curator.framework.CuratorFrameworkFactory;
 4 import org.apache.curator.retry.ExponentialBackoffRetry;
 5 import org.apache.curator.utils.CloseableUtils;
 6 
 7 public class UpdateConfig {
 8 
 9     public static void main(String[] args) throws Exception {
10         String path = "/configserver/app1/database_config";
11         String config = "jdbc.driver=com.mysql.jdbc.Driver\n"
12                 + "jdbc.url=jdbc:mysql://centos2:3306/test?useUnicode=true&characterEncoding=utf8\n"
13                 + "jdbc.username=foo\n"
14                 + "jdbc.password=foo\n";
15         
16         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
17         CuratorFramework client = null;
18         try {
19             client = CuratorFrameworkFactory.builder()
20                     .connectString("centos1:2181,centos2:2181")
21                     .sessionTimeoutMs(5000)
22                     .retryPolicy(retryPolicy)
23                     .build();    // Fluent
24             client.start();
25             client.setData()
26                     .forPath(path, config.getBytes());
27         } finally {
28             CloseableUtils.closeQuietly(client);
29         }
30     }
31 
32 }

命名服務

1. 分佈式系統中,被命名的實體一般是集羣中的機器、提供的服務地址或遠程對象等。

2. 廣義上命名服務的資源定位不必定是實體資源,好比分佈式全局惟一ID。

3. 以數據庫主鍵(分佈式全局惟一ID的一種)舉例。

    a) 可以使用UUID,但UUID的缺點:長度過長;字面上看不出含義。

    b) 實現原理:順序節點。

    c) 代碼。

 1 import org.apache.curator.RetryPolicy;
 2 import org.apache.curator.framework.CuratorFramework;
 3 import org.apache.curator.framework.CuratorFrameworkFactory;
 4 import org.apache.curator.retry.ExponentialBackoffRetry;
 5 import org.apache.curator.utils.CloseableUtils;
 6 import org.apache.zookeeper.CreateMode;
 7 
 8 public class GenerateId {
 9     
10     public static void main(String[] args) throws Exception {
11         for (int index = 0; index < 10; index++) {
12             // type1-job-0000000000
13             System.out.println(generate("type1"));
14         }
15         for (int index = 0; index < 5; index++) {
16             // type2-job-0000000000
17             System.out.println(generate("type2"));
18         }
19     }
20 
21     private static String generate(String type) throws Exception {
22         String path = "/generateid/" + type + "/job-";
23         
24         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
25         CuratorFramework client = null;
26         try {
27             client = CuratorFrameworkFactory.builder()
28                     .connectString("centos1:2181,centos2:2181")
29                     .sessionTimeoutMs(5000)
30                     .retryPolicy(retryPolicy)
31                     .build();
32             client.start();
33             path = client.create()
34                     .creatingParentContainersIfNeeded()
35                     .withMode(CreateMode.PERSISTENT_SEQUENTIAL)
36                     .forPath(path);
37             return type + '-' + path.substring(path.lastIndexOf('/') + 1);
38         } finally {
39             CloseableUtils.closeQuietly(client);
40         }
41     }
42 
43 }

集羣管理

1. 集羣機器監控。

    a) 實現過程:監控系統在/cluster_server節點上註冊Watcher監聽,添加機器時,由機器在/cluster_server節點下建立一個臨時節點/cluster_server/[host_name],並定時寫入運行狀態信息。

    b) 既能實時獲取機器的上/下線狀況,又能獲取機器的運行信息。

    c) 適合大規模分佈式系統監控。

2. 分佈式日誌收集。

    a) 日誌系統包含日誌源機器和收集器機器,因爲硬件問題、擴容、機房遷移或網絡問題等緣由,他們都在變動。

    b) 實現過程。

        i. 註冊收集器機器:收集器機器啓動時建立一個持久節點/log_collector/[collector_hostname],再建立一個臨時節點/log_collector/[collector_hostname]/status,寫入運行狀態信息。

        ii. 任務分發:日誌系統將所有日誌源機器分爲若干組,分別在相應的收集器機器建立的節點/log_collector/[collector_hostname]下建立持久節點/log_collector/[collector_hostname]/[origin_hostname],而收集器機器獲取/log_collector/[collector_hostname]的子節點來獲得日誌源機器列表,同時Watcher監聽/log_collector/[collector_hostname]的子節點變化。

        iii. 動態分配:日誌系統始終Watcher監聽/log_collector下的所有子節點,當有新收集器機器加入時,則將負載高的任務從新分配給新收集器機器;當有收集器機器退出時,則將其下的日誌源機器從新分配給其餘收集器機器。

Master選舉

1. Master用來協調集羣中其餘系統單元,具備對分佈式系統狀態變動的決定權。例如讀寫分離場景中,客戶端寫請求是由Master處理的。

2. 實現原理:利用ZooKeeper強一致性,保證在分佈式高併發狀況下節點建立必定全局惟一,即保證客戶端沒法重複建立一個已存在的ZNode。

3. 實現過程:選舉時,集羣中各機器同時建立臨時節點/master_election,並寫入機器信息,建立成功的機器成爲Master,建立失敗的機器Watcher監控節點/master_election開始等待,一旦該節點被移除則從新選舉。

4. Curator封裝了Master選舉功能。

 1 import org.apache.curator.RetryPolicy;
 2 import org.apache.curator.framework.CuratorFramework;
 3 import org.apache.curator.framework.CuratorFrameworkFactory;
 4 import org.apache.curator.framework.recipes.leader.LeaderSelector;
 5 import org.apache.curator.framework.recipes.leader.LeaderSelectorListenerAdapter;
 6 import org.apache.curator.retry.ExponentialBackoffRetry;
 7 import org.apache.curator.utils.CloseableUtils;
 8 
 9 public class MasterElection {
10     
11     public static void main(String[] args) throws Exception {
12         String path = "/master_election";
13         
14         RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
15         CuratorFramework client = null;
16         LeaderSelector selector = null;
17         try {
18             client = CuratorFrameworkFactory.builder()
19                     .connectString("centos1:2181,centos2:2181")
20                     .sessionTimeoutMs(5000)
21                     .retryPolicy(retryPolicy)
22                     .build();
23             client.start();
24             selector = new LeaderSelector(client, path, new LeaderSelectorListenerAdapter() {
25 
26                 @Override
27                 public void takeLeadership(CuratorFramework client) throws Exception {
28                     long threadId = Thread.currentThread().getId();
29                     System.out.println("Thread" + threadId + " is master.");
30                     Thread.sleep(3000);
31                     System.out.println("Thread" + threadId + " has been down.");
32                     System.exit(0);
33                 }
34                 
35             });
36             selector.autoRequeue();
37             selector.start();
38             Thread.sleep(Long.MAX_VALUE);
39             
40         } catch (InterruptedException e) {
41             e.printStackTrace();
42             
43         } finally {
44             CloseableUtils.closeQuietly(selector);
45             CloseableUtils.closeQuietly(client);
46         }
47     }
48         
49 }

分佈式鎖

1. 分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式。

2. 分佈式鎖分爲排它鎖(Exclusive Lock,簡稱X鎖,又稱寫鎖、獨佔鎖)和共享鎖(Shared Lock,簡稱S鎖,又稱讀鎖)。

    a) 排它鎖相似JDK的synchronized和ReentrantLock。

    b) 共享鎖相似JDK的ReadWriteLock中的讀鎖。

3. 排它鎖實現過程:與Master選舉相似。全部客戶端同時建立臨時節點/execlusive_lock,建立成功的客戶端獲取了鎖,建立失敗的客戶端Watcher監聽節點/execlusive_lock開始等待,一旦該節點被移除(即排它鎖已釋放)則重複該過程。

4. 共享鎖實現過程:

    a) 建立持久節點/shared_lock。

    b) 全部客戶端根據須要的鎖類型(R/W)建立臨時順序節點/shared_lock/[hostname-R/W-],如/shared_lock/[host1-R-0000000000]、/shared_lock/host1-W-0000000003。

    c) 獲取/shared_lock下的全部子節點。

    d) 各客戶端肯定本身的節點順序。

        i. 當前客戶端須要R鎖時,若是無比本身序號小的子節點或全部比本身序號小的子節點都是R鎖,則獲取R鎖成功;若是比本身序號小的子節點有W鎖,則Watcher監聽該W鎖節點並等待。

        ii. 當前客戶端須要W鎖時,若是本身序號是最小的子節點,則獲取W鎖成功,不然Watcher監聽比本身序號小的子節點中序號最大的節點並等待。

    e) 各客戶端收到Watcher通知後,則獲取鎖成功。

5. Curator封裝了分佈式鎖功能。

分佈式隊列

1. 業界分佈式隊列產品大可能是消息中間件(或稱消息隊列),ZooKeeper也可實現分佈式隊列功能。

2. 分佈式隊列分爲FIFO和Barrier兩種:

    a) FIFO即常見的隊列;

    b) Barrier相似JDK的CyclicBarrier,等待的數量達到必定值時才執行。

3. FIFO實現過程(相似共享鎖):

    a) 建立持久節點/queue_fifo。

    b) 全部客戶端建立臨時順序節點/queue_fifo/[hostname-],如/queue_fifo/host1-0000000000。

    c) 獲取/ queue_fifo下的全部子節點。

    d) 各客戶端肯定本身的節點順序:若是本身序號是最小的子節點,則執行;不然Watcher監聽比本身序號小的節點中序號最大的節點並等待。

    e) 收到Watcher通知後,則執行。

4. Barrier實現過程:

    a) 建立持久節點/queue_barrier。

    b) 全部客戶端建立臨時節點/queue_barrier/[hostname],如/queue_fifo/host1。

    c) 獲取/ queue_fifo下的全部子節點。

    d) 若是子節點數大於或等於某值,則執行;不然Watcher監聽節點/queue_barrier並等待。

    e) 收到Watcher通知後,重複步驟c。

Hadoop

1. HDFS的NameNode和YARN的ResourceManager都是基於ZooKeeper實現HA。

2. YARN的HA實現過程(相似Master選舉):

    a) 運行期間,多個ResourceManager並存,但只有一個爲Active狀態,其餘爲Standby狀態。

    b) 當Active狀態的節點沒法工做時,Standby狀態的節點競爭選舉產生新的Active節點。

    c) 假設ResourceManager1「假死」,可能會致使ResourceManager2變爲Active狀態,當ResourceManager1恢復後,出現「腦裂」。經過ACL權限控制能夠解決,即ResourceManager1恢復後發現ZNode不是本身建立,則自動切換爲Standby狀態。

HBase

與大部分分佈式NoSQL數據庫不一樣的是,HBase的數據寫入是強一致性的,甚至索引列也是強一致性。

Kafka

Kafka主要用於實現低延時的發送和收集大量的事件和日誌數據。大型互聯網Web應用中,指網站的PV數和用戶訪問記錄等。

 

做者:netoxi
出處:http://www.cnblogs.com/netoxi本文版權歸做者和博客園共有,歡迎轉載,未經贊成須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。歡迎指正與交流。

相關文章
相關標籤/搜索