淺析Redis?切片集群的數據傾斜問題
Redis 中如何應對數據傾斜
什么是數據傾斜
如果 Redis 中的部署,采用的是切片集群,數據是會按照一定的規(guī)則分散到不同的實例中保存,比如,使用 Redis Cluster 或 Codis。
數據傾斜會有下面兩種情況:
1、數據量傾斜:在某些情況下,實例上的數據分布不均衡,某個實例上的數據特別多。
2、數據訪問傾斜:雖然每個集群實例上的數據量相差不大,但是某個實例上的數據是熱點數據,被訪問得非常頻繁。
發(fā)生了數據傾斜,會造成那些數據量大的和訪問高的實例節(jié)點,系統(tǒng)的負載升高,響應速度變慢。嚴重的情況造成內存資源耗盡,引起系統(tǒng)崩潰。
數據量傾斜
數據量傾斜,也就是實例上的數據分布不均衡,某個實例中的數據分布的特別多 。
數據量的傾斜,主要有下面三種情況:
1、bigkey導致傾斜;
2、Slot分配不均衡導致傾斜;
3、Hash Tag導致傾斜。
下面來一一的分析下
bigkey導致傾斜
什么是 bigkey:我們將含有較大數據或含有大量成員、列表數的 Key 稱之為大Key。
一個 STRING 類型的 Key,它的值為 5MB(數據過大)
一個 LIST 類型的 Key,它的列表數量為 20000 個(列表數量過多)
一個 ZSET 類型的 Key,它的成員數量為 10000 個(成員數量過多)
一個 HASH 格式的 Key,它的成員數量雖然只有 1000 個但這些成員的 value 總大小為 100MB(成員體積過大)
如果某個實例中保存了 bigkey,那么就有可能導致集群的數據傾斜。
bigkey 存在問題
內存空間不均勻:如果采用切片集群的部署方案,容易造成某些實例節(jié)點的內存分配不均勻;
造成網絡擁塞:讀取 bigkey 意味著需要消耗更多的網絡流量,可能會對 Redis 服務器造成影響;
過期刪除:bigkey 不單讀寫慢,刪除也慢,刪除過期 bigkey 也比較耗時;
遷移困難:由于數據龐大,備份和還原也容易造成阻塞,操作失??;
如何避免
對于bigkey可以從以下兩個方面進行處理
1、合理優(yōu)化數據結構
1、對較大的數據進行壓縮處理;
2、拆分集合:將大的集合拆分成小集合(如以時間進行分片)或者單個的數據。
2、選擇其他的技術來存儲 bigkey;
使用其他的存儲形式,考慮使用 cdn 或者文檔性數據庫 MongoDB。
Slot分配不均衡導致傾斜
例如在 Redis Cluster 通過 Slot 來給數據分配實例
1、Redis Cluster方案采用哈希槽來處理 KEY 在不同實例中的分布,一個切片集群共有 16384 個哈希槽,這些哈希槽類似于數據分區(qū),每個鍵值對都會根據它的 key,被映射到一個哈希槽中;
2、一個 KEY ,首先會根據 CRC16 算法計算一個16 bit的值;然后,再用這個 16bit 值對 16384 取模,得到 0~16383 范圍內的模數,每個模數代表一個相應編號的哈希槽。
3、然后把哈希槽分配到所有的實例中,例如,如果集群中有N個實例,那么,每個實例上的槽個數為16384/N個。
如果 Slot 分配的不均衡,就會導致某幾個實例中數據量偏大,進而導致數據傾斜的發(fā)生。
出現(xiàn)這種問題,我們就可以使用遷移命令把這些 Slot 遷移到其它實例上,即可。
Hash Tag導致傾斜
Hash Tag 用于 redis 集群中,其作用是將具有某一固定特征的數據存儲到同一臺實例上。其實現(xiàn)方式為在 key 中加個 {},例如 test{1}。
使用 Hash Tag 后客戶端在計算 key 的 crc16 時,只計算 {} 中數據。如果沒使用 Hash Tag,客戶端會對整個 key 進行 crc16 計算。
| 數據key | 哈希計算 | 對應的Slot |
|---|---|---|
| user:info:{3231} | CRC16('3231') mod 16384 | 1024 |
| user:info:{5328} | CRC16('5328') mod 16384 | 3210 |
| user:order:{3231} | CRC16('3231') mod 16384 | 1024 |
| user:order:{5328} | CRC16('5328') mod 16384 | 3210 |
這樣通過 Hash Tag 就可以將某一固定特征數據存儲到一臺實例上,避免逐個查詢集群中實例。
栗如:如果我們進行事務操作或者數據的范圍查詢,因為Redis Cluster和 Codis 本身并不支持跨實例的事務操作和范圍查詢,當業(yè)務應用有這些需求時,就只能先把這些數據讀取到業(yè)務層進行事務處理,或者是逐個查詢每個實例,得到范圍查詢的結果。
Hash Tag潛在的問題就是,可能存在大量數據被映射到同一個實例的情況出現(xiàn),導致集群的數據傾斜,集群中的負載不均衡。
所有當我使用 Hash Tag 的時候就做好評估,我們的業(yè)務訴求如果不使用 Hash Tag 可以解決嗎,如果不可避免的使用,我們需要評估好數據量,盡量避免數據傾斜的出現(xiàn)。
數據訪問傾斜
雖然每個集群實例上的數據量相差不大,但是某個實例上的數據是熱點數據,被訪問得非常頻繁,這就是數據訪問傾斜。
數據量訪問傾斜的罪魁禍首就是 Hot Key
切片集群中的 Key 最終會存儲到集群中的一個固定的 Redis 實例中。某一個 Key 在一段時間內訪問遠高于其它的 Key,也就是該 Key 對應的 Redis 實例,會收到過大的流量請求,該實例容易出現(xiàn)過載和卡頓現(xiàn)象,甚至還會被打掛掉。
常見引發(fā)熱點 Key 的情況:
1、新聞中的熱點事件;
2、秒殺活動中的,性價比高的商品;
如何發(fā)現(xiàn) Hot Key1、提現(xiàn)預判;
根據業(yè)務經驗進行提前預判;
2、在客戶端進行收集;
通過在客戶端增加命令的采集,來統(tǒng)計發(fā)現(xiàn)熱點 Key;
3、使用 Redis 自帶的命令排查;
使用monitor命令統(tǒng)計熱點key(不推薦,高并發(fā)條件下會有造成redis 內存爆掉的隱患);
hotkeys參數,redis 4.0.3提供了redis-cli的熱點key發(fā)現(xiàn)功能,執(zhí)行redis-cli時加上–hotkeys選項即可。但是該參數在執(zhí)行的時候,如果key比較多,執(zhí)行起來比較慢。
4、在Proxy層做收集
如果集群架構引入了 proxy,可以在 proxy 中做統(tǒng)計
5、自己抓包評估
Redis客戶端使用TCP協(xié)議與服務端進行交互,通信協(xié)議采用的是RESP。自己寫程序監(jiān)聽端口,按照RESP協(xié)議規(guī)則解析數據,進行分析。缺點就是開發(fā)成本高,維護困難,有丟包可能性。
Hot Key 如何解決
知道了Hot Key如何來應對呢
1、對 Key 進行分散處理;
舉個栗子
有一個熱 Key 名字為Hot-key-test,可以將其分散為Hot-key-test1,Hot-key-test2...然后將這些 Key 分散到多個實例節(jié)點中,當客戶端進行訪問的時候,隨機一個下標的 Key 進行訪問,這樣就能將流量分散到不同的實例中了,避免了一個緩存節(jié)點的過載。
一般來講,可以通過添加后綴或者前綴,把一個 hotkey 的數量變成 redis 實例個數 N 的倍數 M,從而由訪問一個redis key變成訪問N * M個redis key。 N*M個redis key經過分片分布到不同的實例上,將訪問量均攤到所有實例。
const M = N * 2
//生成隨機數
random = GenRandom(0, M)
//構造備份新key
bakHotKey = hotKey + “_” + random
data = redis.GET(bakHotKey)
if data == NULL {
data = GetFromDB()
redis.SET(bakHotKey, expireTime + GenRandom(0,5))
}2、使用本地緩存;
業(yè)務端還可以使用本地緩存,將這些熱 key 記錄在本地緩存,來減少對遠程緩存的沖擊。
這里,有個地方需要注意下,熱點數據多副本方法只能針對只讀的熱點數據。如果熱點數據是有讀有寫的話,就不適合采用多副本方法了,因為要保證多副本間的數據一致性,會帶來額外的開銷。
對于有讀有寫的熱點數據,我們就要給實例本身增加資源了,例如使用配置更高的機器,來應對大量的訪問壓力。
總結
1、數據傾斜會有下面兩種情況;
1、數據量傾斜:在某些情況下,實例上的數據分布不均衡,某個實例上的數據特別多。
2、數據訪問傾斜:雖然每個集群實例上的數據量相差不大,但是某個實例上的數據是熱點數據,被訪問得非常頻繁。
2、數據量的傾斜,主要有下面三種情況;
1、bigkey導致傾斜;
2、Slot分配不均衡導致傾斜;
3、Hash Tag導致傾斜。
3、數據訪問傾斜,原因就是 Hot Key 造成的,出現(xiàn)Hot Key,一般下面有下面兩種方式去解決;
1、對 Key 進行分散處理;
2、使用本地緩存;
參考
【Redis核心技術與實戰(zhàn)】https://time.geekbang.org/column/intro/100056701
【Redis設計與實現(xiàn)】https://book.douban.com/subject/25900156/
【Redis 的學習筆記】https://github.com/boilingfrog/Go-POINT/tree/master/redis
【Redis中的切片集群】https://boilingfrog.github.io/2022/02/20/redis中常見的集群部署方案/#切片集群
【Redis 切片集群的數據傾斜分析】https://boilingfrog.github.io/2022/06/22/Redis切片集群的數據傾斜分析/
到此這篇關于Redis 切片集群的數據傾斜分析的文章就介紹到這了,更多相關Redis數據傾斜內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
關于使用IDEA的springboot框架往Redis里寫入數據亂碼問題
這篇文章主要介紹了用IDEA的springboot框架往Redis里寫入數據亂碼問題,本文給大家分享解決方法通過圖文示例相結合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10

