ZooKeeper 避坑指南: ZooKeeper 3.6.4 版本 BUG 導致的資料不一致問題
*作者:子葵*
## 背景
ZooKeeper 作為分散式系統的後設資料中心,對外服務的資料一致性需要得到很好的保證,但是一些老版本的 ZooKeeper 在一些情況下可能無法保證資料的一致性,導致依賴 ZooKeeper 的系統出現異常。
某使用者使用 3.4.6 版本 ZooKeeper 做任務排程,ZooKeeper 例項的 tps 和 qps 都比較高,事務日誌產生的速率很快,即使此使用者配置了自動清理的引數,但是自動清理的最小間隔還是趕不上資料產生的速度,導致磁碟爆滿。
在此使用者清理了舊日誌之後,重啟節點,部分業務機器就報出 NodeExist,NoNode 的異常,並且報錯只集中在部分機器,此次異常導致使用者任務排程系統出現任務重複排程以及任務丟失問題,產生重大損失。
## 原因分析
仔細檢查了這些客戶端發現這些客戶端都連線在同一臺 ZooKeeper 節點上,透過 zkCli 手動排查節點上的資料,對比其他未清理磁碟的 ZooKeeper 節點,清理了磁碟的 ZooKeeper 節點中的資料和其他節點具有差異,此時確定此節點由於一些原因出現了資料不一致問題,導致連線到此節點的客戶端讀到了髒資料。
但是排查日誌,沒有發現異常日誌。由於此節點之前清理過日誌,並且重啟過,磁碟上的資料被重新載入過,因此懷疑是 ZooKeeper 在啟動載入資料的過程中出現了一些異常情況。透過分析 ZooKeeper 啟動中載入資料的程式碼,繼續排查具體原因。
public long restore(DataTree dt, Map<Long, Integer> sessions, PlayBackListener listener) throws IOException { snapLog.deserialize(dt, sessions); FileTxnLog txnLog = new FileTxnLog(dataDir); TxnIterator itr = txnLog.read(dt.lastProcessedZxid+1); long highestZxid = dt.lastProcessedZxid; TxnHeader hdr; try { while (true) { ... try { processTransaction(hdr,dt,sessions, itr.getTxn()); } catch(KeeperException.NoNodeException e) { throw new IOException("Failed to process transaction type: " + hdr.getType() + " error: " + e.getMessage(), e); ... return highestZxid; }
此處是 ZooKeeper 載入磁碟資料的程式碼,此方法的主要作用是,首先將磁碟中的 snapshot 檔案載入進記憶體,初始化 ZooKeeper 記憶體中的資料結構,之後將載入事務日誌應用日誌中對資料的修改,最終還原磁碟中資料的狀態。
但是在 3.4.6 版本的程式碼中 snapLog.deserialize(dt, sessions);這行載入 snapshot 檔案的程式碼有一個返回值,此處沒有進行返回值校驗,導致在 ZooKeeper 本身找不到有效的 snapshot 檔案的情況下還是會繼續載入事務日誌,從而導致 ZooKeeper 在空資料的狀態下直接應用事務日誌,最終導致此節點的資料和其他節點的資料不一致。
此問題已經在 ZooKeeper 社群有對應的 ***issue***,在載入 snapshot 的檔案列表為空的情況下,此問題已經得到了修復,但是由於磁碟爆滿導致的 snapshot 檔案不完整的其他的一些特殊情況下,此問題依然存在。解決此問題還需要從磁碟使用的角度解決。
> ****issue:****
>
> *<*
## 解決方案
為了避免 ZooKeeper 節點的磁碟被快速打滿,可以增加磁碟的容量,配合 ZooKeeper 本身的清理機制,可以在一定範圍內的 tps 下避免磁碟被寫滿的情景,但是增大磁碟容量會帶來顯著的使用成本的提高,並且即使磁碟容量提高了,也可能因為 ZooKeeper 本身清理機制不及時清理,導致磁碟被打滿,最終需要透過人工的方式進行磁碟清理,運維起來很複雜,耗費人力物力,並且叢集穩定性得不到顯著提升。
MSE ZooKeeper 提供 ZooKeeper 例項的全託管,MSE ZooKeeper 例項的磁碟使用對使用者完全透明,使用者無需擔心磁碟爆滿問題,以及磁碟使用過程中的複雜運維。MSE ZooKeeper 透過定時清理,觸發使用閾值清理等手段保證 ZooKeeper 例項在使用過程中磁碟始終處於安全水位,避免由於磁碟問題導致的資料不一致,例項不可用等問題。
MSE ZooKeeper 預設整合 Promethus 監控,提供豐富的指標資訊,並且針對寫多的場景,MSE ZooKeeper 提供 TopN 大盤,能夠快速看到業務熱點資料,以及高 tps 的客戶端情況,能夠透過這些統計資料快速定位業務使用過程中的問題。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69953029/viewspace-2949707/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- ZooKeeper 避坑實踐:如何調優 jute.maxbuffer
- ZooKeeper 05 - ZooKeeper 叢集的腦裂問題(Split Brain)AI
- flink上下游並行度不一致導致的資料亂序問題並行
- BUG—Nuget包版本不一致導致程式行為與預期不符
- 避坑指南:關於SPDK問題分析過程
- Apple Search Ads避坑指南:核心問題解析答疑APP
- minikube與kubectl版本不一致問題
- Zookeeper入門指南
- H2 資料庫避坑指南資料庫
- ZooKeeper分散式專題(二) -- zookeeper應用場景及資料模型分散式模型
- 聊聊Zookeeper的資料一致性解決方案
- 【專案中遇到的zookeeper的問題】
- 問題定位 | XtraBackup 8.0 資料重建避坑事件始末事件
- Canal v1.1.4版本避坑指南
- 坑爹的Python陷阱(避坑指南)Python
- 面試官:Zookeeper怎麼解決讀寫、雙寫併發不一致問題,以及共享鎖的實現原理?面試
- 【爬坑】.Net編譯環境導致的問題編譯
- 橫趟!面試中遇到的 ZooKeeper 問題面試
- 大資料技術 - Zookeeper大資料
- 《大資料: ZooKeeper 資料同步流程》大資料
- ZooKeeper-3.4.6叢集選舉Bug踩坑與恢復記錄
- JavaScript作用域面試題避坑指南JavaScript面試題
- 搞懂 ZooKeeper 叢集的資料同步
- 上雲避坑指南
- .NET AsyncLocal 避坑指南
- 小心避坑:MySQL分頁時出現的資料重複問題MySql
- zookeeper面試題面試題
- [日常填坑系列]CAP食用指南-版本引用問題
- zookeeper叢集奇偶數節點問題
- 三年之久的 etcd3 資料不一致 bug 分析
- 詳解 ZooKeeper 資料持久化持久化
- Zookeeper 如何保證分散式系統資料一致性分散式
- linux安裝zookeeper中各種坑Linux
- Scala版本與Java版本不匹配導致的找不到主類問題Java
- 【zookeeper】zookeeper分散式鎖分散式
- Redis 安裝避坑指南Redis
- eBPF編寫避坑指南eBPF
- React Hooks使用避坑指南ReactHook