<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # Zookeeper 概述: 1. ZooKeeper 是 Apache 軟件基金會的一個軟件項目,它為大型分布式計算提供開源的`分布式配置服務`、同步服務和命名注冊。其架構通過冗余服務實現高可用性。 2. Zookeeper 的設計目標是將那些復雜且容易出錯的分布式一致性服務封裝起來,構成一個高效可靠的原語集,并以一系列簡單易用的接口提供給用戶使用。 3. Zookeeper的數據保存在內存中,性能高,可以實現高吞吐量和低延遲量。 4. ZooKeeper可以用于解決分布式數據一致性的問題,常用在數據發布/訂閱、負載均衡、命名服務、集群管理、Master選舉、`分布式鎖`、`分布式配置服務`和分布式隊列等功能中。 **總之:Zookeeper提供分布式協調服務。** &nbsp; ## 理論補充 **CAP理論** CAP 理論指出對于一個分布式計算系統來說,不可能同時滿足以下三點: * **一致性**:Consistency 在分布式環境中,一致性是指數據在多個副本之間能夠保持一致的特性,等同于所有節點訪問`同一份最新的`數據副本。在一致性的需求下,當一個系統在數據一致的狀態下執行更新操作后,應該保證系統的數據仍然處于一致的狀態。 * **可用性**:Availability 每次請求都能獲取到正確的響應,但是不保證獲取的數據為最新數據。 * **分區容錯性**:Partition Tolerance 分布式系統在遇到任何網絡分區故障的時候,仍然需要能夠保證對外提供滿足一致性和可用性的服務,除非是整個網絡環境都發生了故障。 一個分布式系統最多只能同時滿足一致性(Consistency)、可用性(Availability)和分區容錯性(Partition tolerance)這三項中的兩項。 在這三個基本需求中,最多只能同時滿足其中的兩項,P 是必須的,因此只能在 CP 和 AP 中選擇,`zookeeper 保證的是 CP`,更準確講ZooKeeper會實現最終的一致性,但是并不能保證強一致性;對比 spring cloud 系統中的注冊中心 `eruka 實現的是 AP`。 ![img](https://www.runoob.com/wp-content/uploads/2020/09/cap-theorem-diagram.png) &nbsp; **BASE理論** BASE 是 Basically Available(基本可用)、Soft-state(軟狀態) 和 Eventually Consistent(最終一致性) 三個短語的縮寫。 * **基本可用**:在分布式系統出現故障,允許損失部分可用性(服務降級、頁面降級)。 * **軟狀態**:允許分布式系統出現中間狀態。而且中間狀態不影響系統的可用性。這里的中間狀態是指不同的 data replication(數據備份節點)之間的數據更新可以出現延時的最終一致性。 * **最終一致性**:data replications 經過一段時間達到一致性。 BASE 理論是對 CAP 中的一致性和可用性進行一個權衡的結果,理論的核心思想就是:`我們無法做到強一致,但每個應用都可以根據自身的業務特點,采用適當的方式來使系統達到最終一致性。`ZooKeeper可以實現系統的最終一致性。 &nbsp; ## 安裝 ## 安裝 1. Linux的話去[官網](https://zookeeper.apache.org/releases.html)找到最新的穩定版本的下載路徑 :-: ![](https://img.kancloud.cn/67/6f/676f462f7fe264a4ddd015523f4dbacc_1081x666.png) 注意下載下來的要帶有bin命名的才是打包好的。 2. Linux中創建文件夾下載安裝包 ~~~ ?wget https://dlcdn.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz ~~~ 在下載目錄中解壓 ~~~ ?tar -zxvf apache-zookeeper-3.6.3-bin.tar.gz ~~~ 3. 復制配置文件,在安裝目錄的conf目錄下 ~~~ ?cp zoo_camp.cfg zoo.cfg ~~~ zoo.cfg是zookeeper的默認啟動配置文件 3. 配置bin環境 ~~~ ?vim /etc/profile ?? ?# 添加上如下內容 ?export ZOOKEEPER_HOME=/下載目錄/apache-zookeeper-3.6.3-bin ?export PATH=$ZOOKEEPER_HOME/bin:$PATH ? ?# 使其生效 ?source /etc/profile ~~~ 最好是保證JDK在profile中配置了! 4. 打開Zookeeper服務 :-: ![](https://img.kancloud.cn/70/ea/70ea1bbddbf9f845e864acd19f6b83d8_771x89.png) 如果不能正確啟動成功,有很大的可能是JDK的問題,注意查看JDK是否已經配置了環境變量了。 &nbsp; ### 集群搭建 ZooKeeper一般都會搭建集群來使用,當然使用單機也行,但是這樣就不能很好的發揮其高可用的特性了。ZooKeeper需要至少3臺服務器形成一個集群。 1. 準備至少三臺服務器(由于ZooKeeper的Leader選舉至少要過半才能通過,因此ZooKeeper的集群至少要三臺服務器才行)。 2. 在各個服務器中安裝相同的ZooKeeper版本。并修改`/etc/profile`,將ZooKeeper的相關命令添加到環境變量中。同時要確保服務器中至少安裝了JDK1.8+。 :-: ![](https://img.kancloud.cn/2a/d8/2ad86261fe1dbef35620c9b818cb43bb_510x65.png) 3. 修改每臺服務器的ZooKeeper的配置文件,在配置文件的末尾添加上類似如下內容: :-: ![](https://img.kancloud.cn/47/a4/47a43962ef301ca7a83ded18516cb262_459x117.png) 及其書寫格式為: ~~~ ?server.myid=ip:2888:3888 ~~~ 2888集群內各臺機器之間通信使用,3888用于投票選舉時使用。 4. 每臺服務器創建myid文件,需要創建在zoo.cfg配置文件`dataDir`目錄下的;假如這里dataDir=/var/zookeeper,則可以通過如下命令創建myid文件,設置每臺服務器的myid ~~~ ?echo 1 > /tmp/zookeeper/myid ~~~ '1'表示的就是該服務器的myid,需要和配置文件中server.myid配置的相對應。 5. 啟動各臺服務器的zkServer.sh。 ~~~ # 前臺啟動 zkServer.sh start-foreground # 后臺啟動 zkServer.sh start ~~~ 可以使用命令`zkServer.sh status`查看哪臺服務器是Leader節點。 &nbsp; ## 相關元素 1. 架構 ![ZooKeeper的架構](https://atts.w3cschool.cn/attachments/day_161229/201612291344222238.jpg) * Client 客戶端,分布式應用集群中的一個節點,從ZooKeeper服務器訪問信息。客戶端和ZooKeeper服務器之間會維持心跳連接。 * Server 服務器,ZooKeeper集群中的一個節點,為客戶端提供所有的服務。在客戶端連接的時候,客戶端發送確認碼以告知服務器是活躍的。 * Ensemble ZooKeeper服務器組。形成ensemble所需的最小節點數為3。 * Leader Zookeeper是主從集群,和Reids類似。Leader表示中心節點,在集群啟動的時候被選舉。如果集群中Leader服務宕機了,則執行自動選舉過程。注意增刪改只能發送在Leader中,查詢可以發生在其他節點中。 當Leader 節點宕機的時候,官方的壓測給出了大約在200ms左右可以選舉一個新的節點作為leader節點。即從不可用狀態恢復到可用狀態大約需要200ms。 * Follower ZooKeeper集群的節點之一,屬于Leader節點的從節點,可以給客戶端提供查詢功能;每個Follower節點在Leader宕機的時候都有機會被選擇成新的Leader的。 &nbsp; 2. 層次命名空間 下圖描述了用于內存表示的ZooKeeper文件系統的`樹結構`。ZooKeeper節點稱為 **znode** 。每個znode由一個名稱標識,并用路徑(/)序列分隔。 * 在圖中,首先有一個由“/”分隔的znode。在根目錄下,兩個邏輯命名空間 **config** 和 **workers** 。 * **config** 命名空間用于集中式配置管理,**workers** 命名空間用于命名。 * 在 **config** 命名空間下,每個znode最多可存儲1MB的數據。這種結構的主要目的是存儲同步數據并描述znode的元數據。此結構稱為 **ZooKeeper數據模型**。 ![分層命名空間](https://atts.w3cschool.cn/attachments/day_161229/201612291345162031.jpg) Znode兼具文件和目錄兩種特點。既像文件一樣維護著*數據長度、元信息、ACL、時間戳*等數據結構,又像目錄一樣可以作為路徑標識的一部分。每個Znode由三個部分組成: * **stat**:此為狀態信息,描述該Znode版本、權限等信息。 * **data**:與該Znode關聯的數據。 * c**hildren**:該Znode下的節點。 其他信息: * **版本號** - 每個znode都有版本號,這意味著每當與znode相關聯的數據發生變化時,其對應的版本號也會增加。當多個zookeeper客戶端嘗試在同一znode上執行操作時,版本號的使用就很重要。 * **操作控制列表(ACL)** - ACL基本上是訪問znode的認證機制。管理所有znode讀取和寫入操作。 * **時間戳** - 時間戳表示創建和修改znode所經過的時間。通常以毫秒為單位。ZooKeeper從“事務ID"(zxid)標識znode的每個更改。**Zxid** 是唯一的,并且為每個事務保留時間,可以輕松地確定從一個請求到另一個請求所經過的時間。 * **數據長度** - 存儲在znode中的數據總量是數據長度。最多可以存儲1MB的數據。 &nbsp; 3. Znode的類型 Znode分為持久(persistent)節點,順序(sequential)節點和臨時(ephemeral)節點。 * **持久節點** 即使在創建該特定znode的客戶端斷開連接后,持久節點仍然存在。默認情況下,除非另有說明,否則所有znode都是持久的。大小為1MB。 * **臨時節點** 客戶端活躍時,臨時節點就是有效的。當客戶端與ZooKeeper集群的連接斷開時,臨時節點會自動刪除。因此,只有臨時節點不允許有子節點。如果臨時節點被刪除,則下一個合適的節點將填充其位置。臨時節點在leader選舉中起著重要作用。也可以用于Redis中的分布式鎖。 * **順序節點** 順序節點可以是持久的或臨時的。當一個新的znode被創建為一個順序節點時,ZooKeeper通過將10位的序列號附加到原始名稱來設置znode的路徑。 例如,如果將具有路徑 **/myapp** 的znode創建為順序節點,則ZooKeeper會將路徑更改為 **/myapp0000000001** ,并將下一個序列號設置為0000000002。如果兩個順序節點是同時創建的,那么ZooKeeper不會對每個znode使用相同的數字。順序節點在鎖定和同步中起重要作用。 ![](https://img.kancloud.cn/8e/e3/8ee38623b75d56b7d9ef346613161d9a_698x271.png) 4. Sessions(會話) 會話對于ZooKeeper的操作非常重要。會話中的請求按FIFO順序執行。一旦客戶端連接到服務器,將建立會話并向客戶端分配**會話ID** 。 客戶端以特定的時間間隔發送**心跳**以保持會話有效。如果ZooKeeper集合在超過服務器開啟時指定的期間(會話超時)都沒有從客戶端接收到心跳,則它會判定客戶端死機。 會話超時通常以毫秒為單位。當會話由于任何原因結束時,在該會話期間創建的臨時節點也會被刪除。 5. Watches(監視) 監視是一種簡單的機制,使客戶端收到關于ZooKeeper中znode的更改的通知。客戶端可以在讀取特定znode時設置Watches。Watches會向注冊的客戶端發送任何znode(客戶端注冊表)更改的通知。 Znode更改是與znode相關的數據的修改或znode的子項中的更改。只觸發一次watches。如果客戶端想要再次通知,則必須通過另一個讀取操作來完成。當連接會話過期時,客戶端將與服務器斷開連接,相關的watches也將被刪除。 &nbsp; ## 客戶端使用 ### 常用命令 1. 查看目錄下的zNode ~~~ ?ls [-s] [-w] [-R] path ~~~ 2. 創建節點 ~~~ ?create [-s] [-e] path data ?? ?# 例如:創建aabb節點 ?create /aabb "hello world" ~~~ 選項說明: * \-s:創建序列化節點,節點名稱相同時數據不會覆蓋,會自動添加個版本號。可以使每個客戶端都有自己的一個同名節點。序列化數字由leader維護,會一直遞增。可以用于并發的場景中。 例如: ~~~ ?[zk: localhost:2181(CONNECTED) 9] create /aabb -s "01" ?Created /aabb0000000001 ?[zk: localhost:2181(CONNECTED) 10] create /aabb -s "02" ?Created /aabb0000000002 ?[zk: localhost:2181(CONNECTED) 11] ls / ?[aabb0000000001, aabb0000000002, test, zookeeper] ~~~ * \-e:創建臨時節點。 3. 獲取節點的數據 ~~~ ?get [-s] [-w] path ~~~ 選項說明: * \-s:獲取節點的詳細數據,包括元數據 ~~~ ?[zk: localhost:2181(CONNECTED) 15] get -s /test ?hello world ?# data內容 ?cZxid = 0x2 ?ctime = Mon Jan 17 11:05:13 HKT 2022 ?mZxid = 0x2 ?mtime = Mon Jan 17 11:05:13 HKT 2022 ?pZxid = 0x2 ?cversion = 0 ?dataVersion = 0 ?aclVersion = 0 ?ephemeralOwner = 0x0 ?dataLength = 11 ?numChildren = 0 ~~~ cZxid:創建事務id,64位,由Leader節點維護。 mZxid:修改的事務id。 pZxid:最后一個節點創建的事務id。 ephemeralOwner:session id,用于臨時節點。創建節點的時候可以使用-e選項。 * \-w:只獲取data的內容。 &nbsp; ### API使用 1. 導入依賴 ~~~ ?<dependency> ? ? ?<groupId>org.apache.zookeeper</groupId> ? ? ?<artifactId>zookeeper</artifactId> ? ? ?<version>3.6.3</version> ?</dependency> ~~~ 注意要和集群的版本一致。 2. 創建ZooKeeper對象 ~~~ ?final CountDownLatch countDownLatch = new CountDownLatch(1); ?ZooKeeper zk = new ZooKeeper("103.118.42.131:2181", 3000, watchedEvent -> { ? ? ?System.out.println("new zk watch:" + watchedEvent); ? ? ?Watcher.Event.KeeperState state = watchedEvent.getState(); ? ? ?Watcher.Event.EventType type = watchedEvent.getType(); ? ? ?String path = watchedEvent.getPath(); ? ? ?System.out.println("path:" + path); ? ? ?// 連接狀態的監控 ? ? ?switch (state) { ? ? ? ? ?case Unknown: ? ? ? ? ?case NoSyncConnected: ? ? ? ? ? ? ?break; ? ? ? ? ?case Disconnected: ? ? ? ? ? ? ?System.out.println("disconnected..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case SyncConnected: ? ? ? ? ? ? ?System.out.println("SyncConnected..."); ? ? ? ? ? ? ?countDownLatch.countDown(); ? ? ? ? ? ? ?break; ? ? ? ? ?case AuthFailed: ? ? ? ? ? ? ?break; ? ? ? ? ?case ConnectedReadOnly: ? ? ? ? ? ? ?break; ? ? ? ? ?case SaslAuthenticated: ? ? ? ? ? ? ?break; ? ? ? ? ?case Expired: ? ? ? ? ? ? ?break; ? ? ? ? ?case Closed: ? ? ? ? ? ? ?System.out.println("closed..."); ? ? ? ? ? ? ?break; ? ? ? ? ?default: ? ? ? ? ? ? ?break; ? ? } ?? ? ? ?// 節點的相關狀態 ? ? ?switch (type) { ? ? ? ? ?case None: ? ? ? ? ? ? ?break; ? ? ? ? ?case NodeCreated: ? ? ? ? ? ? ?System.out.println("NodeCreated..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case NodeDeleted: ? ? ? ? ? ? ?System.out.println("NodeDeleted..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case NodeDataChanged: ? ? ? ? ? ? ?System.out.println("NodeDataChanged..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case NodeChildrenChanged: ? ? ? ? ? ? ?System.out.println("NodeChildrenChanged..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case DataWatchRemoved: ? ? ? ? ? ? ?System.out.println("DataWatchRemoved..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case ChildWatchRemoved: ? ? ? ? ? ? ?System.out.println("ChildWatchRemoved..."); ? ? ? ? ? ? ?break; ? ? ? ? ?case PersistentWatchRemoved: ? ? ? ? ? ? ?System.out.println("PersistentWatchRemoved..."); ? ? ? ? ? ? ?break; ? ? ? ? ?default: ? ? ? ? ? ? ?break; ? ? } ?}); ?countDownLatch.await(); ~~~ 由于是異步連接的,所以要用CountDownLatch進行等待。 2. 創建節點 ~~~ ?String path = zk.create("/test1", "hello world".getBytes(StandardCharsets.UTF_8), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); ~~~ 3. 設置數據 ~~~ ?Stat stat = zk.setData(path, "hello test".getBytes(StandardCharsets.UTF_8), -1); ~~~ \-1表示自動匹配數據的版本,否則要和集群中的znode節點一致,不然的話會報錯。 4. 獲取數據,同時設置watch ~~~ ?byte[] data = zk.getData("/test", new Watcher() { ? ? ?@Override ? ? ?public void process(WatchedEvent watchedEvent) { ? ? ? ? ?System.out.println("getData watch:" + watchedEvent); ? ? ? ? ?try { ? ? ? ? ? ? ?//可以重新注冊回調 ? ? ? ? ? ? ?zk.getData("/test", this, new Stat()); ? ? ? ? } catch (KeeperException e) { ? ? ? ? ? ? ?e.printStackTrace(); ? ? ? ? } catch (InterruptedException e) { ? ? ? ? ? ? ?e.printStackTrace(); ? ? ? ? } ? ? } ?}, new Stat()); ~~~ 在getData中設置的Watch會在給znode設置數據或者刪除節點的時候觸發,注意一個watch只能觸發一次,所以一般都會重復設置。 異步回調方式: ~~~ ?zk.getData(path, false, new AsyncCallback.DataCallback() { ? ? ?@Override ? ? ?public void processResult(int rc, String path, Object ctx, byte[] data, Stat stat) { ? ? ? ? ?System.out.println("rc:" + rc); ? ? ? ? ?System.out.println("-------async call back----------"); ? ? ? ? ?System.out.println(ctx.toString()); ? ? ? ? ?System.out.println(new String(data)); ? ? ? ? ?countDownLatch1.countDown(); ? ? } ?}, "abc"); ~~~ 這種方式會在讀取到數據的時候觸發。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看