日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

zookeeper笔记+源码刨析

發布時間:2024/4/19 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 zookeeper笔记+源码刨析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

會不斷更新!沖沖沖!跳轉連接

https://blog.csdn.net/qq_35349982/category_10317485.html

zookeeper

1.介紹

Zookeeper 分布式數據一致性的解決方案,分布式應用程序可以基于他實現諸如數據訂閱/發布,負載均衡,命名服務,集群管理,分布式鎖,分布式隊列

2.安裝篇

2.1.安裝單機版

1.下載

cd /usr/local/src #進入指定目錄 #下載zookeeper wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz

2.解壓

tar -zxvf zookeeper-3.4.13.tar.gz cd zookeeper-3.4.13

3.修改配置文件

#進配置文件 cd zookeeper-3.4.13/conf #將zoo_sample.cfg這個文件復制為zoo.cfg (必須是這個文件名) cp zoo_sample.cfg zoo.cfg #新增data跟log目錄 cd /usr/local/src/zookeeper/zookeeper-3.4.9 mkdir data mkdir log #進入zoo.cfg文件進行編輯 vi zoo.cfg #修改dataDir 新增dataLogDir dataDir=/usr/local/src/zookeeper/data dataLogDir=/usr/local/src/zookeeper/log

4.配置環境變量

export ZOOKEEPER_INSTALL=/usr/local/src/zookeeper export PATH=$PATH:$ZOOKEEPER_INSTALL/bin

5.啟動

cd /usr/local/src/zookeeper/bin ./zkServer.sh start

2.2 安裝集群版

1.改名稱

mv zookeeper-3.4.14 zookeeper01

2.復制多分

cp -r zookeeper01/ zookeeper02 cp -r zookeeper01/ zookeeper03

3.修改配置文件

#創建兩個文件夾 mkdir datamkdir logs #修改配置文件名稱 cd conf mv zoo_sample.cfg zoo.cfg

4.編寫配置文件 (修改三個配置文件)

clientPort=2181 dataDir=/usr/local/src/zookeeper2/data dataLogDir=/usr/local/src/zookeeper2/logs

5.修改集群配置文件

先查看IP ( 不可以使用服務器IP)

ifconfig

在每個zookeeper文件的data目錄下創建一個myid文件,內容分別為1.2.3,這個文件就是記錄每個服務器的ID

touch myid

在每個zookeeper中的zoo.cfg文件中,配置集群服務器Ip

server.1=172.17.153.160:2881:3881 server.2=172.17.153.160:2882:3882 server.3=172.17.153.160:2883:3883 #server.服務器ID=服務器IP地址:服務器之間通信端?:服務器之間投票選舉端? jps #里面有6456 QuorumPeerMain 代表啟動成功

6.啟動

./zkServer.sh start #啟動 ./zkServer.sh status #查看狀態 ./zkServer.sh stop #停止

安裝的問題總結

1.停止8080端口

netstat -nltp | grep 2181kill -9 3027

2.注意開放的端口,以及防火墻的問題

3.查詢日志

./zkServer.sh start-foreground #查詢日志

4.在log中有一個 out文件,看下里面的報錯信息

5.端口被占用后,把dara和logs中的舊文件全部刪掉

https://blog.csdn.net/Hello_World_QWP/article/details/90765608?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

https://blog.csdn.net/qq_36651243/article/details/89396618

https://www.jianshu.com/p/0335f1f41420

https://www.cnblogs.com/zimo-jing/p/9037853.html

https://blog.csdn.net/weixin_45793065/article/details/106709479

3.基本命令

3.1 命令行

1.1.創建節點

#啟動 ./zkCli.sh#查詢當前節點 ls / #創建順序節點 create -s /zk-test 123 #創建臨時節點(客戶端重啟,節點關閉) create -e /zk-temp 123 #創建永久節點 create /zk-permanent 123

1.2.讀取節點

#獲取節點 并查看信息 get /zk-permanent

1.3.更新 刪除節點

get /zk-permanent #更新 set /zk-permanent 456 #刪除 (若該節點存在子節點則無法刪除,需刪除子節點) delete /zk-permanent

3.2 ZooKeeper類

<dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId><version>3.4.14</version></dependency><dependency><groupId>com.101tec</groupId><artifactId>zkclient</artifactId><version>0.2</version></dependency>

2.1連接并創建

