誰說 Facebook 棄用 Cassandra?相反 Facebook 擁有全世界最大的單個 Cassandra 叢集部署,而且他們對 Cassandra 做了很多性能優化,包括 Cassandra on RocksDB 以提升 Cassandra 的響應時間。
在 Instagram (Instagram是Facebook公司旗下一款免費提供線上圖檔及視訊分享的社交應用軟體,于2010年10月釋出。)上,我們擁有世界上最大的 Apache Cassandra 資料庫部署。我們在 2012 年開始使用 Cassandra 取代 Redis ,在生産環境中支撐欺詐檢測,Feed 和 Direct inbox 等産品。起初我們在 AWS 環境中運作了 Cassandra 叢集,但是當 Instagram 架構發生變化時,我們将 Cassandra 叢集遷移到Facebook 的基礎架構中。我們對 Cassandra 的可靠性和可用性有了非常好的體驗,但是在讀取資料延遲方面我們覺得他需要改進。
去年 Instagram 的 Cassandra 團隊開始着手這個項目,以顯着減少 Cassandra 的讀取延遲,我們稱之為 Rocksandra。 在這篇文章中,我将描述該項目的動機,我們克服的挑戰以及内部和公共雲環境中的性能名額。
動機
在 Instagram 上,我們大量使用 Apache Cassandra 作為通用鍵值存儲服務。Instagram 的大多數 Cassandra 請求都是線上的,是以為了向數億 Instagram 使用者提供可靠且響應迅速的使用者體驗,我們有很高的 SLA 要求。
Instagram 可靠性 SLA 保持為5-9s,這意味着在任何給定時間,請求失敗率應小于0.001%。為了提高性能,我們主動監控不同 Cassandra 叢集的吞吐量和延遲,尤其是 P99 讀取延遲。
下面的圖顯示了一個生産 Cassandra 叢集的用戶端延遲。藍線是平均讀取延遲(5ms),橙色線是 P99 讀取延遲(在25ms到60ms的範圍内)。
經過調查,我們發現 JVM 垃圾收集器(GC)對延遲峰值做出了很大貢獻。我們定義了一個稱為 GC 停滞百分比的度量,用于衡量Cassandra 伺服器執行 GC(Young Gen GC)并且無法響應用戶端請求的時間百分比。結果顯示我們生産 Cassandra 伺服器上的 GC 停滞百分比。在最低請求流量時間視窗期間為1.25%,在高峰時段可能高達2.5%。
這表明 Cassandra 伺服器執行個體在垃圾收集上花費 2.5% 的運作時間,而這段時間是不能服務用戶端請求的。GC 開銷顯然對我們的 P99 延遲有很大影響,是以如果我們可以降低 GC 停頓百分比,我們将能夠顯着降低P99延遲。
解決辦法
Apache Cassandra 是一個分布式資料庫,并用 Java 編寫了基于 LSM 樹的存儲引擎。 我們發現存儲引擎中的元件,如memtable,壓縮,讀/寫路徑等,在 Java 堆中建立了很多對象,并為 JVM 産生了大量開銷。為了減少來自存儲引擎的GC影響,我們考慮了不同的方法,并最終決定開發C++存儲引擎來替換現有的引擎。
我們不想從頭開始建構新的存儲引擎,是以我們決定在 RocksDB 之上建構新的存儲引擎。
RocksDB 是一個開源的,高性能嵌入式鍵值資料庫。它是用 C++ 編寫的,并為 C++,C 和 Java 提供官方 API。RocksDB 針對性能進行了優化,尤其是在 SSD 等快速存儲方面。它在業界廣泛用作 MySQL,mongoDB 和其他流行資料庫的存儲引擎。
挑戰
在 RocksDB 上實作新的存儲引擎時,我們克服了三個主要挑戰:
第一個挑戰是 Cassandra 還沒有可插拔的存儲引擎架構,這意味着現有的存儲引擎與資料庫中的其他元件耦合在一起。為了在大規模重構和快速疊代之間找到平衡點,我們定義了一個新的存儲引擎 API,包括最常見的讀/寫和流接口。這樣我們就可以在 API 後面實作新的存儲引擎,并将其注入 Cassandra 内部的相關代碼路徑。
其次,Cassandra 支援豐富的資料類型和表模式,而 RocksDB 提供純粹的鍵值接口。我們仔細定義了編碼/解碼算法,使得我們使用 RocksDB 資料結構來建構 Cassandra 資料模型,并支援與原始 Cassandra 相同的查詢語義。
第三個挑戰是關于 streaming。 Streaming 在 Cassandra 這樣的分布式資料庫是很重要元件。每當我們從 Cassandra 叢集加入或删除節點時,Cassandra 都需要在不同節點之間傳輸資料以平衡叢集中的負載。現有的 streaming 實作基于目前存儲引擎的。是以,我們必須将它們彼此分離,建立一個抽象層,并使用 RocksDB API 重新實作 streaming 傳輸。對于高 streaming 吞吐量,我們現在首先将資料流式傳輸到臨時 sst 檔案,然後使用 RocksDB 提取檔案 API 立即将它們批量加載到 RocksDB 執行個體中。
性能名額
經過大約一年的開發和測試,我們已經完成了第一個版本的實作,并成功将其推廣到 Instagram 中的幾個生産 Cassandra 叢集。在我們的一個生産叢集中,P99讀取延遲從60ms降至20ms。 我們還觀察到該叢集上的GC停滞從2.5%下降到0.3%,這減少了10倍!
我們還想驗證 Rocksandra 在公共雲環境中是否表現良好。我們在 AWS 環境中使用三個 i3.8 xlarge EC2 執行個體部署了一個 Cassandra 叢集,每個執行個體具有 32 個核,244GB記憶體和 帶有4個nvme閃存盤的raid0。
我們使用 NDBench 作為基準測試,并使用這個架構中的預設表模式:
TABLE emp (
emp_uname text PRIMARY KEY,
emp_dept text,
emp_first text,
emp_last text
)
我們将 250M 6KB 行資料預先加載到資料庫中(每個伺服器在磁盤上存儲大約500GB的資料)。我們在 NDBench 中配置了128個讀用戶端和128個寫用戶端。
我們測試了不同的工作負載并測量了 avg/P99/P999 讀/寫延遲。如我們所見,Rocksandra 提供了更低且一緻的讀/寫延遲。
我們還測試了一個隻讀工作負載并觀察到,在類似的P99讀取延遲(2ms)下,Rocksandra 讀取吞吐量提高了10倍(Rocksandra為300K/s,C * 3.0為 30K/s)。
未來工作
我們開源了 Rocksandra 代碼庫和
基準架構,您可以從Github下載下傳(
https://github.com/Instagram/cassandra/tree/rocks_3.0),在您自己的環境中試用!
下一步,我們正在積極開發更多 C 功能,如二級索引,修複等。我們還在開發一個 C
可插拔存儲引擎架構,以便将我們的工作貢獻給Apache Cassandra 社群。
本文翻譯自:
https://instagram-engineering.com/open-sourcing-a-10x-reduction-in-apache-cassandra-tail-latency-d64f86b43589微信公衆号和釘釘群交流
為了營造一個開放的 Cassandra 技術交流,我們建立了微信公衆号和釘釘群,為廣大使用者提供專業的技術分享及問答,定期在國内開展線下技術沙龍,專家技術直播,歡迎大家加入。
微信公衆号:
釘釘群
釘釘群入群連結:
https://c.tb.cn/F3.ZRTY0o