2023-06-29:redis中什么是熱點(diǎn)Key?該如何解決?
2023-06-29:redis中什么是熱點(diǎn)Key?該如何解決?
答案2023-06-29:
在Redis中,經(jīng)常被訪問的key被稱為熱點(diǎn)key。
產(chǎn)生原因和危害
原因
熱點(diǎn)key問題產(chǎn)生的原因可以歸納為以下兩種情況:
用戶對于某些數(shù)據(jù)的訪問頻率遠(yuǎn)大于數(shù)據(jù)的生產(chǎn)頻率,這類數(shù)據(jù)包括熱門商品、熱點(diǎn)新聞、熱點(diǎn)評(píng)論以及明星直播等。
在日常工作生活中,突發(fā)事件(如雙十一期間商品降價(jià)促銷)可能導(dǎo)致某些熱門商品被大量點(diǎn)擊瀏覽或購買,產(chǎn)生了巨大的需求量。類似地,熱點(diǎn)新聞、熱點(diǎn)評(píng)論和明星直播等引起大量刊發(fā)和瀏覽的情況也是典型的讀多寫少場景,它們會(huì)產(chǎn)生熱點(diǎn)問題。
請求集中在分片集群中,超過單個(gè)服務(wù)器的性能極限。在服務(wù)端進(jìn)行數(shù)據(jù)訪問時(shí),通常會(huì)對數(shù)據(jù)進(jìn)行分片切分,其中某個(gè)服務(wù)器上的熱點(diǎn)Key訪問量超過了其承載能力的極限,從而導(dǎo)致熱點(diǎn)Key問題的出現(xiàn)。
危害
1、流量集中,超過物理網(wǎng)卡的處理能力上限。
2、請求過多,導(dǎo)致緩存分片服務(wù)崩潰。
3、數(shù)據(jù)庫擊穿,引發(fā)業(yè)務(wù)雪崩。
發(fā)現(xiàn)熱點(diǎn)key
預(yù)估發(fā)現(xiàn)
針對業(yè)務(wù),可以提前預(yù)估出訪問頻繁的熱點(diǎn)Key,例如在秒殺商品業(yè)務(wù)中,秒殺商品就是熱點(diǎn)Key的典型案例。
然而,并非所有業(yè)務(wù)都容易預(yù)估出熱點(diǎn)Key,有時(shí)可能會(huì)出現(xiàn)對熱點(diǎn)Key的遺漏或預(yù)估錯(cuò)誤的情況。
客戶端發(fā)現(xiàn)
客戶端實(shí)際上是離"熱點(diǎn)Key"最近的位置,因?yàn)镽edis命令是由客戶端發(fā)送的。以Jedis為例,在核心命令入口處使用Google Guava中的AtomicLongMap可以方便地記錄熱點(diǎn)Key的訪問情況,示例如下:
然而,使用客戶端進(jìn)行熱點(diǎn)Key的統(tǒng)計(jì)也存在一些問題:
(1) 無法預(yù)知熱點(diǎn)Key的數(shù)量,可能存在內(nèi)存泄露的風(fēng)險(xiǎn)。
(2) 在不同的客戶端代碼中需要維護(hù)此邏輯,可能增加維護(hù)成本。
(3) 在規(guī)?;瘏R總方面的實(shí)現(xiàn)相對復(fù)雜。
Redis發(fā)現(xiàn)
monitor命令
使用Redis的monitor
命令,可以監(jiān)控到Redis執(zhí)行的所有命令。通過解析monitor
的結(jié)果,我們可以統(tǒng)計(jì)一段時(shí)間內(nèi)的熱點(diǎn)Key排行榜、命令排行榜以及客戶端分布等數(shù)據(jù)。這種方法能夠提供更詳細(xì)的信息,幫助我們深入了解Redis的使用情況。需要注意的是,在生產(chǎn)環(huán)境中使用monitor
命令可能對性能產(chǎn)生一定的影響,因此應(yīng)該謹(jǐn)慎使用,并注意網(wǎng)絡(luò)開銷和輸出緩沖區(qū)的消費(fèi)速度。