public class CreateNote implements Watcher {private static CountDownLatch countDownLatch = new CountDownLatch(1);private static ZooKeeper zooKeeper;/*建立會話*/public static void main(String[] args) throws IOException, InterruptedException, KeeperException {/*客戶端可以通過創建一個zk實例來連接zk服務器new Zookeeper(connectString,sesssionTimeOut,Wather)connectString: 連接地址:IP:端口sesssionTimeOut:會話超時時間:單位毫秒Wather:監聽器(當特定事件觸發監聽時,zk會通過watcher通知到客戶端)*/zooKeeper = new ZooKeeper("47.95.1.96:2181", 5000, new CreateNote());System.out.println(zooKeeper.getState());// 計數工具類:CountDownLatch:不讓main方法結束,讓線程處于等待阻塞//countDownLatch.await();\Thread.sleep(Integer.MAX_VALUE);}/*回調方法:處理來自服務器端的watcher通知*/public void process(WatchedEvent watchedEvent) {// SyncConnectedif(watchedEvent.getState() == Event.KeeperState.SyncConnected){//解除主程序在CountDownLatch上的等待阻塞System.out.println("process方法執行了...");// 創建節點try {createNoteSync();} catch (KeeperException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}/*創建節點的方法*/private static void createNoteSync() throws KeeperException, InterruptedException {/*** path :節點創建的路徑* data[] :節點創建要保存的數據,是個byte類型的* acl :節點創建的權限信息(4種類型)* ANYONE_ID_UNSAFE : 表示任何人* AUTH_IDS :此ID僅可用于設置ACL。它將被客戶機驗證的ID替換。* OPEN_ACL_UNSAFE :這是一個完全開放的ACL(常用)--> world:anyone* CREATOR_ALL_ACL :此ACL授予創建者身份驗證ID的所有權限* createMode :創建節點的類型(4種類型)* PERSISTENT:持久節點* PERSISTENT_SEQUENTIAL:持久順序節點* EPHEMERAL:臨時節點* EPHEMERAL_SEQUENTIAL:臨時順序節點String node = zookeeper.create(path,data,acl,createMode);*/String note_persistent = zooKeeper.create("/my-persistent", "持久節點內容".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);System.out.println("節點創建完成");// // 持久節點 // String note_persistent = zooKeeper.create("/lg-persistent", "持久節點內容".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); // // // 臨時節點 // String note_ephemeral = zooKeeper.create("/lg-ephemeral", "臨時節點內容".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); // // // 持久順序節點 // String note_persistent_sequential = zooKeeper.create("/lg-persistent_sequential", "持久順序節點內容".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT_SEQUENTIAL); // // System.out.println("創建的持久節點" + note_persistent); // System.out.println("創建的臨時節點" + note_ephemeral); // System.out.println("創建的持久順序節點" + note_persistent_sequential);} }

2.2查詢,更新

/*更新數據節點內容的方法*/private void updateNoteSync() throws KeeperException, InterruptedException {/*path:路徑data:要修改的內容 byte[]version:為-1,表示對最新版本的數據進行修改zooKeeper.setData(path, data,version);*///新建Stat stat = zooKeeper.setData("/my-persistent", "我新建了一個節點".getBytes(), -1);//查詢byte[] data = zooKeeper.getData("/my-persistent", false, null);System.out.println("修改前的值:" + new String(data));//修改Stat stat1 = zooKeeper.setData("/my-persistent", "我修改了我新建的節點".getBytes(), -1);//查詢byte[] data2 = zooKeeper.getData("/my-persistent", false, null);System.out.println("修改后的值:" + new String(data2));}

2.3刪除

/*刪除節點的方法*/private void deleteNoteSync() throws KeeperException, InterruptedException {/*zooKeeper.exists(path,watch) :判斷節點是否存在zookeeper.delete(path,version) : 刪除節點*/Stat stat = zooKeeper.exists("/lg-persistent/c1", false);System.out.println(stat == null ? "該節點不存在":"該節點存在");if(stat != null){zooKeeper.delete("/lg-persistent/c1",-1);}Stat stat2 = zooKeeper.exists("/lg-persistent/c1", false);System.out.println(stat2 == null ? "該節點不存在":"該節點存在");}

3.3 curator

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

3.1連接

//不使用fluent編程風格RetryPolicy exponentialBackoffRetry = new ExponentialBackoffRetry(1000, 3);// 使用fluent編程風格CuratorFramework client = CuratorFrameworkFactory.builder().connectString("47.95.1.96:2181").sessionTimeoutMs(50000).connectionTimeoutMs(30000).retryPolicy(exponentialBackoffRetry).namespace("base") // 獨立的命名空間 /base.build();client.start();System.out.println("會話2創建了");// 創建節點String path = "/lg-curator/c1";String s = client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, "init".getBytes());System.out.println("節點遞歸創建成功,該節點路徑" + s);

3.2新增,獲取狀態信息

// 創建節點String path = "/lg-curator/c1";String s = client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, "init".getBytes());System.out.println("節點遞歸創建成功,該節點路徑" + s);// 獲取節點的數據內容及狀態信息// 數據內容byte[] bytes = client.getData().forPath(path);System.out.println("獲取到的節點數據內容:" + new String(bytes));// 狀態信息Stat stat = new Stat();client.getData().storingStatIn(stat).forPath(path);System.out.println("獲取到的節點狀態信息:" + stat );

3.3更新

// 更新節點內容 //1int version = client.setData().withVersion(stat.getVersion()).forPath(path, "修改內容1".getBytes()).getVersion();System.out.println("當前的最新版本是" + version);byte[] bytes2 = client.getData().forPath(path);System.out.println("修改后的節點數據內容:" + new String(bytes2));// BadVersionExceptionclient.setData().withVersion(stat.getVersion()).forPath(path,"修改內容2".getBytes());

3.4刪除

// 刪除節點String path = "/lg-curator";client.delete().deletingChildrenIfNeeded().withVersion(-1).forPath(path);System.out.println("刪除成功,刪除的節點" + path);

3.5 三種監聽

NodeCache: 對一個節點進行監聽,監聽事件包括指定的路徑節點的增、刪、改的操作。

PathChildrenCache: 對指定的路徑節點的一級子目錄進行監聽,不對該節點的操作進行監聽,對其子目錄的節點進行增、刪、改的操作監聽

TreeCache: 可以將指定的路徑節點作為根節點(祖先節點),對其所有的子節點操作進行監聽,呈現樹形目錄的監聽,可以設置監聽深度,最大監聽深度為2147483647(int類型的最大值)

1.PathChildrenCache實現

//PathChildrenCache的使用 //創建監聽事件PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, "/serviceList", false);//監聽路徑下的所有節點pathChildrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);//異步初始化pathChildrenCache.getListenable().addListener(new CilentListener()); //==================== public class CilentListener implements PathChildrenCacheListener {@Overridepublic void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType();if (type.equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)) {System.out.println(pathChildrenCacheEvent.getData().getPath());}if (type.equals(PathChildrenCacheEvent.Type.CHILD_ADDED)) {System.out.println("新增"+pathChildrenCacheEvent.getData().getPath());//獲取新增的節點地址String path = pathChildrenCacheEvent.getData().getPath();String[] split = path.split("/");//獲取服務器的地址String serviceValue = CuratorUtils.findServiceRegister(pathChildrenCacheEvent.getData().getPath());//添加元素Map<String, String> serverAddressMap = ConsumerBoot.serverAddressMap;serverAddressMap.put(split[split.length-1],serviceValue);}if (type.equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)) {String path = pathChildrenCacheEvent.getData().getPath();String[] split = path.split("/");System.out.println("移除"+pathChildrenCacheEvent.getData().getPath());//在Map中移除節點Map<String, String> serverAddressMap = ConsumerBoot.serverAddressMap;serverAddressMap.remove(split[split.length-1]);System.out.println("map中的數量"+serverAddressMap.size());}} }

工具類

package com.lagou.zookeeper;import com.lagou.ZKConstant;import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.framework.recipes.cache.PathChildrenCache; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.data.Stat;import java.nio.ByteBuffer; import java.util.*;public class CuratorUtils {private static String serverList = "serviceList";private static int serverNum = 0;public static CuratorFramework build(){CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()//.connectString("47.95.1.96:2181").connectString("127.0.0.1:2181").namespace(ZKConstant.ZK_NAMESPACE)//.connectionTimeoutMs(15000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).build();curatorFramework.start();return curatorFramework;}/*** 服務注冊* @throws Exception*/public static CuratorFramework serviceRegister(String address,int port) throws Exception {//創建連接CuratorFramework client= CuratorUtils.build();//創建臨時節點,拼接ip+端口String serviceAddress = address+":"+port;Stat s = client.checkExists().forPath("/"+serverList);if (s == null) {//根節點client.create().withMode(CreateMode.PERSISTENT).forPath("/"+serverList);}client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath("/"+serverList+"/"+String.valueOf(serverNum+1),serviceAddress.getBytes());return client;}/*** 服務列表* @return* @throws Exception*/public static List<String> findServiceRegList() throws Exception {//創建連接CuratorFramework client= CuratorUtils.build();List<String> nodeList = client.getChildren().forPath("/" + serverList);return nodeList;}public static void deleteServiceRegister(String path) throws Exception {//創建連接CuratorFramework client= CuratorUtils.build();client.delete().forPath(path);// return nodeList;}//獲取內容public static String findServiceRegister(String path) throws Exception {//創建連接CuratorFramework client= CuratorUtils.build();byte[] bytes = client.getData().forPath(path);return new String(bytes);}/*** 新增時間響應* @param path* @param dateStr* @throws Exception*/public static void addServiceTime(String path,String dateStr) throws Exception {//創建連接CuratorFramework client= CuratorUtils.build();if(client.checkExists().forPath(path)==null){client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path,dateStr.getBytes());}else{client.setData().forPath(path,dateStr.getBytes());}}public static void addReponseTime(String path,String dateStr) throws Exception {//創建連接CuratorFramework client= CuratorUtils.build();if(client.checkExists().forPath(path)==null){client.create().creatingParentContainersIfNeeded().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path,dateStr.getBytes());}else{client.setData().forPath(path,dateStr.getBytes());}}public static byte[] longToBytes(long x) {ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);buffer.putLong(x);return buffer.array();}/*** 求Map<K,V>中Value(值)的最小值* @param map* @return*/public static Object getMinValue(Map<String, Integer> map) {if (map == null) return null;Collection<Integer> c = map.values();Object[] obj = c.toArray();Arrays.sort(obj);return obj[0];}public static void main(String[] args) throws Exception{int numbers[] ={1,2,5};Random random = new Random();int i = random.nextInt(numbers.length);System.out.println(i);System.out.println(numbers[i]);// findServiceRegList();// HashMap<String, Integer> stringStringHashMap = new HashMap<>(); // stringStringHashMap.put("8999",90 ); // stringStringHashMap.put("8998",80 ); // stringStringHashMap.put("8997",70 ); // stringStringHashMap.put("8996",70 ); // // List<Integer> serverServiceList = new ArrayList<Integer>(stringStringHashMap.values()); // List<String> serverKeyList = new ArrayList<String>(stringStringHashMap.keySet());// System.out.println(serverServiceList);// try { // //注冊服務 // CuratorFramework curatorFramework = serviceRegister("127.0.0.1", 8999); // //創建監聽 // PathChildrenCache pathChildrenCache = new PathChildrenCache(curatorFramework, "/serviceList", false);//監聽msg_server_list路徑下的所有節點 // pathChildrenCache.start(PathChildrenCache.StartMode.POST_INITIALIZED_EVENT);//異步初始化 // pathChildrenCache.getListenable().addListener(new PathChildrenCacheListener() { // @Override // public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception { // PathChildrenCacheEvent.Type type = pathChildrenCacheEvent.getType(); // if (type.equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)) { // System.out.println(pathChildrenCacheEvent.getData().getPath()); // } // // if (type.equals(PathChildrenCacheEvent.Type.INITIALIZED)) { // System.out.println("新增"+pathChildrenCacheEvent.getData().getPath()); // } // if (type.equals(PathChildrenCacheEvent.Type.CHILD_REMOVED)) { // System.out.println("移除"+pathChildrenCacheEvent.getData().getPath()); // } // } // });// Thread.sleep(Long.MAX_VALUE); // String testPath="pathChildrenCacheTest"; // //創建連接 // CuratorFramework client= CacheListenerUtils.build(); // //如果testPath存在,刪除路徑 // Stat stat = client.checkExists().forPath("/"+testPath); // if(stat != null) // { // client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath); // } // //創建testPath // client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath,testPath.getBytes()); // // //創建PathChildrenCache // //參數:true代表緩存數據到本地 // PathChildrenCache pathChildrenCache = new PathChildrenCache(client,"/" + testPath,true); // //BUILD_INITIAL_CACHE 代表使用同步的方式進行緩存初始化。 // pathChildrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); // pathChildrenCache.getListenable().addListener((cf, event) -> { // PathChildrenCacheEvent.Type eventType = event.getType(); // switch (eventType) { // case CONNECTION_RECONNECTED: // pathChildrenCache.rebuild(); // break; // case CONNECTION_SUSPENDED: // break; // case CONNECTION_LOST: // System.out.println("Connection lost"); // break; // case CHILD_ADDED: // System.out.println("Child added"); // break; // case CHILD_UPDATED: // System.out.println("Child updated"); // break; // case CHILD_REMOVED: // System.out.println("Child removed"); // break; // default: // } // }); // // //創建子節點1 // client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath+"/1",testPath.getBytes()); // Thread.sleep(1000); // //創建子節點1 // client.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/"+testPath+"/2",testPath.getBytes()); // Thread.sleep(1000); // //刪除子節點1 // client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath+"/1"); // Thread.sleep(1000); // //刪除子節點2 // client.delete().guaranteed().deletingChildrenIfNeeded().forPath("/"+testPath+"/2"); // Thread.sleep(1000); // // // // // pathChildrenCache.close(); // } catch (Exception e) { // e.printStackTrace(); // // TODO: handle exception // }} } -Dlog4j.configuration=file:C:\Users\gaoyuan\Desktop\Zookeeper\Zookeeper\zookeeper_code\zookeeper_code\zookeeper-release-3.5.4\conf\log4j.properties

4.應用場景

1.數據的發布與訂閱

發布與訂閱即所謂的配置中心

推(Push)

拉(Pull)

具備三個特征

  • 數據量比較小
  • 數據會動態發生變化
  • 集群中各機器共享,配置一致

配置獲取

配置變更

2.命名服務

Zookeeper節點創建的API接口創建順序節點,并且返回值中會返回這個節點的完整名字,來生成全局唯一的ID

  • 集群管理

  • Master選舉

  • 分布式鎖

  • 分布式隊列

  • FIFO先入先出
  • 分布式屏障
  • 3.集群管理

    利用臨時節點,判斷服務器的斷開與連接,監聽。來管理集群

    分布式日志收集系統

    4.Master選舉

    Master一般協調集群中的其他系統單元,具有對分布式系統狀態變更的絕對權。

  • 讀寫分離的產經,客戶端的寫請求往往是由Master來處理
  • Master負責處理一些復雜的邏輯,同步給其他單元
  • 5.分布式鎖

    • 排他鎖

    事務T1對數據對象O1加上了排他鎖,枷鎖期間,只允許事務T1對O1進行讀取和更新操作,加鎖期間,其他事務不能對這個數據對象進行任何類型的操作

    • 共享鎖(讀鎖)

    事務T1對數據對象O1加上了共享鎖,則當前事務只能對O1進行讀取事務,其他事務也只能對這個數據對象加共享鎖

    羊群效應

    6.分布式隊列

    特征

    • ZAB協議需要確保那些已經在Leader服務器上提交的事務最終被所以服務器都提交
    • ZAB協議需要確保丟棄那些只在Leader服務器上被提出的事務

    FIFO先入先出

    First Input First Output 先入先出

    分布式屏障

    等待隊列元素聚集后同意安排處理執行的Barrier模型

    5.Zookeeper原理

    5.1 ZAB協議

    Zookeeper Atomic Broadcast(ZAB,Zookeeper源自消息廣播協議)

    支持崩潰恢復的原子廣播協議

    cai用ZAB協議來實現分布式數據的一致性,主備模式的系統架構來保持個副本之間的數據一致性,表現形式就是 采用單一的主進程來接受并處理客戶端的所有事務請求,然后采用事務Proposal的形式廣播到所有的副本進程中

    5.2兩種模式

    崩潰恢復與消息廣播

    5.3三種狀態*

    • LOOKING :Leader選舉階段
    • FOLLOWING:Follower服務器和Leader服務器
    • LEADING : Leader服務器作為主進程領導狀態

    所有進程初始化狀態都是LOOKING狀態

    5.4ZAB與Paxos的聯系與區別

    • 都存在一個類似于Leader進程的角色,負責協調多個Follower進程的運行
    • Leader進程都會等待超過半數的Follower做出正確反饋后,才會提議進行提交
    • 在ZAB協議中,每個Proposal都包含一個epoch值,用來代表當前的Leader周期,在Paxos中同樣存在這樣一個標識

    ZAB協議主要用于高可用的分布式數據主備系統

    Paxos算法主要構件一個分布式的一致性狀態機系統

    5.4服務器的角色*

    Leader

    • 事務請求的唯一調度和處理者,保證集群事務
    • 集群內部各服務器的調度者

    Follwer

    • 處理客戶端非事務性請求(讀取數據),轉發事務給Leader
    • 參與事務請求Proposal的投票
    • 參數Leader選舉投票

    Observer

    提供非事務服務

    不參與投票

    6.源碼刨析

    1.搭建項目

    在VM options中添加(log4j的文件目錄)

    -Dlog4j.configuration=file:C:\Users\gaoyuan\Desktop\Zookeeper\Zookeeper\zookeeper_code\zookeeper_code\zookeeper-release-3.5.4\conf\log4j.properties

    在program arguments**( 配置zoo.cfg的目錄)**

    C:\Users\gaoyuan\Desktop\Zookeeper\Zookeeper\zookeeper_code\zookeeper_code\zookeeper-release-3.5.4\conf\zoo.cfg

    https://www.cnblogs.com/heyonggang/p/12123991.html

    2.server的創建流程

    啟動類 ZooKeeperServerMain

  • 啟動類
  • main.initializeAndRun(args)
  • 注冊jmx
  • ManagedUtil.registerLog4jMBeans();
  • 解析配置文件

    config.parse(args[0]);

  • 初始化日志

  • FileTxnSnapLog txnLog = null; txnLog = new FileTxnSnapLog(config.dataLogDir, config.dataDir);
  • 初始化zkServer對象
  • final ZooKeeperServer zkServer = new ZooKeeperServer(txnLog,config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, null);
  • 創建ServerCnxnFactory對象=====ServerCnxnFactory是Zookeeper中的重要組件,負責處理客戶端與服務器的連接
  • //初始化server端IO對象,默認是NIOServerCnxnFactory:Java原生NIO處理網絡IO事件cnxnFactory = ServerCnxnFactory.createFactory();
  • 初始化配置信息
  • //初始化配置信息 cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), false);@Overridepublic void configure(InetSocketAddress addr, int maxcc, boolean secure) throws IOException {if (secure) {throw new UnsupportedOperationException("SSL isn't supported in NIOServerCnxn");}configureSaslLogin();maxClientCnxns = maxcc;//會話超時時間sessionlessCnxnTimeout = Integer.getInteger(ZOOKEEPER_NIO_SESSIONLESS_CNXN_TIMEOUT, 10000);// We also use the sessionlessCnxnTimeout as expiring interval for// cnxnExpiryQueue. These don't need to be the same, but the expiring// interval passed into the ExpiryQueue() constructor below should be// less than or equal to the timeout.//過期隊列cnxnExpiryQueue =new ExpiryQueue<NIOServerCnxn>(sessionlessCnxnTimeout);expirerThread = new ConnectionExpirerThread();//根據CPU個數計算selector線程的數量int numCores = Runtime.getRuntime().availableProcessors();// 32 cores sweet spot seems to be 4 selector threadsnumSelectorThreads = Integer.getInteger(ZOOKEEPER_NIO_NUM_SELECTOR_THREADS,Math.max((int) Math.sqrt((float) numCores/2), 1));if (numSelectorThreads < 1) {throw new IOException("numSelectorThreads must be at least 1");}//計算woker線程的數量numWorkerThreads = Integer.getInteger(ZOOKEEPER_NIO_NUM_WORKER_THREADS, 2 * numCores);//worker線程關閉時間workerShutdownTimeoutMS = Long.getLong(ZOOKEEPER_NIO_SHUTDOWN_TIMEOUT, 5000);LOG.info("Configuring NIO connection handler with "+ (sessionlessCnxnTimeout/1000) + "s sessionless connection"+ " timeout, " + numSelectorThreads + " selector thread(s), "+ (numWorkerThreads > 0 ? numWorkerThreads : "no")+ " worker threads, and "+ (directBufferBytes == 0 ? "gathered writes." :("" + (directBufferBytes/1024) + " kB direct buffers.")));//初始化selector線程for(int i=0; i<numSelectorThreads; ++i) {selectorThreads.add(new SelectorThread(i));}this.ss = ServerSocketChannel.open();ss.socket().setReuseAddress(true);LOG.info("binding to port " + addr);ss.socket().bind(addr);ss.configureBlocking(false);//初始化accept線程,這里看出accept線程只有一個,里面會注冊監聽ACCEPT事件acceptThread = new AcceptThread(ss, addr, selectorThreads);}
  • 啟動服務
  • //啟動服務:此方法除了啟動ServerCnxnFactory,還會啟動ZooKeeper cnxnFactory.startup(zkServer); package org.apache.zookeeper.server; //啟動類 ZooKeeperServerMain main = new ZooKeeperServerMain(); // 解析單機模式的配置對象,并啟動單機模式protected void initializeAndRun(String[] args)throws ConfigException, IOException, AdminServerException{try {//注冊jmx// JMX的全稱為Java Management Extensions.是管理Java的一種擴展。// 這種機制可以方便的管理、監控正在運行中的Java程序。常用于管理線程,內存,日志Level,服務重啟,系統環境等ManagedUtil.registerLog4jMBeans();} catch (JMException e) {LOG.warn("Unable to register log4j JMX control", e);}// 創建服務配置對象ServerConfig config = new ServerConfig();//如果入參只有一個,則認為是配置文件的路徑if (args.length == 1) {// 解析配置文件config.parse(args[0]);} else {// 參數有多個,解析參數config.parse(args);}// 根據配置運行服務runFromConfig(config);} public void runFromConfig(ServerConfig config)throws IOException, AdminServerException {LOG.info("Starting server");FileTxnSnapLog txnLog = null;try {// Note that this thread isn't going to be doing anything else,// so rather than spawning another thread, we will just call// run() in this thread.// create a file logger url from the command line args//初始化日志文件txnLog = new FileTxnSnapLog(config.dataLogDir, config.dataDir);// 初始化zkServer對象final ZooKeeperServer zkServer = new ZooKeeperServer(txnLog,config.tickTime, config.minSessionTimeout, config.maxSessionTimeout, null);// 服務結束鉤子,用于知道服務器錯誤或關閉狀態更改。final CountDownLatch shutdownLatch = new CountDownLatch(1);zkServer.registerServerShutdownHandler(new ZooKeeperServerShutdownHandler(shutdownLatch));// Start Admin server// 創建admin服務,用于接收請求(創建jetty服務)adminServer = AdminServerFactory.createAdminServer();// 設置zookeeper服務adminServer.setZooKeeperServer(zkServer);// AdminServer是3.5.0之后支持的特性,啟動了一個jettyserver,默認端口是8080,訪問此端口可以獲取Zookeeper運行時的相關信息adminServer.start();boolean needStartZKServer = true;//---啟動ZooKeeperServer//判斷配置文件中 clientportAddress是否為nullif (config.getClientPortAddress() != null) {//ServerCnxnFactory是Zookeeper中的重要組件,負責處理客戶端與服務器的連接//初始化server端IO對象,默認是NIOServerCnxnFactory:Java原生NIO處理網絡IO事件cnxnFactory = ServerCnxnFactory.createFactory();//初始化配置信息cnxnFactory.configure(config.getClientPortAddress(), config.getMaxClientCnxns(), false);//啟動服務:此方法除了啟動ServerCnxnFactory,還會啟動ZooKeepercnxnFactory.startup(zkServer);// zkServer has been started. So we don't need to start it again in secureCnxnFactory.needStartZKServer = false;}if (config.getSecureClientPortAddress() != null) {secureCnxnFactory = ServerCnxnFactory.createFactory();secureCnxnFactory.configure(config.getSecureClientPortAddress(), config.getMaxClientCnxns(), true);secureCnxnFactory.startup(zkServer, needStartZKServer);}// 定時清除容器節點//container ZNodes是3.6版本之后新增的節點類型,Container類型的節點會在它沒有子節點時// 被刪除(新創建的Container節點除外),該類就是用來周期性的進行檢查清理工作containerManager = new ContainerManager(zkServer.getZKDatabase(), zkServer.firstProcessor,Integer.getInteger("znode.container.checkIntervalMs", (int) TimeUnit.MINUTES.toMillis(1)),Integer.getInteger("znode.container.maxPerMinute", 10000));containerManager.start();// Watch status of ZooKeeper server. It will do a graceful shutdown// if the server is not running or hits an internal error.// ZooKeeperServerShutdownHandler處理邏輯,只有在服務運行不正常的情況下,才會往下執行shutdownLatch.await();// 關閉服務shutdown();if (cnxnFactory != null) {cnxnFactory.join();}if (secureCnxnFactory != null) {secureCnxnFactory.join();}if (zkServer.canShutdown()) {zkServer.shutdown(true);}} catch (InterruptedException e) {// warn, but generally this is okLOG.warn("Server interrupted", e);} finally {if (txnLog != null) {txnLog.close();}}}

    3.Leader選舉

    概念

    • 外部投票:特指其他服務器發來的投票
    • 內部投票:服務器自身當前的投票
    • 選舉輪次:ZooKeeper服務器Leader選舉的輪次,即logical clock(邏輯時鐘)
    • Pk: 指對內部投票和外部投票進行一個對比來確定是否需要變更內部投票
    • sendqueue:選票發送隊列:保存待發送的投票
    • recvqueue:選票接收隊列,用于保存接收到的外部投票

    //====================

    服務器啟動時期的Leader選舉

    1)每個Server發出一個投票

    2)接受來自給各個服務器的投票

    3)處理投票

