Netflix AI團隊通過按ID拆分Cassandra分區,將寬分區讀取延遲從秒級降至毫秒級
Netflix工程師詳細介紹了他們如何在TimeSeries Abstraction中處理Apache Cassandra的寬分區。兩種方法協同工作:時間切片重新分區在表級別調整未來分區,而動態分區則在讀取路徑上按TimeSeries ID檢測並拆分過大的分區。檢測通過字節計數和Kafka進行,拆分經過校驗和驗證,布隆過濾器將讀取路由到並行子分區。平均讀取延遲從秒級降至低雙位數毫秒,500MB以上的分區仍保持可用。
Netflix工程團隊發佈了一種處理Apache Cassandra中寬分區的方法。該研究工作針對Netflix的TimeSeries Abstraction,這是一個用於時間事件數據的平台。
TimeSeries Abstraction以毫秒級延遲攝入和查詢PB級的時間事件數據,底層使用Apache Cassandra 4.x。時序數據按標識符和時間範圍組織成分區,隨着事件累積,分區可能變得“寬”。動態重新分區將過大的分區異步地拆分為較小的子分區,應用程序繼續查詢相同的邏輯分區,而存儲佈局透明地演變。
對於大多數數據集,平均讀取延遲保持在個位數毫秒。但當分區過寬時,尾部讀取延遲上升到秒級,可能導致讀取超時、垃圾回收暫停、高CPU利用率和線程排隊。TimeSeries服務器還處理非常高的讀取吞吐量,使問題更加複雜。Netflix團隊希望找到比單純擴展集羣更智能的解決方案。
TimeSeries將數據集分解為離散的時間塊:時間切片、時間桶和事件桶。當創建命名空間時,用户指定預期的工作負載特徵,供應管道運行蒙特卡洛模擬來選擇基礎設施和分區配置。這種方法在三種情況下不足:工作負載未知或估計不準確;工作負載隨時間和需求變化;存在數據異常值(少數ID收到更多事件)。離散時間切片為前兩種情況提供了自然解決方案,但手動調整數千個數據集不可持續。
解決方案1:時間切片重新分區。Cassandra提供nodetool tablehistograms等內省API。後台工作線程監視這些直方圖,並在分區大小偏離目標密度時計算調整因子。該密度通常設置為2 MiB到10 MiB。例如,如果過度分區導致高讀取放大,工作線程會更新未來時間切片採用更寬的間隔。這減少了讀取延遲和超時,但僅在大多數表需要重新分區時有效。
解決方案2:按ID動態分區。這是一個異步管道,按TimeSeries ID拆分寬分區。分為三個階段:檢測、規劃和拆分、讀取服務。檢測在讀取路徑上進行:每次讀取跟蹤分區的字節數,當超過閾值時,服務器向Kafka發送事件。優先拆分不可變分區。規劃階段讀取整個分區以計算準確拆分計劃,支持檢查點。拆分子任務使用事件桶分區策略,將更多事件桶分配到同一時間桶。驗證通過比較拆分前後的校驗和進行,僅當匹配時拆分才算完成。
讀取路徑使用布隆過濾器(微秒級響應)檢查已拆分的分區鍵,命中時查詢路由元數據,將請求路由到較小的子分區。原始寬分區永不刪除,作為安全回退。Netflix還通過Data Bridge Spark作業進行離線驗證。分階段推出,包括影子比較模式。
兩種解決方案的比較:粒度、觸發條件、影響範圍、核心機制、檢測信號、最佳適用場景等均有不同。用例包括長期用户活動日誌、設備遙測、過度供應的新數據集和延遲敏感儀表板。
結果:平均讀取延遲從秒級降至低雙位數毫秒,尾部延遲從幾秒降至約200毫秒,讀取超時減少,CPU利用率降低,集羣更穩定。對於500MB以上的極端寬行,服務仍能分頁查詢並保持可用。未來工作包括拆分可變寬分區和重新處理失敗的拆分。