本文做者:HelloGitHub-老荀html
本文是 HelloZooKeeper 系列的最後一篇文章,接下來主要聊聊面試中若是被問到 ZooKeeper 的問題如何回答,也能夠看成學完本系列的測試。node
準備好了嗎?面試開始嘍~「首發於 HelloGitHub 公衆號」面試
終於來到重頭戲了,本小節我會從網上找到一些關於 ZK 的面試題進行剖析講解,而且站在面試官的基礎上分析考點,相信看完這一節,出去面試再碰到 ZK 相關的問題你便能披荊斬棘、所向披靡!算法
我先給你們模擬一個面試的場景:數據庫
面試官:我看你簡歷上用過 ZK,能給我介紹下嗎?你是怎麼理解 ZK 的做用呢?apache
(若是你把百度百科中的定義背給他聽,我只能說 666,千萬別這樣,會被別人當成傻子。)編程
我:個人理解 ZK 是一個脫離於應用的第三方進程,相似的數據庫,消息隊列,Redis 等都是扮演這個角色,擁有必定的數據存儲和查詢能力,可讓咱們在如今都是分佈式部署的應用之間「傳遞」數據,其次 ZK 支持的回調通知,讓應用能夠在一些業務場景中感知到數據的變化並及時做出相應的反應。最後,ZK 自己也支持集羣部署具備高可用的特色,是一個可靠的第三方中間件。緩存
面試官:嗯,你剛剛提到了回調通知,能仔細跟我聊聊 ZK 是怎麼去實現的嗎?安全
我:各類編程語言的客戶端都會對這個回調通知進行抽象,一般須要開發者聲明一個 callback 的對象,在 Java 的客戶端中這個接口是 Watcher
,ZK 服務端提供了一些方法,好比 getData
、exists
或者最新版本中的 addWatch
均可以用來向 ZK 註冊回調通知,而向服務端發送的回調通知,只會告訴服務端我當前的這個路徑須要被通知,服務端得知後,會在內存中記錄下來,路徑和客戶端之間的關係,客戶端本身也須要記錄下來,路徑和具體回調的關係。當被訂閱的路徑發生事件的時候,各類增刪改吧,服務端就會從內存中的記錄去查看有沒有須要通知的客戶端,有的話會發送一個通知的請求給客戶端,客戶端收到通知後,就會從本地的記錄中取出對應的回調對象去執行 callback 方法!markdown
(實際狀況,我以爲面試官可能不會讓你一直說下去,應該是互相聊的一個狀態)
面試官:嗯,說得挺詳細,那你剛剛提到的 getData
、exists
、 addWatch
三種註冊有什麼區別嗎?
我:getData
、exists
以及 getChildren
註冊的通知都是一次性的,當服務端通知過一次後,就會刪除內存中的記錄,以後若是仍然須要通知的話,客戶端就要去繼續註冊,而 addWatch
註冊的回調通知是永久性的,只須要註冊一次能夠一直被通知。
面試官:嗯好,你剛剛還提到了 ZK 有必定的數據存儲能力,你能說說 ZK 是怎麼保存和整理數據的嗎?
我:ZK 的數據體如今兩部分。
面試官:哦?哪兩部分?
我:內存中和磁盤上。
面試官:那你先說說內存裏 ZK 是怎麼存儲數據
我:從邏輯上來說,ZK 內存中的數據實際上是一個樹形結構,從 /
根節點開始,逐級向下用 /
分割,每個節點下面還能夠有多個子節點,就相似於 Unix 中的目錄結構,但在實際中,ZK 是使用一個 HashMap 去存儲整個樹形結構的數據的,key 是對應的全路徑字符串,value 則是一個節點對象,包含了節點的各類信息。
面試官:能說說你以爲爲何要這麼設計嗎?
(其實我以爲通常面試官不會這麼問,如下回答也是我我的的猜測)
我:首先 HashMap 查詢速度很快,是 Java 標準庫中一個很是重要的數據結構,在許多地方都有用到。ZK 自己並不須要排序或者是範圍求值的操做,因此 HashMap 徹底能夠知足查詢的需求。至於爲何邏輯上要設計成樹形結構,父子節點,這個多是由於這個結構和 Unix 文件系統很像,很是便於理解以及基於路徑進行數據的分類,並且最新的 ZK 中有一些功能是依賴了父子遞歸這個特性的(好比 addWatch
),若是是普通的 key-value 是沒法知足的。
面試官:嗯好,那你再說說磁盤上 ZK 是怎麼存儲數據的呢?
我:ZK 在磁盤上規定了兩種文件類型,一種是 log 文件,一種是 snapshot。log 文件是增量記錄,負責對每個寫請求進行保存,snapshot 文件是全量記錄,是對內存的快照。
面試官:ZK 是怎麼保證內存中的數據和磁盤中的數據的一致性呢?
我:真正的強一致性,ZK 沒法保證。對於每一次的寫請求,ZK 是採起先記錄磁盤再修改內存的,因此保證了若是出現意外的話,優先記錄磁盤能夠儘量的保證數據的完整。若是 ZK 是正常退出的話,也會強制刷磁盤文件和生成 snapshot,保證了一致性,但若是是非正常退出的話,極端狀況下的一部分數據是會丟失的。
面試官:你剛剛也提到了 ZK 自己也能夠集羣部署的?能多聊一點嗎?
我:ZK 的配置文件 zoo.cfg
中能夠配置其餘節點的信息,各個節點經過 dataDir
目錄下的 myid
文件進行區分,不一樣節點之間能夠相互通訊,客戶端連上集羣中的任意一個節點均可以進行通訊。
面試官:ZK 集羣中有幾種不一樣的角色?你知道嗎?
我:有 Leader、Follower、Observer 三種角色。
面試官:說說他們之間的區別吧
我:集羣中有且只能有一個 Leader,Leader 負責對整個集羣的寫請求事務進行提交,在一個集羣選出 Leader 以前是沒法對外提供服務的。Follower 和 Observer 都只能處理讀請求,區別是 Follower 有投票權能夠參與 Leader 的競選,Observer 沒法參與 Leader 的競選。
面試官:那你能夠跟我講講,選舉 Leader 依靠哪些信息嗎?
我:每個節點都會維護三個最重要的信息:epoch、zxid、myid。epoch 表明選舉的輪次,優先比較,若是相同則繼續比較下一級。zxid 表明本節點處理過的最大事務 ID,越大表明當前節點經手的寫請求越多,知道的也就越多,第二優先級比較,若是還相同則比較 myid,myid 整個集羣中不能重複,因此最終必定能分出勝負。勝利的節點當選 Leader。
(準確的說,epoch 和 zxid 是一個字段,一個記錄在高 32 位,一個記錄在低 32 位)
面試官:不一樣節點之間怎麼通訊呢?怎麼去進行選舉?
我:每個 ZK 節點在啓動的時候,會經過讀取配置文件中的集羣信息,與其餘節點創建 Socket 鏈接,集羣間的通訊就是經過這個 Socket。每一個節點選舉的時候都把本身認爲的候選人信息廣播出去,同時也接收來自其餘節點的候選人信息,經過比較後,失敗的一方會更改本身的候選人信息並從新進行廣播,反覆直到某一個節點獲得半數以上投票,選舉就完成了。
面試官:不一樣的節點角色,在處理讀寫請求上有什麼不一樣嗎?你先聊聊 Leader 吧
我:好滴,Leader 做爲集羣中的老大,負責對收到的寫請求發起提案 PROPOSAL,告訴其餘節點當前收到一個寫請求,其餘節點收到後,會在本地進行歸檔,其實就是寫入文件輸出流,完畢後會發送一個 ACK 給 Leader,Leader 統計到半數以上的 ACK 以後會再次發送給其餘節點一個 COMMIT,其餘節點收到 COMMIT 以後就能夠修改內存數據了。讀請求的話不須要提案直接查詢內存中的數據返回便可。
面試官:那 Follower 或 Observer 呢?
我:他們收到讀請求是同樣的,直接返回本地的內存數據便可。可是寫請求的話,會將當前請求轉發給 Leader,而後由 Leader 去處理,就和以前的流程是同樣的。
面試官:不一樣的請求 ZK 是如何保證順序呢?
我:這個順序的保證最終是落實在一個先進先出的隊列,優先進該隊列的請求會被先處理,因此能保證順序。
面試官:不一樣的客戶端的請求怎麼保證順序呢?A 先發送了一個建立節點,在該請求返回以前,B 發送了一個查詢該節點,B 會阻塞到 A 執行完畢再查詢嗎?仍是直接返回查詢不到節點?
我:B 會直接返回查不到。不一樣的客戶端之間的順序 ZK 不保證,緣由是在底層 ZK 是經過一個 Map 去分別放置不一樣的客戶端的請求的,不一樣的客戶端的 key 是不同的,而這個 Map 的 value 則是我剛剛提到的先進先出的隊列。因此只有同一個客戶端的請求能被順序執行,不一樣的客戶端是沒法保證的。
面試官:能說說不一樣的客戶端的 key 是什麼嗎?怎麼保證不一樣。
我:每個客戶端在鏈接至 ZK 後會被分配一個 sessionId,這個 sessionId 是經過當前時間戳、節點的 myid 和一個遞增特性生成的一個 long 類型字段,能夠保證不會重複。
面試官:說到 session,你知道 ZK 的會話是怎麼維持的嗎?
我:你問的是客戶端和服務端之間的會話嗎?
面試官:是的,你能跟我說說嗎?
我:每個客戶端在鏈接 ZK 的時候會同時上報本身的超時時間,加上剛剛的 sessionId,ZK 的服務端會在本地維護一個映射關係,經過計算能夠計算出該 sessionId 的超時時間,而且 ZK 本身也有一個 tickTime
的配置,經過一個算法能夠將不一樣客戶端不一樣超時間都映射到相同間隔的時間點上,再將這個超時時間和 sessionId 關係存起來。
面試官:映射到相同的時間點上有什麼好處嗎?
我:這樣服務端在啓動後,後臺會有一個線程,經過這個統一的時間間隔,取出 session 過時的客戶端,向他們發送會話過時的消息,極大的節約了性能。
面試官:客戶端是怎麼去更新會話的超時時間呢?
我:首先客戶端的每次操做都會刷新這個超時時間,其次客戶端必須設計一個 PING 的操做,用於在客戶端空閒的時候主動去刷新會話超時時間,防止過時。
面試官:除了客戶端和服務端之間的會話,還有別的嗎?
我:服務端和服務端之間也有心跳,並且服務端的心跳是由 Leader 主動發起的,向其餘節點發送 PING 請求,而其餘節點收到 PING 後,須要把本地的會話信息一併發送給 Leader。
編不下去了,上面一些題具備我強烈的主觀偏好性,我以爲若是面試官是個菜雞的話,這些問題大部分都問不出來,因此重點是不在於我怎麼回答,而是當你對背後的原理了然於胸時,天然是神擋殺神,佛擋殺佛。
我說說我認爲比較重要的幾個特性:
最後經過一個模擬面試回答了一下我認爲 ZK 中比較有特色的面試問題,若是你們對面試問題還有什麼疑問記得留言給我噢~必須給大家安排上!
我大部分題目是網上直接搜的,網址在這裏 ZooKeeper面試題(2020最新版)可是過濾了一些太 low 的題目。
我上面說了 Leader 在接受到寫請求後,會發起提案,而後等待其餘節點的 ACK,這個 ACK 是要求半數以上經過才能繼續下去的,因此能收到半數以上的 ACK 說明集羣中的一半以上都已經完成了本地磁盤的歸檔,天然是保證了主從之間的數據同步。
我以前的文章中有介紹如今 ZK 中有 7 種節點類型,關於新節點的原理我還沒來得及講,因此他若是這麼問了你能夠很官方的回答他:
他通常後面會接着問二者的區別,臨時節點會隨着客戶端的會話斷開而自動刪除,原理就是在建立臨時節點的時候,服務端會維護一個 sessionId 和它對應的臨時節點路徑列表,當關閉會話時,把這個列表裏的路徑都拿出來一一刪除便可。而順序節點的區別就在於 ZK 會自動爲路徑加上數字的後綴,僅此而已。
併發建立時,順序節點怎麼保證後綴數字惟一呢?
ZK 的請求是放入隊列裏一個個處理的,因此其實並無所謂的併發,前一個請求處理完再處理下一個請求,天然就能保證後綴數字的惟一性了。
ZK 將權限分爲兩大類,兩大類又能繼續細分:
chroot 是 ZK 設計給客戶端的命名空間隔離,做爲不一樣客戶端的根節點,由客戶端去維護,總的來講就是發送請求以前把 chroot 的路徑拼接上,再去請求服務端。chroot 對於服務端是透明的,徹底不知道的。
Learner 和 Leader 之間同步數據是一個比較漫長和複雜的過程,總的來講能夠大體分爲如下步驟:
託你們的福,我把 ZK 的源碼所有(爆肝)瀏覽了一遍,找到了至少 99% 的配置選項,ZK 的配置大體能夠分爲 3 種:
zoo.cfg
配置文件中的參數命令行參數不多,並且沒有對應的配置名稱,這裏我簡單介紹下:
單機版只支持兩種形式的命令行傳參
2181 /your/zk/data/path
zoo.cfg
的路徑,例如:/your/zoocfg/path
集羣版更簡單隻支持 zoo.cfg
的路徑一個參數
我仔細查看源碼的時候發現有些配置實際做用時須要計算又或者是一魚兩吃,被多個地方使用,因此很難一步到位的講清楚,因此下面的介紹僅供參考,配置項加星號(*)的是我將來打算開篇講解的。
配置項 | 默認值(單位) | 介紹 |
---|---|---|
dataDir | /tmp/zookeeper | 存放 snapshot、myid 文件路徑 |
clientPort | 2181 | 監聽客戶端請求端口 |
tickTime | 2000(毫秒) | 影響客戶端會話檢查間隔、服務端之間心跳間隔 |
syncLimit | 5 | tickTime * syncLimit 決定了服務端心跳超時時間 |
initLimit | 10 | tickTime * initLimit 決定了 ACK 的超時時間 |
dataLogDir | 和 dataDir 一致 | 存放 log 文件路徑 |
minSessionTimeout | tickTime * 2 | 客戶端的超時時間最小值 |
maxSessionTimeout | tickTime * 20 | 客戶端的超時時間最大值 |
electionAlg | 3 | 選舉算法(1,2 已被廢棄) |
localSessionsEnabled* | false | 啓用本地會話 |
localSessionsUpgradingEnabled* | false | 本地會話能夠升級成全局會話 |
clientPortAddress | - | 客戶端的 host 要求,不配置的話能夠接受任意發向 2181 的請求 |
secureClientPort | - | SSL 安全端口號 |
secureClientPortAddress | - | SSL 安全 host |
observerMasterPort* | - | 使 Observer 經過 Follower 去了解集羣中的選舉狀況 |
clientPortListenBacklog | 50 | TCP 服務端用於臨時存放已完成三次握手的請求的隊列的最大長度 |
maxClientCnxns | 60 | 客戶端最大鏈接數 |
connectToLearnerMasterLimit | 0 | 決定了 Follower 鏈接 Leader 的超時時間 |
quorumListenOnAllIPs | false | 服務端是否接受來自任意 IP 地址的請求 |
peerType | - | 選項 observer / participant,決定節點角色 |
syncEnabled | true | Learner 是否須要本地持久化文件 |
dynamicConfigFile* | - | 動態配置路徑 |
autopurge.snapRetainCount | 3 | 保留多少個最新的 snapshot 文件 |
autopurge.purgeInterval | 0(小時) | 間隔多久進行一次 snapshot 的清理 |
standaloneEnabled | true | 是否容許單機模式啓動 |
reconfigEnabled* | false | 是否容許動態配置 |
sslQuorum | false | 集羣間是否使用 SSL 通訊 |
portUnification | false | 是否容許不安全鏈接 |
sslQuorumReloadCertFiles | false | 啓用密鑰更新時自動加載 |
quorum.auth.enableSasl | false | 啓用集羣間 SASL 鑑權 |
quorum.auth.serverRequireSasl | false | |
quorum.auth.learnerRequireSasl | false | |
quorum.auth.learner.saslLoginContext | QuorumLearner | |
quorum.auth.server.saslLoginContext | QuorumServer | |
quorum.auth.kerberos.servicePrincipal | zkquorum/localhost | |
quorum.cnxn.threads.size | 20 | 集羣間異步創建鏈接線程池最大線程數 |
jvm.pause.info-threshold.ms | 1000(毫秒) | INFO 輸出暫停統計閾值 |
jvm.pause.warn-threshold.ms | 10000(毫秒) | WARN 輸出暫停統計閾值 |
jvm.pause.sleep.time.ms | 500(毫秒) | JVM 暫停統計線程 sleep 間隔 |
jvm.pause.monitor* | false | 是否啓用 JVM 暫停統計 |
metricsProvider.className* | DefaultMetricsProvider(全路徑) | 統計實現類路徑 |
multiAddress.enabled | false | |
multiAddress.reachabilityCheckTimeoutMs | 1000(毫秒) | |
multiAddress.reachabilityCheckEnabled | true | |
(以開頭)server.* | 集羣配置 | |
(以開頭)group* | 分組配置 | |
(以開頭)weight* | 權重 | |
(以開頭)metricsProvider.* | 自定義的統計配置 |
以上就是 3.6.2 中 zoo.cfg
全部的官方配置選項了
Java 程序想要指定環境變量有兩種方法:
-DpropertyKey=propertyValue
便可zoo.cfg
中直接指定(指定時不須要寫 zookeeper.
的前綴)。只要不是在上面 2.2 中 ZK 本身定義的配置項裏,ZK 啓動的時候讀取這些配置會自動幫他們添加 zookeeper.
前綴並加入當前環境變量中若是該配置是 follower.nodelay
,就只能用第一種方式添加環境變量了。
讓咱們也來看看 ZK 本身定義了哪些環境變量配置吧
配置項 | 默認值 | 配置 |
---|---|---|
zookeeper.server.realm* | - | 客戶端配置 |
zookeeper.clientCnxnSocket | ClientCnxnSocketNIO(全路徑) | 客戶端配置,通訊的實現類 |
zookeeper.client.secure | true | 客戶端配置 |
zookeeper.request.timeout | 0 | 客戶端配置,異步 API 超時時間 |
zookeeper.server.principal | - | 客戶端配置 |
zookeeper.sasl.client.username | zookeeper | 客戶端配置 |
zookeeper.sasl.client.canonicalize.hostname | true | 客戶端配置 |
zookeeper.disableAutoWatchReset | false | 客戶端配置,會話超時自動清空 watcher |
zookeeper.sasl.clientconfig | - | |
zookeeper.sasl.client | true | 啓用 SASL |
zookeeper.ssl(.quorum).authProvider | x509 | SSL 實現類,加 quorum 的是服務端的配置,下同 |
zookeeper.ssl(.quorum).protocol | TLSv1.2 | |
zookeeper.ssl(.quorum).enabledProtocols | - | |
zookeeper.ssl(.quorum).ciphersuites | 根據不一樣的 jvm 版本 | |
zookeeper.ssl(.quorum).keyStore.location | - | |
zookeeper.ssl(.quorum).keyStore.password | - | |
zookeeper.ssl(.quorum).keyStore.type | - | |
zookeeper.ssl(.quorum).trustStore.location | - | |
zookeeper.ssl(.quorum).trustStore.password | - | |
zookeeper.ssl(.quorum).trustStore.type | - | |
zookeeper.ssl(.quorum).context.supplier.class | - | |
zookeeper.ssl(.quorum).hostnameVerification | true | |
zookeeper.ssl(.quorum).crl | false | |
zookeeper.ssl(.quorum).ocsp | false | |
zookeeper.ssl(.quorum).clientAuth | - | |
zookeeper.ssl(.quorum).handshakeDetectionTimeoutMillis | 5000(毫秒) | |
zookeeper.kinit | /usr/bin/kinit | |
zookeeper.jmx.log4j.disable | false | 禁用 jmx log4j |
zookeeper.admin.enableServer* | true | 是否啓用 Admin Server |
zookeeper.admin.serverAddress* | 0.0.0.0 | |
zookeeper.admin.serverPort* | 8080 | |
zookeeper.admin.idleTimeout* | 30000 | |
zookeeper.admin.commandURL* | /commands | |
zookeeper.admin.httpVersion* | 11 | |
zookeeper.admin.portUnification | false | |
zookeeper.DigestAuthenticationProvider.superDigest | - | 管理員帳號密碼 |
zookeeper.ensembleAuthName | - | |
zookeeper.requireKerberosConfig | - | |
zookeeper.security.auth_to_local | DEFAULT | |
(以開頭)zookeeper.authProvider.* | - | 自定義 scheme 校驗規則 |
zookeeper.letAnySaslUserDoX | - | |
zookeeper.SASLAuthenticationProvider.superPassword | - | |
zookeeper.kerberos.removeHostFromPrincipal | - | |
zookeeper.kerberos.removeRealmFromPrincipal | - | |
zookeeper.X509AuthenticationProvider.superUser | - | |
zookeeper.4lw.commands.whitelist* | - | 四字命令白名單 |
zookeeper.preAllocSize | 65536 * 1024 | |
zookeeper.forceSync | yes | |
zookeeper.fsync.warningthresholdms | 1000(毫秒) | fsync 告警閾值 |
zookeeper.txnLogSizeLimitInKb | -1(KB) | log 文件大小 |
zookeeper.datadir.autocreate | true | data 目錄自動建立 |
zookeeper.db.autocreate | true | |
zookeeper.snapshot.trust.empty | false | 不信任空的 snapshot 文件 |
zookeeper.snapshot.compression.method | 空字符串 | snapshot 文件壓縮實現 |
zookeeper.commitProcessor.numWorkerThreads | CPU 核心數 | |
zookeeper.commitProcessor.shutdownTimeout | 5000(毫秒) | |
zookeeper.commitProcessor.maxReadBatchSize | -1 | |
zookeeper.commitProcessor.maxCommitBatchSize | 1 | |
zookeeper.fastleader.minNotificationInterval | 200(毫秒) | 收集選票超時時間(初始) |
zookeeper.fastleader.maxNotificationInterval | 60000(毫秒) | 收集選票超時時間(最大) |
zookeeper.leader.maxTimeToWaitForEpoch | -1 | |
zookeeper.leader.ackLoggingFrequency | 1000 | |
zookeeper.testingonly.initialZxid | - | 初始化 zxid,僅供測試! |
zookeeper.leaderConnectDelayDuringRetryMs | 100 | Leaner 鏈接 Leader 超時時間 |
follower.nodelay | true | 設置 TCP no delay |
zookeeper.forceSnapshotSync | false | Learner 強制使用 snapshot 和 Leader 進行同步 |
zookeeper.leader.maxConcurrentSnapSyncs | 10 | |
zookeeper.leader.maxConcurrentDiffSyncs | 100 | |
zookeeper.observer.reconnectDelayMs | 0(毫秒) | Observer 延遲重連至 Leader |
zookeeper.observer.election.DelayMs | 200(毫秒) | Observer 延遲開始選舉 |
zookeeper.observerMaster.sizeLimit | 32 * 1024 * 1024 | |
zookeeper.electionPortBindRetry | 3 | 選舉端口鏈接重試次數 |
zookeeper.tcpKeepAlive | false | Socket keep alive 設置 |
zookeeper.cnxTimeout | 5000(毫秒) | Socket 超時時間 |
zookeeper.multiAddress.enabled | false | |
zookeeper.multiAddress.reachabilityCheckTimeoutMs | 1000(毫秒) | |
zookeeper.multiAddress.reachabilityCheckEnabled | true | |
zookeeper.quorumCnxnTimeoutMs | -1 | |
zookeeper.observer.syncEnabled | true | Observer 是否須要本地歸檔 |
zookeeper.bitHashCacheSize | 10 | 位圖初始緩存大小 |
zookeeper.messageTracker.BufferSize | 10 | |
zookeeper.messageTracker.Enabled | false | |
zookeeper.pathStats.slotCapacity | 60 | |
zookeeper.pathStats.slotDuration | 15 | |
zookeeper.pathStats.maxDepth | 6 | |
zookeeper.pathStats.sampleRate | 0.1 | |
zookeeper.pathStats.initialDelay | 5 | |
zookeeper.pathStats.delay | 5 | |
zookeeper.pathStats.topPathMax | 20 | |
zookeeper.pathStats.enabled | false | |
zookeeper.watcherCleanThreshold | 1000 | |
zookeeper.watcherCleanIntervalInSeconds | 600 | |
zookeeper.watcherCleanThreadsNum | 2 | |
zookeeper.maxInProcessingDeadWatchers | -1 | |
zookeeper.watchManagerName | WatchManager(全路徑) | |
zookeeper.connection_throttle_tokens | 0 | |
zookeeper.connection_throttle_fill_time | 1 | |
zookeeper.connection_throttle_fill_count | 1 | |
zookeeper.connection_throttle_freeze_time | -1 | |
zookeeper.connection_throttle_drop_increase | 0.02 | |
zookeeper.connection_throttle_drop_decrease | 0.002 | |
zookeeper.connection_throttle_decrease_ratio | 0 | |
zookeeper.connection_throttle_weight_enabled | false | |
zookeeper.connection_throttle_global_session_weight | 3 | |
zookeeper.connection_throttle_local_session_weight | 1 | |
zookeeper.connection_throttle_renew_session_weight | 2 | |
zookeeper.extendedTypesEnabled* | false | 是否啓用 TTL 節點類型 |
zookeeper.emulate353TTLNodes* | false | 是否兼容 3.5.3 的 TTL |
zookeeper.client.portUnification | false | |
zookeeper.netty.server.outstandingHandshake.limit | -1 | |
zookeeper.netty.advancedFlowControl.enabled | false | |
zookeeper.nio.sessionlessCnxnTimeout | 10000(毫秒) | |
zookeeper.nio.numSelectorThreads | CPU 核心數 / 2 再開方 | |
zookeeper.nio.numWorkerThreads | CPU 核心數 * 2 | |
zookeeper.nio.directBufferBytes | 64 * 1024(字節) | |
zookeeper.nio.shutdownTimeout | 5000(毫秒) | |
zookeeper.request_stale_connection_check | true | |
zookeeper.request_stale_latency_check | false | |
zookeeper.request_throttler.shutdownTimeout | 10000(毫秒) | |
zookeeper.request_throttle_max_requests | 0 | |
zookeeper.request_throttle_stall_time | 100 | |
zookeeper.request_throttle_drop_stale | true | |
zookeeper.serverCnxnFactory | NIOServerCnxnFactory(全路徑) | |
zookeeper.maxCnxns | 0 | |
zookeeper.snapshotSizeFactor | 0.33 | |
zookeeper.commitLogCount | 500 | |
zookeeper.sasl.serverconfig | Server | |
zookeeper.globalOutstandingLimit | 1000 | |
zookeeper.enableEagerACLCheck | false | |
zookeeper.skipACL | no | |
zookeeper.allowSaslFailedClients | false | |
zookeeper.sessionRequireClientSASLAuth | false | |
zookeeper.digest.enabled | true | |
zookeeper.closeSessionTxn.enabled | true | |
zookeeper.flushDelay | 0 | |
zookeeper.maxWriteQueuePollTime | zookeeper.flushDelay / 3 | |
zookeeper.maxBatchSize | 1000 | |
zookeeper.intBufferStartingSizeBytes | 1024 | |
zookeeper.maxResponseCacheSize | 400 | |
zookeeper.maxGetChildrenResponseCacheSize | 400 | |
zookeeper.snapCount | 100000 | |
zookeeper.snapSizeLimitInKb | 4194304(千字節) | |
zookeeper.largeRequestMaxBytes | 100 * 1024 * 1024 | |
zookeeper.largeRequestThreshold | -1 | |
zookeeper.superUser | - | |
zookeeper.audit.enable | false | 是否啓用 audit 日誌 |
zookeeper.audit.impl.class | Log4jAuditLogger(全路徑) | audit 日誌功能實現類 |
ZK 的配置仍是不少的,有些我這裏 TODO 了,之後有機會和你們詳細介紹下~並且至關一部分的配置 ZK 官方的文檔中已經給出瞭解釋,能夠查看 ZK 3.6.2 配置文檔。
我這裏還要吐槽下,ZK 中有些配置是用 true 或者 false,有些使用 yes 或者 no,明顯是兩個(波)人開發的,這種不該該作一個統一嗎?yes 或 no 真的不少餘...
感謝大家能看到這裏,陪伴這個系列從開始到如今!這個項目從有想法立項到以後跟蛋蛋溝通,再到正式開始編寫,到最後我寫下這段結語,大概經歷了三個多月(大家看到的時候應該是更晚),如今回頭再看以前寫的東西,感慨頗深。
(截圖來自-B 站何同窗的視頻)
若是以我本身的自控能力,這玩意本身搞,搞着搞着可能就涼了,在此感謝蛋蛋給予個人幫助和鼓勵。關於 ZK 個人確以前有研究過一段時間,可是以如今的眼光看,當時的研究其實也就是皮毛而已(可能如今也仍是),不少東西是我此次整理時現學的,收穫很是多,最直觀的感覺就是,我之後出去面試不會再懼怕 ZK 相關的問題了。
感謝你們這 3 個月的陪伴,本系列終結嘍!若是還有什麼想學的開源框架和技術能夠留言告訴咱們,後續繼續爲你們安排免費的乾貨教程。
最最後,來個大大的贊吧!
關注 HelloGitHub 公衆號 收到第一時間的更新。
還有更多開源項目的介紹和寶藏項目等待你的發掘。