    • 優先檢查ZXID. ZXID比較大的服務器優先作為Leader
    • 如果ZXID相同,那么就比較myid。 myId較大的服務器作為

    4)統計投票

    5)改變服務器狀態

    服務器運行時期的Leader的選舉

    ? 1)變更狀態

    ? 2)每個Server會發出一個投票

    ? 3) 接受來自各個服務器的投票,與啟動時過程相同

    ? 4)處理投票

    ? 5)統計投票

    ? 6)改變服務器的狀態

    public interface Election {//?尋找Leaderpublic Vote lookForLeader() throws InterruptedException;//停止public void shutdown(); }

    FastLeaderElection有三個重要的類

    1.Notification

    表示收到的選舉投票信息(其他服務器發來的選舉投票信息)

    /*Notification表示收到的選舉投票信息(其他服務器發來的選舉投票信息),其包含了被選舉者的id、zxid、選舉周期等信息,其buildMsg方法將選舉信息封裝至ByteBuffer中再進行發送*/static public class Notification {/** Format version, introduced in 3.4.6*/public final static int CURRENTVERSION = 0x2;int version;/** Proposed leader**/// 被推選的leader的idlong leader;/** zxid of the proposed leader*/// 被推選的leader的事務idlong zxid;/** Epoch*/// 推選者的選舉周期long electionEpoch;/** current state of sender*/// 推選者的狀態QuorumPeer.ServerState state;/** Address of sender*/// 推選者的idlong sid;QuorumVerifier qv;/** epoch of the proposed leader*/// 被推選者的選舉周期long peerEpoch;}

    2.ToSend

    表示發送給其他服務器的選舉投票信息

    /*ToSend表示發送給其他服務器的選舉投票信息,也包含了被選舉者的id、zxid、選舉周期等信息*/static public class ToSend {static enum mType {crequest, challenge, notification, ack}ToSend(mType type,long leader,long zxid,long electionEpoch,ServerState state,long sid,long peerEpoch,byte[] configData) {this.leader = leader;this.zxid = zxid;this.electionEpoch = electionEpoch;this.state = state;this.sid = sid;this.peerEpoch = peerEpoch;this.configData = configData;}/** Proposed leader in the case of notification*///被推舉的leader的idlong leader;/** id contains the tag for acks, and zxid for notifications*/// 被推舉的leader的最大事務idlong zxid;/** Epoch*/// 推舉者的選舉周期long electionEpoch;/** Current state;*/// 推舉者的狀態QuorumPeer.ServerState state;/** Address of recipient*/// 推舉者的idlong sid;/** Used to send a QuorumVerifier (configuration info)*/byte[] configData = dummyData;/** Leader epoch*/// 被推舉的leader的選舉周期long peerEpoch;}LinkedBlockingQueue<ToSend> sendqueue;LinkedBlockingQueue<Notification> recvqueue;

    3.Messenger

    protected class Messenger {/*** Receives messages from instance of QuorumCnxManager on* method run(), and processes such messages.*/class WorkerReceiver extends ZooKeeperThread {//是否停止volatile boolean stop;//服務器之間的連接QuorumCnxManager manager;WorkerReceiver(QuorumCnxManager manager) {super("WorkerReceiver");this.stop = false;this.manager = manager;}public void run() {//響應Message response;while (!stop) {//不停止// Sleeps on receivetry {//從RecvQueue取一個選舉投票信息(從其他服務器發射過來的)response = manager.pollRecvQueue(3000, TimeUnit.MILLISECONDS);//無投票則跳過if(response == null) continue;// The current protocol and two previous generations all send at least 28 bytesif (response.buffer.capacity() < 28) {LOG.error("Got a short response: " + response.buffer.capacity());continue;}// this is the backwardCompatibility mode in place before ZK-107// It is for a version of the protocol in which we didn't send peer epoch// With peer epoch and version the message became 40 bytesboolean backCompatibility28 = (response.buffer.capacity() == 28);// this is the backwardCompatibility mode for no version informationboolean backCompatibility40 = (response.buffer.capacity() == 40);response.buffer.clear();// Instantiate Notification and set its attributesNotification n = new Notification();int rstate = response.buffer.getInt();long rleader = response.buffer.getLong();long rzxid = response.buffer.getLong();long relectionEpoch = response.buffer.getLong();long rpeerepoch;int version = 0x0;if (!backCompatibility28) {rpeerepoch = response.buffer.getLong();if (!backCompatibility40) {/** Version added in 3.4.6*/version = response.buffer.getInt();} else {LOG.info("Backward compatibility mode (36 bits), server id: {}", response.sid);}} else {LOG.info("Backward compatibility mode (28 bits), server id: {}", response.sid);rpeerepoch = ZxidUtils.getEpochFromZxid(rzxid);}QuorumVerifier rqv = null;// check if we have a version that includes config. If so extract config info from message.if (version > 0x1) {int configLength = response.buffer.getInt();byte b[] = new byte[configLength];response.buffer.get(b);synchronized(self) {try {rqv = self.configFromString(new String(b));QuorumVerifier curQV = self.getQuorumVerifier();if (rqv.getVersion() > curQV.getVersion()) {LOG.info("{} Received version: {} my version: {}", self.getId(),Long.toHexString(rqv.getVersion()),Long.toHexString(self.getQuorumVerifier().getVersion()));if (self.getPeerState() == ServerState.LOOKING) {LOG.debug("Invoking processReconfig(), state: {}", self.getServerState());self.processReconfig(rqv, null, null, false);if (!rqv.equals(curQV)) {LOG.info("restarting leader election");self.shuttingDownLE = true;self.getElectionAlg().shutdown();break;}} else {LOG.debug("Skip processReconfig(), state: {}", self.getServerState());}}} catch (IOException e) {LOG.error("Something went wrong while processing config received from {}", response.sid);} catch (ConfigException e) {LOG.error("Something went wrong while processing config received from {}", response.sid);}} } else {LOG.info("Backward compatibility mode (before reconfig), server id: {}", response.sid);}/** If it is from a non-voting server (such as an observer or* a non-voting follower), respond right away.*/if(!validVoter(response.sid)) {//獲取自己的投票Vote current = self.getCurrentVote();QuorumVerifier qv = self.getQuorumVerifier();//構建對象ToSend notmsg = new ToSend(ToSend.mType.notification,current.getId(),current.getZxid(),logicalclock.get(),self.getPeerState(),response.sid,current.getPeerEpoch(),qv.toString().getBytes());//放到隊列等待發送sendqueue.offer(notmsg);} else {//接受到服務器的選票信息// Receive new messageif (LOG.isDebugEnabled()) {LOG.debug("Receive new notification message. My id = "+ self.getId());}// State of peer that sent this messageQuorumPeer.ServerState ackstate = QuorumPeer.ServerState.LOOKING;switch (rstate) {//讀取狀態case 0:ackstate = QuorumPeer.ServerState.LOOKING;break;case 1:ackstate = QuorumPeer.ServerState.FOLLOWING;break;case 2:ackstate = QuorumPeer.ServerState.LEADING;break;case 3:ackstate = QuorumPeer.ServerState.OBSERVING;break;default:continue;}n.leader = rleader;n.zxid = rzxid;//獲取選舉周期n.electionEpoch = relectionEpoch;n.state = ackstate;//設置服務器IDn.sid = response.sid;n.peerEpoch = rpeerepoch;n.version = version;n.qv = rqv;/** Print notification info*/if(LOG.isInfoEnabled()){printNotification(n);}/** If this server is looking, then send proposed leader*/if(self.getPeerState() == QuorumPeer.ServerState.LOOKING){recvqueue.offer(n);/** Send a notification back if the peer that sent this* message is also looking and its logical clock is* lagging behind.*/if((ackstate == QuorumPeer.ServerState.LOOKING)&& (n.electionEpoch < logicalclock.get())){Vote v = getVote();QuorumVerifier qv = self.getQuorumVerifier();ToSend notmsg = new ToSend(ToSend.mType.notification,v.getId(),v.getZxid(),logicalclock.get(),self.getPeerState(),response.sid,v.getPeerEpoch(),qv.toString().getBytes());//將消息放到隊列中,等待發送sendqueue.offer(notmsg);}} else {/** If this server is not looking, but the one that sent the ack* is looking, then send back what it believes to be the leader.*///獲取當前的投票Vote current = self.getCurrentVote();if(ackstate == QuorumPeer.ServerState.LOOKING){if(LOG.isDebugEnabled()){LOG.debug("Sending new notification. My id ={} recipient={} zxid=0x{} leader={} config version = {}",self.getId(),response.sid,Long.toHexString(current.getZxid()),current.getId(),Long.toHexString(self.getQuorumVerifier().getVersion()));}QuorumVerifier qv = self.getQuorumVerifier();ToSend notmsg = new ToSend(ToSend.mType.notification,current.getId(),current.getZxid(),current.getElectionEpoch(),self.getPeerState(),response.sid,current.getPeerEpoch(),qv.toString().getBytes());//將消息放到隊列中,等待發送sendqueue.offer(notmsg);}}}} catch (InterruptedException e) {LOG.warn("Interrupted Exception while waiting for new message" +e.toString());}}LOG.info("WorkerReceiver is down");}}/*** This worker simply dequeues a message to send and* and queues it on the manager's queue.*/class WorkerSender extends ZooKeeperThread {//是否終止volatile boolean stop;//服務器之間的連接QuorumCnxManager manager;WorkerSender(QuorumCnxManager manager){super("WorkerSender");this.stop = false;this.manager = manager;}public void run() {while (!stop) {try {//sendqueue中獲取消息ToSend m = sendqueue.poll(3000, TimeUnit.MILLISECONDS);if(m == null) continue;//不為空則進行處理process(m);} catch (InterruptedException e) {break;}}LOG.info("WorkerSender is down");}/*** Called by run() once there is a new message to send.** @param m message to send*/void process(ToSend m) {//構建消息ByteBuffer requestBuffer = buildMsg(m.state.ordinal(),m.leader,m.zxid,m.electionEpoch,m.peerEpoch,m.configData);//發送消息manager.toSend(m.sid, requestBuffer);}}WorkerSender ws;WorkerReceiver wr;Thread wsThread = null;Thread wrThread = null;/*** Constructor of class Messenger.** @param manager Connection manager*/Messenger(QuorumCnxManager manager) {//創建 WorkerSenderthis.ws = new WorkerSender(manager);//創建新線程this.wsThread = new Thread(this.ws,"WorkerSender[myid=" + self.getId() + "]");//守護線程this.wsThread.setDaemon(true);//創建WorkerReceiverthis.wr = new WorkerReceiver(manager);this.wrThread = new Thread(this.wr,"WorkerReceiver[myid=" + self.getId() + "]");//設置守護線程this.wrThread.setDaemon(true);}/*** Starts instances of WorkerSender and WorkerReceiver*/void start(){this.wsThread.start();this.wrThread.start();}/*** Stops instances of WorkerSender and WorkerReceiver*/void halt(){this.ws.stop = true;this.wr.stop = true;}}

    類屬性

    //日志 private static final Logger LOG = LoggerFactory.getLogger(FastLeaderElection.class);/*** Determine how much time a process has to wait* once it believes that it has reached the end of* leader election.*/ //完成leader election的等待時間final static int finalizeWait = 200;/*** Upper bound on the amount of time between two consecutive* notification checks. This impacts the amount of time to get* the system up again after long partitions. Currently 60 seconds.*/ //兩個連續 通知之間的最大時間final static int maxNotificationInterval = 60000;/*** This value is passed to the methods that check the quorum* majority of an established ensemble for those values that* should not be taken into account in the comparison * (electionEpoch and zxid). */final static int IGNOREVALUE = -1;/*** Connection manager. Fast leader election uses TCP for* communication between peers, and QuorumCnxManager manages* such connections.*///管理服務器之間的連接QuorumCnxManager manager;// 選票發送隊列,?于保存待發送的選票LinkedBlockingQueue<ToSend> sendqueue;// 選票接收隊列,?于保存接收到的外部投票LinkedBlockingQueue<Notification> recvqueue;// 投票者QuorumPeer self;Messenger messenger;// 邏輯時鐘volatile long logicalclock; /* Election instance */// 推選的leader的idlong proposedLeader;// 推選的leader的zxidlong proposedZxid;// 推選的leader的選舉周期long proposedEpoch;// 是否停?選舉volatile boolean stop;

    4.sendNotififications

    private void sendNotifications() {//遍歷投票參與者集合for (long sid : self.getCurrentAndNextConfigVoters()) {QuorumVerifier qv = self.getQuorumVerifier();//構建對象ToSend notmsg = new ToSend(ToSend.mType.notification,proposedLeader,proposedZxid,logicalclock.get(),QuorumPeer.ServerState.LOOKING,sid,proposedEpoch, qv.toString().getBytes());if(LOG.isDebugEnabled()){LOG.debug("Sending Notification: " + proposedLeader + " (n.leader), 0x" +Long.toHexString(proposedZxid) + " (n.zxid), 0x" + Long.toHexString(logicalclock.get()) +" (n.round), " + sid + " (recipient), " + self.getId() +" (myid), 0x" + Long.toHexString(proposedEpoch) + " (n.peerEpoch)");}//放到隊列等待發送sendqueue.offer(notmsg);}}

    5.totalOrderPredicate

    該函數將接受的投票與自身投票進行pk,查看是否消息中包含的服務器id是否更優,其按照epoch,zxid,id的優先級進行pk

    protected boolean totalOrderPredicate(long newId, long newZxid, long newEpoch, long curId, long curZxid, long curEpoch) {LOG.debug("id: " + newId + ", proposed id: " + curId + ", zxid: 0x" +Long.toHexString(newZxid) + ", proposed zxid: 0x" + Long.toHexString(curZxid));//使用投票器看權重是否為0if(self.getQuorumVerifier().getWeight(newId) == 0){return false;}/** We return true if one of the following three cases hold:* 1- New epoch is higher* 2- New epoch is the same as current epoch, but new zxid is higher* 3- New epoch is the same as current epoch, new zxid is the same* as current zxid, but server id is higher.*/return ((newEpoch > curEpoch) ||((newEpoch == curEpoch) &&((newZxid > curZxid) || ((newZxid == curZxid) && (newId > curId)))));}

    6.termPredicate

    判斷leader選舉是否結束,是否有一半以上的服務器選出了leader

    private boolean termPredicate(HashMap<Long, Vote> votes, Vote vote) {SyncedLearnerTracker voteSet = new SyncedLearnerTracker();voteSet.addQuorumVerifier(self.getQuorumVerifier());if (self.getLastSeenQuorumVerifier() != null&& self.getLastSeenQuorumVerifier().getVersion() > self.getQuorumVerifier().getVersion()) {voteSet.addQuorumVerifier(self.getLastSeenQuorumVerifier());}/** First make the views consistent. Sometimes peers will have different* zxids for a server depending on timing.*/for (Map.Entry<Long, Vote> entry : votes.entrySet()) {/ 將等于當前投票的項放?setif (vote.equals(entry.getValue())) {voteSet.addAck(entry.getKey());}}//統計set,查看投某個id的票數是否超過?半return voteSet.hasAllQuorums();}

    概念補充

    1.zxid概念補充

    ZooKeeper節點狀態改變的每一個操作都將使節點接收到一個Zxid格式的時間戳,并且這個時間戳全局有序。也就是說,每個對節點的改變都將產生一個唯一的Zxid

    cZxid概念

    對應為該節點的創建時間(Create)

    mZxid概念

    對應該節點的最近一次修改的時間(Mofify)

    與其子節點無關

    問題

  • jar包報錯
  • 要把項目中Build里面的jar包在項目中引入一下

    作業的資料查找

    https://segmentfault.com/a/1190000019670015

    https://blog.csdn.net/sqh201030412/article/details/51446434?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-1&spm=1001.2101.3001.4242

    單詞

    subscribe 訂閱,捐款
    Access Control Lists,ACL 訪問控制列表

    Latch 插銷,鎖

    election 選舉

    Notification 通知

    extract通知

    Verifier 檢驗人

    vote 投票

    Quorum 大多數

    Predicate 斷言,暗示

    Epoch 時代

    Interval 間隔,區間

    propos 關于評論

    logical邏輯

    Policy 政策

    Retry 停止重試

    Exponential 指數

    guarantee保證

    tribute 奉獻,致敬

    總結

    以上是生活随笔為你收集整理的zookeeper笔记+源码刨析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    色噜噜日韩精品欧美一区二区 | 国产黄色在线看 | 超碰av在线播放 | 久久久久久久久久久久亚洲 | 久草在线欧美 | 欧亚日韩精品一区二区在线 | 香蕉网站在线观看 | 色噜噜日韩精品欧美一区二区 | 日韩中文字幕网站 | 狠狠色丁香 | 久久婷婷网| 五月天久久婷 | 亚洲精品视频在线免费播放 | 国产福利一区二区在线 | 国产a免费 | 亚洲国产欧美在线人成大黄瓜 | 日韩一区二区免费视频 | 在线观看视频97 | 成人一级免费视频 | 久久永久视频 | 五月天久久激情 | 最新色视频 | 九色视频网站 | 国产欧美精品一区二区三区四区 | 欧美极品少妇xxxx | 久久线视频 | 黄网站免费大全入口 | 久久久久久麻豆 | 丰满少妇一级片 | 亚洲欧美日韩中文在线 | 亚洲影院色 | www日日夜夜 | 日韩色综合网 | 美州a亚洲一视本频v色道 | 操老逼免费视频 | 精品在线不卡 | 在线免费观看视频一区二区三区 | 国产一区福利在线 | 狠狠狠狠狠狠狠 | 国产美女被啪进深处喷白浆视频 | 在线播放国产一区二区三区 | 国产精品久久久久久a | 亚洲视频专区在线 | 最近中文字幕第一页 | 香蕉久久久久 | 激情视频国产 | 在线日韩中文 | 99欧美精品 | 波多野结衣资源 | 久久精品国产一区二区电影 | 欧美最猛性xxxxx(亚洲精品) | 成人福利在线播放 | 久久免费看av | www.888av| 欧美精品首页 | 久草免费色站 | 91视频高清 | 国产亚洲精品女人久久久久久 | 精品999在线 | 免费在线观看av不卡 | 国产人成一区二区三区影院 | 亚洲视频精品在线 | 国产破处视频在线播放 | 国产高清视频免费在线观看 | 啪啪激情网 | 午夜精品久久久久久久久久 | 久久久夜色 | 91精品久久久久久综合五月天 | 久久爱992xxoo | 日韩精品一区二区三区免费观看视频 | 人人澡澡人人 | 激情综合电影网 | 久久久999精品视频 国产美女免费观看 | 在线观看网站你懂的 | 激情视频一区二区三区 | 日日日日 | 91免费视频网站在线观看 | 啪啪资源| 91香蕉嫩草| 国产亚洲一区二区三区 | 伊人国产在线观看 | 热久久精品在线 | 日韩视频在线播放 | 国产一级二级在线 | 国产精品99久久久精品免费观看 | 国产精品igao视频网网址 | 97香蕉久久国产在线观看 | 久草剧场 | 6699私人影院 | 久久综合免费视频影院 | 97超碰人人网 | 欧美综合色 | 91看片网址| 日韩电影精品 | 色婷婷久久久 | 久久久男人的天堂 | 超碰在线个人 | 三级黄在线 | 欧美日韩精品免费观看视频 | 美女视频久久黄 | 久久国产美女视频 | 国产欧美在线一区二区三区 | 日韩中文字幕亚洲一区二区va在线 | 亚洲开心激情 | 日韩乱色精品一区二区 | 美女福利视频一区二区 | 久久久久网址 | 中文字幕在线字幕中文 | 国产精品无| 在线观看午夜av | 中文字幕中文字幕在线一区 | 国产精品日韩在线观看 | 91亚·色 | av手机版| 国产免费观看久久黄 | 色天堂在线视频 | 精品在线一区二区 | 99情趣网视频 | 欧美日韩性视频在线 | 免费在线观看成年人视频 | 久久国产成人午夜av影院宅 | 日日精品| 天天操天天爱天天爽 | 国产三级香港三韩国三级 | 国产日韩精品一区二区三区在线 | 精品欧美在线视频 | 又爽又黄又无遮挡网站动态图 | 久草在线国产 | aaa日本高清在线播放免费观看 | 综合网欧美 | 欧美一级专区免费大片 | 久久好看免费视频 | 国产黄色精品 | 久久久久福利视频 | 亚洲一区免费在线 | 岛国av在线不卡 | 91亚色视频 | 超碰97久久| www.人人干| 91伊人久久大香线蕉蜜芽人口 | 国内揄拍国内精品 | 在线免费精品视频 | 日韩电影中文,亚洲精品乱码 | 91秒拍国产福利一区 | 天天干,天天射,天天操,天天摸 | 91九色在线视频观看 | 超碰免费av | 奇米网8888| 夜夜操天天操 | 精品久久久久久久久亚洲 | 999久久久免费视频 午夜国产在线观看 | 色噜噜狠狠狠狠色综合 | 日韩高清久久 | 在线观看成人小视频 | 婷婷在线免费 | 久久久精品福利视频 | 精品产品国产在线不卡 | 又湿又紧又大又爽a视频国产 | 久久免费看| av青草| 成av人电影| 日韩欧美一区二区三区在线观看 | 婷婷激情久久 | 亚洲免费av电影 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产一级免费片 | 91禁在线观看 | 久久国产露脸精品国产 | 久久久在线视频 | 日韩中文字幕免费在线观看 | 国产高清久久久久 | 日韩精品高清视频 | 日韩久久久久久久久久久久 | 18久久久| 激情综合色综合久久综合 | 美腿丝袜一区二区三区 | 国产一线天在线观看 | 中文字幕资源网 国产 | 国产综合精品一区二区三区 | 99精品免费观看 | 亚洲精品小视频 | 99国产精品视频免费观看一公开 | 一区二区三区免费在线 | 在线观看中文字幕亚洲 | 色网站在线看 | 四虎国产精品免费观看视频优播 | 国产裸体视频网站 | 日韩乱理 | 国产99在线 | 一本一本久久a久久精品综合 | 99久久网站 | 成人av资源网站 | www.久久视频 | 99这里只有精品99 | 精品一区在线 | 国产欧美日韩一区 | 久久精品电影网 | 久久影院一区 | 人人爽人人爽人人片av | 日韩免费视频 | 波多野结衣精品视频 | 国产精品欧美久久久久三级 | 欧洲一区二区在线观看 | 久久精品成人热国产成 | 视频精品一区二区三区 | 九九九电影免费看 | 伊人官网 | 成年人在线免费视频观看 | 97精品超碰一区二区三区 | 国产色视频123区 | 精品一区精品二区 | 日韩视频二区 | 91看毛片 | 色婷婷www | 国产精品女 | 日本中文字幕网站 | 国产成人亚洲在线观看 | 91女子私密保健养生少妇 | 成人一区二区三区在线 | 三级av在线免费观看 | 在线观看免费视频你懂的 | 九月婷婷色 | 国产免费一区二区三区网站免费 | 日本大片免费观看在线 | 久久精品亚洲 | 免费精品人在线二线三线 | 亚洲aaa毛片 | 久久午夜视频 | www日韩视频 | 久久人人爽人人 | 一级性生活片 | 久久不见久久见免费影院 | 91精品国产高清自在线观看 | 久久夜靖品 | 久久国产精品成人免费浪潮 | 色狠狠操 | 99视频国产在线 | 亚洲国产wwwccc36天堂 | 欧美精彩视频在线观看 | 国产精品久久9 | 久久精品99国产精品 | 日本久久精品 | 韩国一区二区三区视频 | 免费日韩视 | 欧美一级片在线观看视频 | 视频国产在线观看18 | 国产精品永久久久久久久久久 | 自拍超碰在线 | 中文字幕在线观看一区 | 久久精品96 | 亚洲天堂网站 | 欧美在线aaa| 91中文视频 | 久久精品999 | 久久精品高清 | 日日干天天爽 | 成年人黄色免费网站 | 国产精品久久久久国产精品日日 | 二区三区av| 欧美精品中文字幕亚洲专区 | 久久精品日产第一区二区三区乱码 | 超碰九九 | 91麻豆精品国产91久久久更新时间 | 婷婷丁香色 | 国产91精品欧美 | av中文字幕日韩 | 永久免费的啪啪网站免费观看浪潮 | 成人午夜免费福利 | 日韩精品久久久久久久电影99爱 | 国产免费亚洲高清 | 精品久久网站 | 婷婷色社区 | 国产一级精品在线观看 | 高清在线一区 | 激情久久久久久久久久久久久久久久 | 91福利在线导航 | 国产精品一区免费看8c0m | 亚洲精品999 | 91在线一区二区 | 国产精品久久久久久久久久新婚 | www.夜夜草 | 成人在线网站观看 | 久久久999 | 亚洲三级网| 999久久久久久 | av大全在线观看 | 欧美一区二区三区免费观看 | 99综合影院在线 | 国产精品美女久久久久久久久久久 | 久久精品导航 | 最近日韩中文字幕中文 | 欧美日韩一级久久久久久免费看 | 国内精品久久久久久 | 成人亚洲精品国产www | avhd高清在线谜片 | 日韩免费在线观看视频 | 国内精品视频一区二区三区八戒 | 在线影院 国内精品 | 91夫妻视频 | 国产极品尤物在线 | 天堂av在线免费观看 | 久久电影色 | 亚洲视频电影在线 | 日韩精品一区二区三区免费观看视频 | 久久国产精品免费 | 成人高清在线观看 | 亚洲综合丁香 | 天天操天天操天天爽 | www.午夜色.com | 91在线最新 | 97在线观看免费高清 | 美女黄色网在线播放 | 久久精品一 | 国产精品一区二区精品视频免费看 | 亚洲综合少妇 | 男女视频久久久 | 国产精品久久久久久久久免费看 | 亚洲色图美腿丝袜 | 婷婷六月丁 | 狠狠干,狠狠操 | 人人爽人人澡人人添人人人人 | 国产午夜三级一区二区三 | 在线观看中文 | 99久久精品费精品 | 伊人资源站 | 成人黄色片在线播放 | 国产黄色片在线 | 日韩中文在线视频 | 99久久日韩精品视频免费在线观看 | 欧美在线久久 | 激情丁香婷婷 | 日韩理论在线播放 | wwwwww色| 蜜臀aⅴ国产精品久久久国产 | 在线观看日韩精品 | 国产手机在线播放 | 狠狠干狠狠艹 | 国产欧美日韩一区 | 亚洲国产精品va在线看 | 最近能播放的中文字幕 | 婷婷色资源 | 久久综合加勒比 | 香蕉久久久久久av成人 | 精品91| 日本99热| 99爱精品视频 | 亚洲精品黄色在线观看 | 在线免费性生活片 | 国产亚洲免费观看 | 国产一区二区不卡视频 | 久久精品直播 | 狠狠干中文字幕 | 日韩三级精品 | 日韩激情三级 | av黄色在线播放 | 中文字幕第 | 国产精品久久久亚洲 | 亚洲国产成人av网 | 99精品免费在线观看 | 日本电影久久 | 91精品久久久久久久久久入口 | 一区二区三区在线观看免费 | 日韩电影在线一区 | 天天射天天做 | 美女福利视频一区二区 | 国产尤物在线观看 | 国内精品免费久久影院 | 天天综合五月天 | 日韩精品免费一区二区在线观看 | 97成人精品视频在线播放 | 天天射天天 | 日韩成人中文字幕 | 在线国产片 | 99久久精品无码一区二区毛片 | 久久久99精品免费观看app | 最近中文字幕第一页 | 欧美日韩高清不卡 | 国产婷婷精品av在线 | 中文字幕色在线视频 | 日日操日日干 | 免费看精品久久片 | 精品国产成人在线影院 | 国产精品网红直播 | 欧美精品久久久久性色 | 久久久久日本精品一区二区三区 | 日韩理论电影网 | www日韩精品| 国产色久| 成人免费视频网站在线观看 | 成人av一区二区兰花在线播放 | 国产区在线看 | 玖玖视频精品 | 久久国色夜色精品国产 | 国产高清福利在线 | 国产伦理一区二区三区 | 国内精品美女在线观看 | 亚洲天天摸日日摸天天欢 | 97视频在线观看免费 | 麻豆视频在线看 | 91免费在线视频 | 国内久久视频 | 日韩黄色免费看 | 久热国产视频 | 97视频免费播放 | 欧美精彩视频在线观看 | 国产精品一区在线播放 | 人人插人人舔 | 综合网天天色 | 97在线观看免费 | 国产日韩高清在线 | 久久99久国产精品黄毛片入口 | 激情xxxx | 欧美一级性生活 | 国产黄在线免费观看 | 日韩精品一区二区在线 | 黄色国产高清 | 五月婷婷丁香在线观看 | 久久综合中文字幕 | 国产高清视频 | 免费亚洲黄色 | 国产对白av| 国产自产高清不卡 | 一区久久久 | 九九热中文字幕 | 久久精品www人人爽人人 | 久久无码精品一区二区三区 | 高清视频一区二区三区 | 欧美婷婷综合 | 成人av影视在线 | 日韩精品一区二区三区高清免费 | 色婷婷88av视频一二三区 | 精品久久久久久久久久岛国gif | 激情视频91 | 69av在线视频 | www.com久久| 久久国内视频 | 国产精品久久久久久久久久不蜜月 | 国产精品6999成人免费视频 | 精品国产一区二区三区久久久蜜臀 | 成人影视免费 | 永久免费av在线播放 | 中文字幕在线一区观看 | 狠狠久久 | 国产精品久久久久久久久久久免费看 | 午夜a区| 亚洲在线a | 在线观看黄色大片 | 亚洲无人区小视频 | 日韩精品专区 | 欧美 另类 交| www好男人 | 在线观看免费成人 | av青草 | 久久久久久久久久影院 | 日韩av中文字幕在线免费观看 | 日韩久久一区 | 男女啪啪免费网站 | 欧美日韩久久不卡 | 亚洲成av片人久久久 | 国产黄色片在线免费观看 | 99在线国产 | 久艹视频在线免费观看 | 国产视频亚洲精品 | 日韩av偷拍| 亚洲国产精品va在线看黑人动漫 | 973理论片235影院9 | 国产成人精品久久亚洲高清不卡 | 91在线观看黄 | 97超视频在线观看 | 亚洲成人一区 | 91亚洲精品久久久久图片蜜桃 | 免费人成在线观看网站 | 国产精品久久久久av | 麻豆国产视频下载 | 最近中文字幕在线中文高清版 | 久久久久久久久久久久亚洲 | 国产精品av在线免费观看 | 欧美一区影院 | 777视频在线观看 | 欧美激情视频一二区 | 狠狠色丁香婷婷综合久久片 | 伊人精品影院 | 蜜桃麻豆www久久囤产精品 | 免费av试看 | 人人舔人人舔 | 成人av地址 | 九九三级毛片 | 亚洲综合色网站 | 亚洲aⅴ一区二区三区 | 日韩精品aaa | av资源网在线播放 | 久久久久激情 | 狠狠干网址 | 色在线观看网站 | 婷婷激情5月天 | 久久草在线视频国产 | 日韩丝袜在线观看 | 精品国产乱码久久久久久1区2匹 | 在线免费视 | 日韩a在线 | 欧美一级免费 | 狠狠久久伊人 | 成年人国产精品 | 日韩一二区在线观看 | 毛片无卡免费无播放器 | 特级黄色片免费看 | 久久国产91 | 深夜国产在线 | 日韩高清免费无专码区 | www.亚洲黄色 | 国产在线免费av | 欧美一区二区三区激情视频 | 在线视频观看你懂的 | 亚洲精品欧美专区 | 日韩av伦理片 | 日韩视频一区二区在线观看 | 最近中文字幕mv免费高清在线 | 亚洲一区日韩在线 | 97网在线观看 | av网址最新 | 国产麻豆剧传媒免费观看 | 久久99久久99久久 | 极品中文字幕 | 97操操操| 久久色视频 | 国产精品99爱 | 国产在线欧美日韩 | 中文字幕乱偷在线 | a√国产免费a | 97色国产| 国产一卡久久电影永久 | 日韩av电影一区 | 精品a在线 | 欧美小视频在线观看 | 91夜夜夜 | 国产精品久久久 | 色av资源网| 久久黄页 | 97热久久免费频精品99 | 亚洲一区二区三区毛片 | 久久在线观看 | 国产91影院| 中文字幕乱码一区二区 | 亚洲爱视频 | 黄色大全免费网站 | 午夜体验区 | 久久不射网站 | 干天天 | 国产精品第7页 | 久久与婷婷 | 在线看黄色的网站 | 热精品| 国产精品一级在线 | 日本h在线播放 | 久久国语露脸国产精品电影 | 久久不卡免费视频 | 日韩精品视频第一页 | 亚洲播放一区 | 美女视频黄免费网站 | 不卡中文字幕av | 欧美国产在线看 | 国产亚洲人 | 国产精品美女在线观看 | 久久视频国产精品免费视频在线 | 亚洲欧美综合精品久久成人 | 黄色大片网| 亚洲黄色av网址 | 韩国av永久免费 | 99色国产| 四虎在线永久免费观看 | 国产精品一区二区吃奶在线观看 | 国产成人三级在线 | 久久99亚洲精品 | 日韩免费观看一区二区 | 在线天堂中文在线资源网 | 在线观看视频一区二区 | 91精品国产91久久久久 | 狠狠色丁香久久综合网 | 美女久久久久久久 | 日日操夜夜操狠狠操 | www黄色 | 国产一区观看 | 精品久久免费 | 在线观看中文字幕dvd播放 | 久久精品一区二区国产 | 91传媒视频在线观看 | 黄色三级免费观看 | 插插插色综合 | 国产123区在线观看 国产精品麻豆91 | 免费黄色一区 | 国产精品一区二区三区电影 | 欧洲一区二区三区精品 | 91一区啪爱嗯打偷拍欧美 | 日韩免费网址 | 欧美一级视频一区 | 黄色高清视频在线观看 | 国产夫妻av在线 | 黄p在线播放 | 国产精品免费一区二区三区 | 亚洲成人av在线电影 | 欧美精品在线免费 | 久久久精品午夜 | 激情网综合 | 中文字幕有码在线观看 | 狠狠操操操 | 四虎小视频| 成人免费大片黄在线播放 | 成人亚洲网| 国产aaa免费视频 | 在线欧美日韩 | 91丨九色丨国产在线 | 午夜免费福利视频 | av在线播放快速免费阴 | 久久久久国产精品一区二区 | 久久精品中文字幕一区二区三区 | 国产手机视频在线观看 | 久久综合婷婷国产二区高清 | 日韩欧美在线影院 | 超碰午夜 | 69av久久 | 免费看久久 | 久久综合狠狠综合久久综合88 | 香蕉网站在线观看 | 午夜精品一区二区三区可下载 | 成人在线网站观看 | 天天干天天做 | 日日夜夜天天 | 日日干夜夜骑 | 区一区二在线 | 缴情综合网五月天 | 91精品国自产在线 | 色综合久久综合网 | 国产精品手机播放 | 安徽妇搡bbbb搡bbbb | 婷婷亚洲五月色综合 | 一区二区亚洲精品 | 久久综合免费视频影院 | 激情婷婷久久 | 韩国精品在线 | 国产精品人人做人人爽人人添 | 亚洲涩涩涩涩涩涩 | 日韩电影在线观看一区二区 | 欧美一级片在线免费观看 | 五月婷婷播播 | 青草视频在线 | 免费视频在线观看网站 | 国内久久久久 | 91亚洲在线 | 国产一区二区在线播放视频 | 日韩精品高清视频 | 久久免费的视频 | 超碰公开在线 | 久草在线精品观看 | 夜夜夜影院 | 日韩网站在线播放 | 九九九九九九精品任你躁 | 国产色网站 | 99中文视频在线 | 521色香蕉网站在线观看 | 日批在线观看 | 国产在线观看午夜 | 精品福利在线视频 | 色91在线| 97综合网| 成年人在线免费视频观看 | 国产在线视频不卡 | 视频91在线 | 国产免费一区二区三区网站免费 | 亚洲人成人99网站 | 蜜臀久久99精品久久久无需会员 | 天天色天天骑天天射 | 久久精品一区二区三 | 91久久精品日日躁夜夜躁国产 | 99久视频| 国产 亚洲 欧美 在线 | 国产日本在线观看 | 伊人资源站 | 国产精品麻豆果冻传媒在线播放 | 精品国产一区二区三区日日嗨 | 中文综合在线 | 在线免费性生活片 | 成人黄在线观看 | 97国产一区二区 | 欧美孕妇与黑人孕交 | 91黄色视屏 | 五月婷婷色播 | 亚洲成人麻豆 | 亚洲a在线观看 | 一区二区不卡高清 | 韩国一区视频 | 美女网站视频久久 | 91av观看 | 在线观看视频中文字幕 | 日韩色视频在线观看 | 亚洲国产一区在线观看 | 国产精品一区二区在线观看 | 特及黄色片 | 久久久久久久国产精品影院 | 日韩在线看片 | 国产又粗又猛又黄又爽的视频 | 韩日电影在线免费看 | 国产精品日韩高清 | 超碰国产在线观看 | 国产精品久久久久久久久免费 | 亚洲精品美女免费 | 国产精品久久久久一区二区国产 | 果冻av在线 | 亚洲欧美视频一区二区三区 | 亚洲日本在线视频观看 | 日韩欧美在线免费观看 | 国产视频在线观看一区二区 | 国产精品一区二区无线 | 中文字幕婷婷 | 久久久国产精品一区二区中文 | 视频在线观看入口黄最新永久免费国产 | 九九在线视频免费观看 | 久久综合久久伊人 | 婷婷精品国产欧美精品亚洲人人爽 | 一区二区在线影院 | 最新超碰在线 | 亚洲人成在线观看 | 久久亚洲影院 | 久久免费视频6 | 一级黄色av | 五月天色婷婷丁香 | 激情综合五月天 | 久草综合视频 | 成人h视频 | 人人看人人草 | 国产一区视频在线播放 | 免费看毛片在线 | 天天操天天色天天射 | 亚洲电影久久久 | 天天操婷婷 | 亚洲欧美偷拍另类 | 国产精品久久久免费看 | 欧美成人精品在线 | 中文字幕有码在线播放 | 狠狠做深爱婷婷综合一区 | 99re亚洲国产精品 | 国产成人精品综合久久久久99 | 色婷婷综合久久久中文字幕 | 91亚洲精品久久久中文字幕 | 天天曰夜夜操 | 91中文字幕网 | 国产v在线观看 | 日韩免费看 | 久久免费视频在线观看30 | 日韩字幕在线 | 欧美激情综合五月色丁香 | 免费观看xxxx9999片 | 成人91在线 | 特级西西444www大精品视频免费看 | 在线看岛国av | 国产精品亚洲成人 | 国产福利一区在线观看 | 国产成人精品免高潮在线观看 | 久久精品官网 | 色婷婷88av视频一二三区 | 日韩一区二区三区不卡 | 成人高清在线观看 | 欧美午夜寂寞影院 | 亚洲h视频在线 | 精品国产视频在线观看 | 精品视频免费播放 | 国产成人一级电影 | 尤物97国产精品久久精品国产 | 久久久久免费观看 | 黄色免费看片网站 | 亚洲精品国久久99热 | 中文字幕在线视频免费播放 | 国产精品a久久 | 国产成人免费精品 | 免费网站v | japanese黑人亚洲人4k | 欧美日韩午夜 | 6080yy午夜一二三区久久 | 国产丝袜一区二区三区 | 高清av影院 | 精品一区精品二区 | 最新中文字幕在线观看视频 | 九色福利视频 | 久草综合在线观看 | 五月婷婷,六月丁香 | 久久成人午夜视频 | 日本精品一区二区三区在线播放视频 | 天天射天天色天天干 | 欧美一区日韩精品 | 黄网站app在线观看免费视频 | 日韩试看| 久久久午夜剧场 | 狠狠狠狠狠操 | 亚洲成人黄色在线观看 | 午夜精品久久久久久久99婷婷 | 99久久精品免费看国产一区二区三区 | 欧美91精品久久久久国产性生爱 | 国产一级二级三级视频 | 欧美 日韩 国产 成人 在线 | 亚洲狠狠婷婷综合久久久 | 婷婷国产在线 | 国产精品久久久久久久久久久免费 | 91最新视频 | 欧美日韩免费视频 | av官网| 国产日韩欧美在线播放 | 国产女v资源在线观看 | 三级黄色网址 | 久久免费中文视频 | 一级a性色生活片久久毛片波多野 | 国产精品精品久久久久久 | 99在线精品视频在线观看 | 国产一二区在线观看 | 国产精品毛片久久蜜 | 深夜男人影院 | 97国产在线 | 欧美精品一区二区在线播放 | 日韩免费在线视频观看 | 日韩精品免费在线 | 欧美大jb | 99久久国产免费看 | 色婷婷狠 | av片在线观看免费 | 日韩极品视频在线观看 | 国产99黄| 欧美福利精品 | 99精品视频网站 | а天堂中文最新一区二区三区 | 96视频在线 | 亚洲在线免费视频 | 天天综合日日夜夜 | 中文字幕在线观看完整版电影 | av在线免费网 | 99在线视频网站 | 日免费视频 | 国产成人精品一区二区三区网站观看 | 亚洲在线黄色 | a在线视频v视频 | 亚洲精品久久久久久久蜜桃 | 成人久久综合 | 婷婷久久综合九色综合 | 91视频这里只有精品 | 麻豆精品传媒视频 | 永久免费的av电影 | 日韩激情免费视频 | 国产免费专区 | 美女久久99 | 超碰人人做 | 久久字幕网 | 人人干网站 | 欧美 另类 交 | 国产裸体无遮挡 | 久久久免费观看 | 日韩伦理片hd | av免费看电影 | 日韩二区在线 | 日韩在线视频一区二区三区 | 色偷偷人人澡久久超碰69 | 欧美成人理伦片 | 日本性生活免费看 | 日本久久久久久 | 成人午夜电影在线播放 | 日女人免费视频 | 日本成人中文字幕在线观看 | 日韩中文字幕免费 | 日韩视频在线观看免费 | 99re在线视频观看 | 狠狠色狠狠色综合系列 | 波多野结衣久久精品 | 精品国精品自拍自在线 | 天无日天天操天天干 | www.夜夜干.com | 91丨九色丨蝌蚪丨老版 | 色综合狠狠干 | 中文字幕日韩免费视频 | 综合中文字幕 | 久久五月天色综合 | 国产99久久九九精品免费 | 国产69久久久 | 久久成人午夜视频 | 亚洲一区 影院 | 国产精品va在线 | 久久久久久久久久久黄色 | 日本aaaa级毛片在线看 | 黄色大片中国 | 免费看精品久久片 | 中文av免费 | 日韩一级黄色av | 国产精品久久久久久爽爽爽 | 国产精品久久久亚洲 | 婷婷精品在线视频 | 免费在线国产 | 射射色 | 日韩在线在线 | 国产精品免费久久久久影院仙踪林 | 免费黄色看片 | 日韩美女av在线 | 99在线精品视频在线观看 | 三级黄色大片在线观看 | 国产一区二区在线视频观看 | 中文字幕影片免费在线观看 | 精品视频999 | 精品国产人成亚洲区 | 久久国产综合视频 | 人人搞人人搞 | 99re久久资源最新地址 | 免费黄色网址网站 | 五月婷婷久 | 激情www | 一区二区视频播放 | 在线观看av中文字幕 | 日韩videos| 国产日韩中文字幕在线 | 天天天天天天干 | 日本精品中文字幕 | 亚洲综合网站在线观看 | 日韩精品一区二区在线观看视频 | 国产精品9999| 中文字幕日韩免费视频 | 久久艹久久| 日韩精品中文字幕在线观看 | www.狠狠操.com | 亚洲人xxx| 一区二区视频在线播放 | 黄色福利网站 | 超碰在线公开免费 | 国产涩图 | 色偷偷88888欧美精品久久 | 成人午夜久久 | 麻豆播放 | 51久久夜色精品国产麻豆 | 2022国产精品视频 | 日本99久久 | 超碰公开在线 | 亚州精品一二三区 | 天天天天色射综合 | 天天久久综合 | 特黄特色特刺激视频免费播放 | 久草在线视频首页 | 国产成人一二三 | 欧美日韩性视频 | 91尤物国产尤物福利在线播放 | 正在播放国产精品 | 欧美精品黑人性xxxx | 又污又黄的网站 | 97av在线视频免费播放 | 成人性生爱a∨ | 久久综合精品一区 | 91在线中字 | 午夜精品电影 | 99久久夜色精品国产亚洲96 | 特级西西www44高清大胆图片 | 99精品一区 | 日本三级全黄少妇三2023 | 亚洲一区二区三区精品在线观看 | 婷婷播播网 | 日韩电影在线观看一区二区 | 9ⅰ精品久久久久久久久中文字幕 | 激情伊人五月天久久综合 | 日本中文字幕系列 | 91麻豆精品国产91久久久无需广告 | 天天干天天射天天操 | 婷婷色六月天 | 久久久香蕉视频 | 国产美女精品视频免费观看 | 亚洲二级片| 中文字幕在线视频第一页 | 亚洲一区二区三区在线看 | 欧美日韩一级视频 | 91精品欧美 | 亚洲天堂网在线视频 | 成人丁香花 | 91免费看黄色 | 日本色小说视频 | 精品夜夜嗨av一区二区三区 | 国产伦精品一区二区三区… | 亚洲精品国精品久久99热 | 国产日韩欧美视频在线观看 | 国产精品一区在线播放 | 国产在线精品一区二区三区 | 蜜臀精品久久久久久蜜臀 | 欧美日韩免费在线观看视频 | 免费在线观看亚洲视频 | 天天插天天干 | 奇米影视8888在线观看大全免费 | 天天爱天天操天天射 | 国产视频 亚洲视频 | 亚洲一级电影在线观看 | 91视频久久 | 亚洲视频axxx | 亚洲精品视频网站在线观看 | 久久久国产日韩 | 欧美另类xxx | 日韩色中色 | 欧美日韩精品影院 | 欧美日韩久久不卡 | 日韩专区在线 | 国产一区二区三区久久久 | 久久99国产精品自在自在app |