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