Redis 混合存儲-冷熱數據識別與交換
來自專欄我是程序員23 人贊了文章
背景
Redis混合存儲產品是阿里雲自主研發的完全兼容Redis協議和特性的混合存儲產品。
通過將部分冷數據存儲到磁碟,在保證絕大部分訪問性能不下降的基礎上,大大降低了用戶成本並突破了內存對Redis單實例數據量的限制。其中,對冷熱數據的識別和交換是混合存儲產品性能的關鍵因素。冷熱數據定義
在Redis混合存儲中,內存和磁碟的比例是用戶可以自由選擇的:
Redis混合存儲實例將所有的Key都認為是熱數據,以少量的內存為代價保證所有Key的訪問請求的性能是高效且一致的。而對於Value部分,在內存不足的情況下,實例本身會根據最近訪問時間,訪問頻度,Value大小等維度選取出部分value作為冷數據後台非同步存儲到磁碟上直到內存小於制定閾值為止。
在Redis混合存儲實例中,我們將所有的Key都認為是熱數據保存在內存中是出於以下兩點考慮:
- Key的訪問頻度比Value要高很多。作為KV資料庫,通常的訪問請求都需要先查找Key確認Key是否存在,而要確認一個key不存在,就需要以某種形式檢查所有Key的集合。在內存中保留所有Key,可以保證key的查找速度與純內存版完全一致。
- Key的大小佔比很低。即使是普通字元串類型,通常的業務模型裡面Value比Key要大幾倍。而對於Set,List,Hash等集合對象,所有成員加起來組成的Value更是比Key大了好幾個數量級。
因此,Redis混合存儲實例的適用場景主要有以下兩種:
- 數據訪問不均勻,存在熱點數據;
- 內存不足以放下所有數據,且Value較大(相對於Key而言)
冷熱數據識別
當內存不足時的情況下,實例會按照最近訪問時間,訪問頻度,value大小等維度計算出value的權重,將權重最低的value存儲到磁碟上並從內存中刪除。
偽代碼如下:while used_memory > max_memory coldest_value = pick_coldest_value() swap_value(coldest_value)end
理想的情況下,我們當然希望能夠準確的計算出當前最冷的value。然而,value的冷熱程度根據訪問情況動態變化的,每次都重新計算所有value的冷熱權重的時間消耗是完全不可接受的。
Redis本身在內存滿的情況下會根據用戶設置的淘汰策略淘汰數據,而熱數據從內存寫到磁碟也可以認為是一種「淘汰」的過程。從性能,準確率以及用戶理解程度考慮,我們在冷熱數據識別時採用和Redis類似的近似計算方法,支持多種策略, 通過隨機採樣小部分數據來降低CPU和內存消耗,通過eviction pool利用採樣歷史信息來輔助提高準確率。上圖為不同版本和不同採樣樣本數目配置下,Redis近似淘汰演算法的命中率示意圖。淺灰色的點為被淘汰數據,灰色的點為未淘汰數據,綠色點為測試過程中新加入的數據。冷熱數據交換
Redis混合存儲在冷熱數據交換過程在後台IO線程中完成。
熱數據->冷數據
非同步方式:
- 主線程在內存接近最大值時,生成一系列數據換出任務;
- 後台線程執行這些數據換出任務,執行完畢之後通知主線程;
- 主線程更新釋放內存中的value,更新內存中數據字典中的value為一個簡單的元信息;
同步方式:
如果寫入流量過大,非同步方式來不及換出數據,導致內存超出最大規格內存。主線程將直接執行數據換出任務,達到變相限流的目的。
冷數據->熱數據
非同步方式:
- 主線程在執行命令前,先判斷命令涉及的value是否都在內存中;
- 如果不是,生成數據載入任務,掛起該客戶端,主線程繼續處理其他客戶端請求;
- 後台線程執行數據載入任務,執行完畢後通知主線程;
- 主線程在內存中更新數據字典中的value,喚醒之前掛起的客戶端,處理其請求。同步方式:
在Lua腳本,具體命令執行階段,如果發現有value存儲在磁碟上,主線程將直接執行數據載入任務,保證Lua腳本和命令的語義不變。
本文作者:懷聽
原文鏈接
更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎
本文為雲棲社區原創內容,未經允許不得轉載。
推薦閱讀:
※中國首代「假」防空艦僅紙面數據無戰力,卻依然吊打鄰國
※【大數據專欄】中國的中產階級們,到了國外到底有多能買?
※我們不生產數據,我們只是數據的搬運工
※數據告訴你----各省人都喜歡什麼車?
※南寧市家事糾紛大數據分析報告·撫養編(2015-2016)