概述
什么是熱key?
當一個key的訪問量明顯大于其他key的時候,他就可以被稱為熱key。
什么情況下產生熱點Key問題?
比如瞬間有幾十萬的請求去訪問redis上某個固定的key。
這種情況其實在日常工作生活中是常見的事件,例如:熱門商品降價促銷、熱點新聞、熱點評論、明星直播等,這些典型的讀多寫少的場景就會產生熱點問題。
熱Key問題
假如突然有幾十萬的請求去訪問redis上的某個特定key。那么,這樣會造成流量過于集中,達到物理網卡上限,從而導致這臺redis的服務器宕機。
那接下來這個key的請求,就會直接懟到你的數據庫上,導致你的服務不可用。
發(fā)現熱Key
- 憑借業(yè)務經驗,進行預估哪些是熱key
其實這個方法還是挺有可行性的。比如某商品在做秒殺,那這個商品的key就可以判斷出是熱key。缺點很明顯,并非所有業(yè)務都能預估出哪些key是熱key。 - 在客戶端進行收集
這個方式就是在操作redis之前,加入一行代碼進行數據統(tǒng)計。那么這個數據統(tǒng)計的方式有很多種,也可以是給外部的通訊系統(tǒng)發(fā)送一個通知信息。缺點就是對客戶端代碼造成入侵。有贊的就是采用對原生jedis包的JedisPool和Jedis類做了改造,在JedisPool初始化過程中集成TMC“熱點發(fā)現”+“本地緩存”功能從而實現熱key發(fā)現和治理。 - 自己抓包評估
自己寫程序監(jiān)聽redis端口,按照RESP協(xié)議規(guī)則解析數據,進行分析。缺點就是開發(fā)成本高,維護困難,有丟包可能性。 - 業(yè)務埋點分析
通過業(yè)務埋點日志進行統(tǒng)計分析,找出高頻接口和熱點參數,再結合業(yè)務分析出熱key
解決方案
- 利用二級緩存
比如利用ehcache,或者一個HashMap都可以。在你發(fā)現熱key以后,把熱key加載到系統(tǒng)的JVM中。針對這種熱key請求,會直接從jvm中取,而不會走到redis層。缺點就是需要考慮緩存一致性問題。常見框架:J2cache - 備份熱key
采用redis集群模式,將同一份熱key在集群中備份多份,具體實現可以采用固定前綴+隨機數的方式將熱key分散到集群中的多個節(jié)點,從而分散請求量
//偽代碼示例
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))
}