概述
什么是熱key?
當(dāng)一個(gè)key的訪問量明顯大于其他key的時(shí)候霎终,他就可以被稱為熱key咧最。
什么情況下產(chǎn)生熱點(diǎn)Key問題蹬屹?
比如瞬間有幾十萬的請求去訪問redis上某個(gè)固定的key匿级。
這種情況其實(shí)在日常工作生活中是常見的事件空镜,例如:熱門商品降價(jià)促銷、熱點(diǎn)新聞咳焚、熱點(diǎn)評論洽损、明星直播等,這些典型的讀多寫少的場景就會(huì)產(chǎn)生熱點(diǎn)問題革半。
熱Key問題
假如突然有幾十萬的請求去訪問redis上的某個(gè)特定key碑定。那么,這樣會(huì)造成流量過于集中又官,達(dá)到物理網(wǎng)卡上限不傅,從而導(dǎo)致這臺(tái)redis的服務(wù)器宕機(jī)。
那接下來這個(gè)key的請求赏胚,就會(huì)直接懟到你的數(shù)據(jù)庫上,導(dǎo)致你的服務(wù)不可用商虐。
發(fā)現(xiàn)熱Key
- 憑借業(yè)務(wù)經(jīng)驗(yàn)觉阅,進(jìn)行預(yù)估哪些是熱key
其實(shí)這個(gè)方法還是挺有可行性的。比如某商品在做秒殺秘车,那這個(gè)商品的key就可以判斷出是熱key典勇。缺點(diǎn)很明顯,并非所有業(yè)務(wù)都能預(yù)估出哪些key是熱key叮趴。 - 在客戶端進(jìn)行收集
這個(gè)方式就是在操作redis之前割笙,加入一行代碼進(jìn)行數(shù)據(jù)統(tǒng)計(jì)。那么這個(gè)數(shù)據(jù)統(tǒng)計(jì)的方式有很多種眯亦,也可以是給外部的通訊系統(tǒng)發(fā)送一個(gè)通知信息伤溉。缺點(diǎn)就是對客戶端代碼造成入侵。有贊的就是采用對原生jedis包的JedisPool和Jedis類做了改造妻率,在JedisPool初始化過程中集成TMC“熱點(diǎn)發(fā)現(xiàn)”+“本地緩存”功能從而實(shí)現(xiàn)熱key發(fā)現(xiàn)和治理乱顾。 - 自己抓包評估
自己寫程序監(jiān)聽redis端口,按照RESP協(xié)議規(guī)則解析數(shù)據(jù)宫静,進(jìn)行分析走净。缺點(diǎn)就是開發(fā)成本高,維護(hù)困難孤里,有丟包可能性伏伯。 - 業(yè)務(wù)埋點(diǎn)分析
通過業(yè)務(wù)埋點(diǎn)日志進(jìn)行統(tǒng)計(jì)分析,找出高頻接口和熱點(diǎn)參數(shù)捌袜,再結(jié)合業(yè)務(wù)分析出熱key
解決方案
- 利用二級緩存
比如利用ehcache说搅,或者一個(gè)HashMap都可以。在你發(fā)現(xiàn)熱key以后虏等,把熱key加載到系統(tǒng)的JVM中蜓堕。針對這種熱key請求抛虏,會(huì)直接從jvm中取,而不會(huì)走到redis層套才。缺點(diǎn)就是需要考慮緩存一致性問題迂猴。常見框架:J2cache - 備份熱key
采用redis集群模式,將同一份熱key在集群中備份多份背伴,具體實(shí)現(xiàn)可以采用固定前綴+隨機(jī)數(shù)的方式將熱key分散到集群中的多個(gè)節(jié)點(diǎn)沸毁,從而分散請求量
//偽代碼示例
const M = N * 2
//生成隨機(jī)數(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))
}