Redis vs Tendis:冷熱混合儲存版架構揭秘
作者:jingjunli,騰訊 IEG 後臺開發工程師
Redis 作為高效能快取被廣泛應用到各個業務, 比如遊戲的排行榜, 分散式鎖等場景。經過在 IEG 的長期運營, 我們也遇到 Redis 一些痛點問題, 比如記憶體佔用高, 資料可靠性差, 業務維護快取和儲存的一致性繁瑣。由 騰訊互娛 CROS DBA 團隊 & 騰訊雲資料庫團隊聯合研發的 Tendis 推出了: 快取版 、 混合儲存版 和 儲存版 三種不同產品形態, 針對不同的業務需求, 本文主要介紹 混合儲存版 的整體架構, 並且詳細揭秘內部的原理。
導語
本文首先介紹騰訊 IEG 運營 Redis 遇到的一些痛點問題, 然後介紹由 騰訊互娛 CROS DBA 團隊 & 騰訊雲資料庫團隊聯合研發的 Tendis 的三種不同的產品形態。最後重點介紹冷熱混合儲存版的架構, 並且重點介紹各個元件的功能特性。
背景介紹
Redis 有哪些痛點 ?
在使用的過程中, 主要遇到以下一些痛點問題:
記憶體成本高
業務不同階段對 QPS 要求不同 比如遊戲業務, 剛上線的新遊戲特別火爆, 為了支援上千萬同時線上, 需要不斷的進行擴容增加機器。運營一段時間後, 遊戲玩家可能變少, 訪問頻率(QPS)沒那麼高, 依然佔用大量機器, 維護成本很高。 需要為 Fork 預留記憶體 Redis 儲存全量資料時, 需要 Fork 一個程式。Linux 的 fork 系統呼叫基於 Copy On Write 機制, 如果在此期間 Redis 有大量的寫操作, 父子程式就需要各自維護一份記憶體。因此部署 Redis 的機器往往需要預留一半的記憶體。
Tendis 是什麼 ?
Tendis 是集騰訊眾多海量 KV 儲存優勢於一身的 Redis 儲存解決方案, 並 100% 相容 Redis 協議和 Redis4.0 所有資料模型。作為一個高可用、高效能的分散式 KV 儲存資料庫, 從訪問時延、持久化需求、整體成本等不同維度的考量, Tendis 推出了 快取版 、 混合儲存版 和 儲存版 三種不同產品形態,並將儲存版開源。感興趣的小夥伴 可以去 Github 關注我們的專案: Tencent/Tendis
Tendis 快取版適用於對延遲要求特別敏感, 並且對 QPS 要求很高的業務。基於社群 Redis 4.0 版本進行定製開發。
Tendis 儲存版適用於大容量, 延遲不敏感型業務, 資料全部儲存在 磁碟, 適合溫冷資料的儲存。Tendis 儲存版是騰訊互娛 CROS DBA 團隊 & 騰訊雲資料庫團隊 自主設計和研發的開源分散式高效能 KV 儲存系統。另外在 可靠性、複製機制、併發控制、gossip 實現以及資料搬遷等做了大量的最佳化, 並且解決了一些 Redis cluster 比較棘手的問題。完全相容 Redis 協議, 並使用 RocksDB 作為底層儲存引擎。
Tendis 冷熱混合儲存版冷熱混合儲存 綜合了快取版和儲存版的優點, 快取層存放熱資料, 全量資料存放在儲存層。這既保證了熱資料的訪問效能,同時保證了全量資料的可靠性,同時熱資料支援自動降冷。
Tendis 冷熱混合儲存版 整體架構
Tendis 冷熱混合儲存版主要由 Proxy 、快取層 Redis、 儲存層 Tendis 儲存版 和 同步層 Redis-sync 組成, 其中每個元件的功能如下:
Proxy 元件: 負責對客戶端請求進行路由分發,將不同的 Key 的命令分發到正確的分片,同時 Proxy 還負責了部分監控資料的採集,以及高危命令線上禁用等功能。
快取層 Redis Cluster: 快取層 Redis 基於 社群 Redis 4.0 進行開發。Redis 具有以下功能: 1) 版本控制 2) 自動將 冷資料從快取層中淘汰, 將熱資料從儲存層載入到快取層; 3) 使用 Cuckoo Filter 表示全量 Keys, 防止快取穿透; 4) 基於 RDB+AOF 擴縮容方式, 擴縮容更加高效便捷。
儲存層 Tendis Cluster: Tendis 儲存版 是騰訊基於 RocksDB 自研的 相容 Redis 協議的 KV 儲存引擎, 該引擎已經在騰訊集團內部運營多年, 效能和穩定性得到了充分的驗證。在混合儲存系統中主要負責全量資料的儲存和讀取, 以及資料備份, 增量日誌備份等功能。
同步層 Redis-sync: 1) 並行資料匯入 儲存層 Tendis
; 2) 服務無狀態, 故障重新拉起; 3) 資料自動路由。
Tendis 冷熱混合儲存的一些重要特性介紹:
快取層 Redis Cluster
和儲存層 Tendis Cluster
分別進行擴縮容, 叢集自治管理等。冷資料自動降冷, 降低記憶體成本; 熱資料自動快取, 降低訪問延遲
快取層 Redis Cluster
冷熱混合儲存快取層 Redis 在社群版的基礎上增加了以下功能:
版本控制 冷熱資料互動 Cuckoo Filter 避免快取穿透 智慧淘汰演算法 基於 RDB+AOF 擴縮容
下面分別對這幾個特性進行詳細的講解。
版本控制
首先基於社群版 Redis 改動是版本控制。我們為每個 Key 和 每條 Aof 增加一個 Version , 並且 Version 是單調遞增的。在每次更新/新增一個 Key 後, 將當前節點的 Version 賦值給 Key 和 Value, 然後對全域性的 Version++; 如下所示, 在 redisObject 中新增 64bits, 其中 48bits 用於版本控制。
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount;
/* for hybrid storage */
unsigned flag:4; /* OBJ_FLAG_... */
unsigned reserved:4;
unsigned counter:8; /* for cold-data-cache-policy */
unsigned long long revision:REVISION_BITS; /* for value version */
void *ptr;
} robj;
引入版本控制主要帶來以下優勢:
增量 RDB
社群版 Redis 主備在斷線重連後, 如果 slave 傳送的 psync_offset 對應的資料不在當前的 Master 的 repl_backlog 中, 則主備需要重新進行全量同步。再引入 Version 之後, slave 斷線重連, 給 Master 傳送 帶 Version 的
PSYNC replid psync_offset version
命令。如果出現上述情況, Master 將大於等於 Version 的資料生成增量 RDB, 發給 Slave, 進而解決需要增量, 同步比較慢的問題。
Aof 的冪等
如果同步層 Redis-sync 出現網路瞬斷(短暫的和快取層或者儲存層斷開), 作為一個無狀態的同步元件, Redis-sync 會重新拉取未同步到 Tendis 的增量資料, 重新傳送給 Tendis。每條 Aof 都具有一個 Version, Tendis 在執行的時候僅會執行比當前 Version 大的 Aof, 避免 aof 執行多次導致的資料不一致。
冷熱資料互動
冷資料的恢復指當使用者訪問的 Key 不在快取層, 需要將資料從儲存層重新載入到快取層。資料恢復這裡是快取層直接和儲存層直接互動, 當冷 Keys 訪問的請求比較大, 資料恢復很容易成為瓶頸, 因此為每個 Tendis 節點建立一個連線池, 專門負責與這個 Tendis 節點進行冷熱資料恢復。
使用者訪問一個 Key 的具體流程如下:
首先判斷 Key 是否在快取層, 如果快取層存在, 則執行命令; 如果快取層不存在, 查詢 Cuckoo Filter, 判斷 Key 是否有可能在儲存層; 如果 Key 可能在儲存層, 則向儲存層傳送 dumpx dbid key withttl
命令嘗試從儲存層獲取資料, 並且阻塞當前請求的客戶端;儲存層收到 dumpx , 如果 Key 在儲存層, 則向快取層返回 RESTOREEX dbid key ttl value
; 如果 Key 不在儲存層(Cuckoo Filter 的誤判), 則向快取層返回DUMPXERROR key
;儲存層收到 RESTOREEX 或者 DUMPXERROR 後, 將冷資料恢復。然後就可以喚醒阻塞的客戶端, 執行客戶端的請求。
Key 降冷 與 Cuckoo Filter
這裡主要講解混合儲存從 1:1 版的快取層快取全量 Keys, 到 N:M 版的快取層將 Key 和 Value 同時驅逐的演進, 以及我們引入 Cuckoo Filter 避免快取穿透, 同時節省大量記憶體。
Key 降冷的背景介紹2020 年 6 月份上線的 1:1 版的冷熱混合儲存, 快取層 Redis 儲存全量的 Keys 和熱 Values(All Keys + Hot values), 儲存層 Tendis 儲存全量的 Keys 和 Values(All Keys + All values)。在上線執行了一段時間後, 發現全量 Keys 的記憶體開銷特別大, 冷熱混合的收益並不明顯。為了進一步釋放記憶體空間, 提高快取的效率, 我們放棄了 Redis 快取全量 Keys 的方案, 驅逐的時候將 key 和 Value 都從快取層淘汰。
Cuckoo Filter 解決快取擊穿和快取穿透如果快取層不儲存全量的 Keys, 就會出現快取擊穿和快取穿透的問題。為了解決這一問題, 快取層引入 Cuckoo Filter 表示全量的 keys 。我們需要一個支援刪除、可動態伸縮並且空間利用率高的 Membership Query 結構, 經過我們的調研和對比分析, 最終選擇
Dynamic Cuckoo Filter
。Dynamic Cuckoo Filter 實現專案初期參考了 RedisBloom 中 Cuckoo Filter 的實現, 在開發的過程中也遇到了一些坑, RedisBloom 實現的 Cuckoo Filter 在刪除的時候會出現誤刪, 最終給 RedisBloom 提 PR(Fix Cuckoo filter compact cause deleted by mistake #260) 修復了問題。
Key 降冷的收益最終採用將 Key 和 Value 同時從快取層淘汰, 降低記憶體的收益很大。比如現網的一個業務, 總共有 6620 W 個 Keys , 在快取全量 Keys 的時候 佔用 18408 MB 的記憶體, 在 Key 降冷後 僅僅佔用 593MB 。
智慧淘汰/載入策略
作為冷熱混合儲存系統, 熱資料在快取層, 全量資料在儲存層。關鍵的問題是淘汰和載入策略, 這裡直接影響快取的效率, 細分主要有兩點: 1) 當快取層記憶體滿時, 選擇哪些資料淘汰; 2) 當使用者訪問儲存層的資料時, 是否需要將其放入快取層。
首先介紹混合儲存的淘汰策略, 主要有以下兩個淘汰策略:
maxmemory-policy 當快取層 Redis 記憶體使用到達 maxmemory, 系統將按照 maxmemory-policy 的記憶體策略將 Key/Value 從快取層驅逐, 釋放記憶體空間。(驅逐是指將 Key/Value 從快取層中淘汰掉, 儲存層 和 快取層的 Cuckoo Filter 依然存在該 Key; ) value-eviction-policy 如果配置 value-eviction-policy, 後臺會定期將使用者 N 天未訪問的 Key/Value 被驅逐出記憶體;
快取載入策略 為了避免快取汙染的問題(比如類似 Scan 的訪問, 遍歷儲存層的資料, 將快取層真正的熱資料淘汰, 從而造成了快取效率低下) 。我們實現快取載入策略: 僅僅將規定時間內訪問頻率超過某個閾值的資料載入到快取中, 這裡的時間和閾值都是可配置的。
基於 RDB+AOF 擴縮容
社群版 Redis 的擴容流程:
社群版 Redis 擴容存在的一些問題:
importing 和 migrating 的設定不是原子的
先設定目標節點 slot 為 importing 狀態, 再設定源節點的 slot 為 migrating 狀態。如果反過來, 由於兩次操作非原子: 源節點設定為 migrating , 目標節點還未設定 migrating 狀態, 請求在這兩個節點間反覆 Move 。
搬遷以 Key 為粒度, 效率較低
Migrate 命令每次搬遷一個或者多個 Keys, 將整個 Slot 搬遷到目標節點需要多次網路互動。
大 Key 問題
由於 Migrate 命令是同步命令, 在搬遷過程中是不能處理其他使用者請求的, 因此可能會影響業務。(延遲時間波動較大)
由於社群版 Redis 存在的上述問題, 我們實現了基於 RDB+Aof 的擴縮容方式, 大致流程如下:
管控新增新節點, 規劃待搬遷 slots; 管控端向目標節點下發 slot 同步命令: cluster slotsync beginSlot endSlot [[beginSlot endSlot]...]
目標節點向源節點傳送 sync [slot ...]
, 命令請求同步 slot 資料源節點生成指定 slot 資料的一致性快照全量資料(RDB), 並將其傳送給目標節點 源節點開始持續傳送增量資料(Aof) 管控端定位獲取源節點和目標節點的落後值 (diff_bytes), 如果落後值在指定的閾值內, 管控端向目標節點傳送 cluster slotfailover
(流程類似 Redis 的 cluster failover, 首先阻塞源節點寫入, 然後等待目標節點和源節點的落後值為 0, 最後將 搬遷的 slots 歸屬目標節點)
同步層 Redis-sync
同步層 Redis-sync 模擬 Redis Slave 的行為, 接收 RDB 和 Aof, 然後並行地匯入到儲存層 Tendis。同步層主要需要解決以下問題:
併發地匯入到儲存層 Tendis, 如何保證時序正確 ? 特殊命令的處理, 比如 FLUSHALL/FLUSHDB/SWAPDB/SELECT/MULTI 等 ? 作為一個無狀態的同步元件, 如何保證故障後, 資料斷點續傳 ? 快取層和儲存層 分別進行擴縮容, 如何將請求路由到正確的 Tendis 節點 ?
為了解決上述的三個問題, 我們實現了下面的功能:
Slot 內序列, Slot 間並行 針對問題 1, Redis-sync 中採用與 Redis 相同的計算 Slot 的演算法, 解析到具體的命令後, 根據 Key 所屬的 slot, 將其放到對應的 佇列中( slot%QueueSize )。因此同一個 Slot 的資料是序列寫入, 不同 slot 的資料可以並行寫入, 不會出現時序錯亂的行為。 串並轉換 針對問題 2, Redis-sync 會在並行和序列模式之間進行轉換。比如收到 FLUSHDB 命令, 這是需要將 FLUSHDB 命令 前的命令都執行完, 再執行 FLUSHDB 命令。 定期上報 針對問題 3, Redis-sync 會定期將已傳送給儲存層的 aof 的 Version 持久化到 儲存層。如何 Redis-sync 故障, 首先從 儲存層獲取上次已傳送的位置, 然後向對應的 Redis 節點傳送 psync, 請求同步。 資料自動路由 針對問題 4, Redis-sync 會定期從儲存層獲取 Slot
到Tendis 節點
的對映關係, 並且維護這些 Tendis 節點的連線池。請求從 快取層到達, 然後計算請求所屬的 slot, 然後傳送到正確的 Tendis 節點。
儲存層 Tendis Cluster
Tendis 是相容 Redis 核心資料結構與協議的分散式高效能 KV 資料庫, 主要具有以下特性:
相容 Redis 協議 完全相容 redis 協議,支援 redis 主要資料結構和介面,相容大部分原生 Redis 命令。 持久化儲存 使用 rocksdb 作為儲存引擎,所有資料以特定格式儲存在 rocksdb 中,最大支援 PB 級儲存。 去中心化架構 類似於 redis cluster 的分散式實現,所有節點透過 gossip 協議通訊,可指定 hashtag 來控制資料分佈和訪問,使用和運維成本極低。 水平擴充套件 叢集支援增刪節點,並且資料可以按照 slot 在任意兩節點之間遷移,擴容和縮容過程中對應用運維人員透明,支援擴充套件至 1000 個節點。 故障自動切換 自動檢測故障節點,當故障發生後,slave 會自動提升為 master 繼續對外提供服務。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559354/viewspace-2768822/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Shopee ClickHouse 冷熱資料分離儲存架構與實踐架構
- 阿里雲 Redis 混合儲存版上線阿里Redis
- TiDB 冷熱儲存分離解決方案TiDB
- Redis儲存結構以及儲存格式Redis
- [譯] 熱的 Vs 冷的 Observables
- redis 儲存結構原理 2Redis
- ElasticSearch實戰系列十: ElasticSearch冷熱分離架構Elasticsearch架構
- c# 冷儲存示例C#
- 二、儲存架構演變架構
- VSAN儲存結構解析+儲存資料恢復案例資料恢復
- 物件儲存 vs 檔案儲存 vs 塊儲存,選哪個?物件
- Curve 檔案儲存在 Elasticsearch 冷熱資料儲存中的應用實踐Elasticsearch
- 聊一聊Redis熱點key儲存問題Redis
- bs/cs混合架構架構
- 淘寶圖片儲存系統架構架構
- 架構師,儲存災備挑戰架構
- 架構與思維:如何應對Redis熱Key?架構Redis
- 【VMware vSAN】全新vSAN 8 ESA快速儲存架構配置檔案服務並建立檔案共享。架構
- 雲端儲存國外火爆國內冷
- Streaming Data Warehouse 儲存:需求與架構架構
- 架構師之路,從「儲存選型」起步架構
- Android 儲存系統之架構篇Android架構
- iSCSI儲存的4種系統架構架構
- Redis 分散式儲存Redis分散式
- Redis持久化儲存Redis持久化
- nginx+iis+redis+Task.MainForm構建分散式架構 之 (redis儲存分散式共享的session及共享session運作流程)NginxRedisAIORM分散式架構Session
- 現代儲存架構:磁帶儲存在資料中心"重生"架構
- 前端架構之移動端混合架構(hybrid)前端架構
- GPU體系架構(二):GPU儲存體系GPU架構
- 如何進行雲端儲存架構框架設計?架構框架
- MySQL高階10-InnoDB引擎儲存架構MySql架構
- RocketMQ架構原理解析(二):訊息儲存MQ架構
- “雲端計算”時代 儲存架構如何變化架構
- HipChat 十億級檢索和儲存架構曝光架構
- MongoDB分片儲存的叢集架構實現MongoDB架構
- 超融合私有云基礎架構方案評估(架構與儲存篇)架構
- 圖解vsan儲存結構/資料恢復方法圖解資料恢復
- 儲存架構|Haystack太強了!存2600億圖片架構