Redis-Faina是Facebook開源的一款使用Python語言實(shí)現(xiàn)的工具。它利用上述原理可以獲取最近10萬條命令的熱點(diǎn)Key、熱點(diǎn)命令以及命令執(zhí)行的耗時(shí)分布等數(shù)據(jù)。為了減少網(wǎng)絡(luò)開銷并提高輸出緩沖區(qū)的消費(fèi)速度,Redis-Faina會(huì)盡可能地在本機(jī)執(zhí)行monitor命令。使用Redis-Faina可以更詳細(xì)地了解Redis的使用情況。需要注意,在生產(chǎn)環(huán)境中使用該工具時(shí)應(yīng)考慮性能影響和安全性。
此種方法存在兩個(gè)問題:
1、在高并發(fā)條件下,使用monitor命令會(huì)導(dǎo)致內(nèi)存暴增,同時(shí)可能影響Redis的性能。因此,這種方法適合在短時(shí)間內(nèi)使用,而不適合長時(shí)間或高并發(fā)的監(jiān)控。
2、monitor命令只能統(tǒng)計(jì)單個(gè)Redis節(jié)點(diǎn)的熱點(diǎn)key,對于Redis集群,需要進(jìn)行匯總統(tǒng)計(jì)才能獲取全集群的熱點(diǎn)key信息。
可以參考的框架:Facebook開源的redis-faina正是利用上述原理使用Python語言實(shí)現(xiàn)的
hotkeys
Redis在版本4.0.3中為redis-cli提供了--hotkeys
選項(xiàng),用于方便地找到熱點(diǎn)key。通過使用該選項(xiàng),我們可以快速獲取到Redis中的熱點(diǎn)key信息。這個(gè)功能的引入為我們在分析和優(yōu)化Redis性能時(shí)提供了更方便和直接的工具。需要注意的是,確保Redis版本符合要求,并使用適當(dāng)?shù)拿钚羞x項(xiàng)來獲得所需的熱點(diǎn)key信息。

如果發(fā)生錯(cuò)誤,確保先將內(nèi)存逐出策略設(shè)置為allkeys-lfu
或者volatile-lfu
,否則可能會(huì)返回錯(cuò)誤。


然而,如果鍵值非常多,執(zhí)行此操作可能會(huì)變得相對較慢,這與熱點(diǎn)的概念有些相悖。此外,熱度的定義可能不夠準(zhǔn)確。
抓取TCP包發(fā)現(xiàn)熱點(diǎn)key
Redis客戶端使用TCP協(xié)議與服務(wù)端進(jìn)行交互,通信協(xié)議采用RESP??梢酝ㄟ^對機(jī)器上所有Redis端口的TCP數(shù)據(jù)包進(jìn)行抓取來完成熱點(diǎn)key的統(tǒng)計(jì)。這種方法對Redis客戶端和服務(wù)端沒有侵入,是一種較完美的方案。然而,存在以下三個(gè)問題:
1.需要進(jìn)行一定的開發(fā)工作。
2.對于高流量的機(jī)器抓包,可能會(huì)對機(jī)器網(wǎng)絡(luò)產(chǎn)生干擾,并可能丟包。
3.維護(hù)成本較高。
為了解決這些問題,有一些開源方案如ELK(ElasticSearch, Logstash, Kibana)體系下的packetbeat插件可以實(shí)現(xiàn)Redis、MySQL等服務(wù)的數(shù)據(jù)包抓取、分析和報(bào)表展示。
處理熱點(diǎn)key
發(fā)現(xiàn)熱點(diǎn)key后,可以采取以下方法進(jìn)行處理:
1.?使用二級(jí)緩存:使用Guava Cache或HCache將熱點(diǎn)key加載到JVM中作為本地緩存。訪問這些key時(shí),直接從本地緩存獲取數(shù)據(jù),避免直接訪問Redis層,有效保護(hù)緩存服務(wù)器。
2.?key分散:將熱點(diǎn)key分散為多個(gè)子key,并分別存儲(chǔ)在緩存集群的不同機(jī)器上。這些子key的值與熱點(diǎn)key相同。當(dāng)通過熱點(diǎn)key查詢數(shù)據(jù)時(shí),通過某種哈希算法隨機(jī)選擇一個(gè)子key,然后再訪問緩存機(jī)器,將熱點(diǎn)key分散到多個(gè)子key上。
請注意,以上只是幾種處理熱點(diǎn)key的方法,根據(jù)實(shí)際需求和系統(tǒng)情況,可能還會(huì)有其他適合的解決方案。