一文讀懂GaussDB(for Mongo)的計算存儲分離架構
1.摘要
GaussDB(for Mongo)是華為云自主研發兼容MongoDB4.0接口的文檔數據庫。基于共享存儲的存算分離架構,對于傳統MongoDB社區版有如下優勢:
秒級添加Secondary節點(相比社區版Mongo小時級添加Secondary節點)
基于WAL復制, Secondary節點無寫IO,從根本上解決社區版Seconary節點Oplog脫節問題
Primary/Seconary無任何IO交互,Secondary節點個數理論無上限, 支持百萬OPS的讀事務能力
LSMTree Compaction 計算/IO卸載到Compaction統一調度池,集中管理,不浪費用戶讀寫IO
基于共享存儲,Chunk分裂/遷移動作不引起真實IO,只更新路由元數據,秒級分裂/均衡
2.GaussDB(for Mongo)技術架構
1)容忍更多Shard宕機
與社區版MongoDB的`Share-Nothing`模式不同的是,GaussDB(for Mongo)采用`Share-Storage`架構,計算存儲分離。集群模式下,N個Shard節點,可以容忍N-1個Shard宕機。
某個Shard節點宕機后,其負責的數據由于存在于共享的存儲池中,因此不需要物理拷貝數據,只需要修改元數據路由信息,即可被其他分片節點接管。
2)更快的分裂與均衡能力
此外,由于Chunk數據在存儲池中,Chunk的分裂與均衡不涉及到數據拷貝,可以做到分鐘級分裂與擴容,分裂與擴容對用戶的影響也遠比社區版MongoDB小。
3)百萬級讀OPS能力
GaussDB(for Mongo)副本集模式下,Primary/Secondary節點之間共享同一份數據庫文件。Secondary節點只復制Primary節點的WriteAheadLog以及LSMTree的結構變更信息,并應用到內存中。Secondary節點沒有LSMTree的Compaction和Flush任務,因此對用戶的讀業務影響很小。
此外,由于`Share-Storage`的架構優勢,添加Secondary節點并不需要拷貝數據,添加Secondary節點的動作可以秒級完成。而Primary/Secondary之間只傳遞元數據變更,不傳遞WriteAheadLog,因此Secondary節點的個數即使變多,也不影響Primary節點的寫性能。Secondary節點可以水平擴展,支撐百萬級的讀OPS。
4)主節點IO卸載
LSMTree的寫壓力來源于三部分:
用戶的業務寫入導致的Memtable Flush
后臺SST文件Compaction
WAL的持續寫入
根據線上業務的實際測算,三者的IO資源消耗占比為: 1:10:1。后臺的SST文件Compaction占了絕大部分IO帶寬,通過將Compaction任務集中化管理,從計算池卸載到存儲池,進一步減少了用戶計算節點的CPU和IO資源消耗。
5)GaussDB(for Mongo) 只讀節點設計
傳統社區版MongoDB副本集基于Oplog做數據復制,只讀節點需要鏡像主節點的所有寫IO操作。GaussDB(for Mongo) 的只讀節點和主節點共享同一份底層數據庫文件(LSMTree的SST文件),只讀節點并不自己生成SST文件。
隨著業務數據的寫入,Compaction的不斷執行,LSMTree的當前版本(包含哪些SST文件)不斷更新,LSMTree的元數據更新(增刪SST文件的記錄)被同步到只讀節點執行。
RocksDB中,數據的變更被持久化到WAL里,元數據的變更(增刪文件的操作, 叫做VersionEdit)被持久化到Mainifest里。RocksDB的數據和元數據是分開的,WAL流和VersionEdit流是并行的,沒有嚴格的先后順序。為了保證只讀節點和主節點完全一致的事件回放順序,WAL和VersionEdit流必須要合并成一個流,在雙流合并后,通過LSN就可以為每個事件(WAL的寫操作/VersionEdit)定序。
基于WAL+VersionEdit復制,而不基于Oplog復制
共享文件(sst/wal)的生命周期管理由主節點負責sst文件和wal的文件的生命周期由主節點負責。RocksDB中,SST文件通過層級的引用計數來維持不被刪除。如下圖,RocksDB的每個游標會維持SuperVersion,如下圖中的S0,S1,S2。每個SuperVersion會引用一個Version,一個Version代表LSMTree在不斷變形(通過增刪SST文件變形)的過程中,某個時間點的形狀,最新的Version就代表LSMTree當前的形狀。
在GaussDB(for Mongo)中,主節點會記錄所有只讀節點在使用的Version,并為這些Version增加引用計數從而維持SST文件的生命周期。對于WAL,主節點會記錄所有只讀節點中最老的LSN(`oldestLsn`),最老的LSN來自于復制最慢的只讀節點。并刪除比oldestLsn還舊的WAL文件。
元數據變更通知,無論是oldestLsn還是只讀節點的當前在用的活躍的Version,都需要及時推進,這些元數據的變更是通過主從節點的定期心跳上報到主節點上的。主節點利用心跳數據對垃圾版本與WAL做清理。如下圖所示,在經歷一次心跳后,主節點發現Secondary0的Version0和Secondary1的Version0不再使用。刪除這兩個Version后,SST0的引用計數為0,表示SST0可以被刪除。OldestLsn也從100推進到了250,可以清理掉250之前的WAL。
只讀節點的memtable的釋放:主節點的Memtable不會實時Flush為SST文件。如果只讀節點不處理主節點的Memtable的話,只讀節點的數據就不是實時的,且存在數據一致性問題。只讀節點通過回放WAL到內存的Memtable中,來覆蓋SST文件與主節點的Memtable的Gap。上文介紹了只讀節點是不往共享存儲寫入數據的, 所以只讀節點上的 Memtable 最后的結局一定是被丟棄掉。但什么時候丟棄這個 Memtable 就是一個問題。過早的丟棄,會造成SST文件與Memtable之間的數據不連續,存在Gap,過晚的丟棄會造成內存的浪費。只有當只讀節點識別到SST的數據已經完全能夠Cover某個Memtable時,這個Memtable才可以被丟棄。
GaussDB(for Mongo)的只讀節點在每次應用VersionEdit后,檢查所有SST中的最大的LSN與Memtable的最小的LSN的關系,來決定是否要丟棄某個Memtable。
內存元數據的反向更新:傳統的復制,數據流從Oplog來,走一遍完整的數據庫Server層CRUD接口,再落到引擎層。這種邏輯和主節點上業務的寫入邏輯是一致的,因此Server層的一些內存元數據結構,在這個過程中就自然而然的得到更新了。但是當采用基于WAL的復制后,整個WritePath并不經過只讀節點的Server層。因此Server層的內存元數據更新,就是一個很大的挑戰。在這里,只讀節點對每一條WAL做分析,如果WAL的內容會影響Mongo內存元數據,就會reload對應的元數據模塊。
3.總結
GaussDB(for Mongo) 基于Share-Storage架構,實現秒級Chunk分裂與均衡,對業務影響更小,水平擴展速度更快,能容忍更多節點宕機。只讀節點功能,實現了一份數據多計算節點共用的功能。極大的提升了存儲的利用效率,提高了計算節點的讀取數據能力。為了讓副本節點具有持續的讀擴展能力,整個只讀方案采用元數據的同步模式,在不降低主節點負載的情況下,極大的提升了整個系統的讀數據的處理能力。為3節點,5節點,乃至于15節點以上的副本集的工作提供了可能。
數據庫
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。