Redis 热 Key 发现以及解决办法
背景介紹
最近在技術交流微信群里看大家討論技術,其中有談到?Redis?熱?Key?的一些問題解決方案,我也仔細思考了一下我們目前系統中?Redis?的使用場景,我們是不是也存在熱?Key?問題,或者說如果我們也出現了熱?Key?問題會怎么去解決。
目前我在京東做一款?APP?(京東讀書)的業務量不是特別大,說一個指標就可以了,DAU?在?20W?左右,熟悉這個指標的朋友馬上就可以感受什么叫量不是特別大了。所以我的工作中遇到熱?Key?的問題可能印象中沒有過,如果硬要說出現過,也算是有過,不過那種情況不能算是簡單的熱?Key?問題,還有一些功能設計以及?Redis?數據結構選擇方面的一些問題,這些可以后面專門總結一下,這篇還是只聊熱?Key。
目錄
熱 Key 帶來問題
其實,按我理解來說,沒有什么所謂的熱?Key?問題,所謂的熱?Key?問題都是由于對某個?Key?的訪問量過大所產生的一些衍生問題。
由于某個?Key?的數據一定是存儲到后端某臺服務器的?Redis?單個實例上,如果對這個?Key?突然出現大量的請求操作,這樣就會造成流量過于集中,達到?Redis?單個實例處理上限,可能會導致?Redis?實例?CPU?使用率?100%,或者是網卡流量達到上限等,對系統的穩定性和可用性造成影響,或者更為嚴重出現服務器宕機,無法對外提供服務;更有甚者在出現?Redis?服務不可用之后,大量的數據請求全部落地數據庫查詢上,Redis?都已經頂不住了,數據庫也是分分鐘掛掉的節奏,這個是所謂的熱?Key?問題。
-
流量集中,達到服務器處理上限(CPU、網絡?IO?等);
-
會影響在同一個?Redis?實例上其他?Key?的讀寫請求操作;
-
熱?Key?請求落到同一個?Redis?實例上,無法通過擴容解決;
-
大量?Redis?請求失敗,查詢操作可能打到數據庫,拖垮數據庫,導致整個服務不可用。
通過上面的描述,其實熱?key?問題不僅是對某個?Key?請求流量過于集中的問題,也和服務器性能有很大的關聯,如果是一個普通的?Docker?容器(4C8G,4核CPU,8G內存,大家不要笑,我們系統好多這種規格服務器),和一臺性能強勁的物理機,這兩種不同的服務器規格配置對熱?Key?的認定估計也不會相同,這個可能是我對熱?key?問題的一點不同理解。
如何發現熱 Key
通過上面的分析,出現熱?Key?的危害還是很大的,我們不可能等到熱?Key?出現已經拖垮了服務再去處理,那個時候業務一定已經收到影響,損失也是不言而喻的;那么能夠在熱?Key?出現前通過一些手段提前監控到熱?Key?的出現,對于保證業務系統的穩定性是非常重要的,那么我們都有哪些手段提前觀測到熱?Key?的出現呢?
憑借業務經驗,預估熱 Key 出現
根據業務系統上線的一些活動和功能,我們是可以在某些場景下提前預估熱?Key?的出現的,比如業務需要進行一場商品秒殺活動,秒殺商品信息和數量一般都會緩存到?Redis?中,這種場景極有可能出現熱?Key?問題的。
-
優點:簡單,憑經驗發現熱?Key,提早發現提早處理;
-
缺點:沒有辦法預測所有熱?Key?出現,比如某些熱點新聞事件,無法提前預測。
客戶端進行收集
一般我們在連接?Redis?服務器時都要使用專門的 SDK(比如:Java?的客戶端工具?Jedis、Redisson),我們可以對客戶端工具進行封裝,在發送請求前進行收集采集,同時定時把收集到的數據上報到統一的服務進行聚合計算。
-
優點:方案簡單
-
缺點:
-
對客戶端代碼有一定入侵,或者需要對?SDK?工具進行二次開發;
-
沒法適應多語言架構,每一種語言的?SDK?都需要進行開發,后期開發維護成本較高。
-
在代理層進行收集
如果所有的?Redis?請求都經過?Proxy(代理)的話,可以考慮改動?Proxy?代碼進行收集,思路與客戶端基本類似。
-
優點:對使用方完全透明,能夠解決客戶端?SDK?的語言異構和版本升級問題;
-
缺點:
-
開發成本會比客戶端高些;
-
并不是所有的?Redis?集群架構中都有?Proxy?代理(使用這種方式必須要部署?Proxy)。
-
使用 Redis 自帶命令
hotkeys 參數
Redis?在?4.0.3?版本中添加了?hotkeys?查找特性,可以直接利用?redis-cli --hotkeys?獲取當前?keyspace?的熱點?key,實現上是通過?scan + object freq?完成的。
-
優點:無需進行二次開發,能夠直接利用現成的工具;
-
缺點:
-
由于需要掃描整個?keyspace,實時性上比較差;
-
掃描時間與?key?的數量正相關,如果?key?的數量比較多,耗時可能會非常長。
-
monitor?命令
monitor?命令可以實時抓取出?Redis?服務器接收到的命令,通過?redis-cli monitor?抓取數據,同時結合一些現成的分析工具,比如?redis-faina,統計出熱 Key。
-
優點:無需進行二次開發,能夠直接利用現成的工具;
-
缺點:該命令在高并發的條件下,有內存增暴增的隱患,還會降低?Redis?的性能。
Redis 節點抓包分析
Redis?客戶端使用?TCP?協議與服務端進行交互,通信協議采用的是?RESP?協議。自己寫程序監聽端口,按照?RESP?協議規則解析數據,進行分析。或者我們可以使用一些抓包工具,比如?tcpdump?工具,抓取一段時間內的流量進行解析。
-
優點:對?SDK?或者?Proxy?代理層沒有入侵;
-
缺點:
-
有一定的開發成本;
-
熱?Key?節點的網絡流量和系統負載已經比較高了,抓包可能會導致情況進一步惡化。
-
熱 Key 問題解決方案
增加 Redis 實例復本數量
對于出現熱?Key?的?Redis?實例,我們可以通過水平擴容增加副本數量,將讀請求的壓力分擔到不同副本節點上。
二級緩存(本地緩存)
當出現熱?Key?以后,把熱?Key?加載到系統的?JVM?中。后續針對這些熱?Key?的請求,會直接從?JVM?中獲取,而不會走到?Redis?層。這些本地緩存的工具很多,比如?Ehcache,或者?Google Guava?中?Cache?工具,或者直接使用?HashMap?作為本地緩存工具都是可以的。
使用本地緩存需要注意兩個問題:
-
如果對熱?Key?進行本地緩存,需要防止本地緩存過大,影響系統性能;
-
需要處理本地緩存和?Redis?集群數據的一致性問題。
熱 Key 備份
通過前面的分析,我們可以了解到,之所以出現熱?Key,是因為有大量的對同一個?Key?的請求落到同一個?Redis?實例上,如果我們可以有辦法將這些請求打散到不同的實例上,防止出現流量傾斜的情況,那么熱?Key?問題也就不存在了。
那么如何將對某個熱?Key?的請求打散到不同實例上呢?我們就可以通過熱?Key?備份的方式,基本的思路就是,我們可以給熱?Key?加上前綴或者后綴,把一個熱?Key?的數量變成?Redis?實例個數?N?的倍數?M,從而由訪問一個?Redis?Key?變成訪問?N * M?個?Redis?Key。?N * M?個?Redis?Key?經過分片分布到不同的實例上,將訪問量均攤到所有實例。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // N 為 Redis 實例個數,M 為 N 的 2倍 const M = N * 2 //生成隨機數 random = GenRandom(0, M) //構造備份新 Key bakHotKey = hotKey + "_" + random data = redis.GET(bakHotKey) if data == NULL {data = redis.GET(hotKey)if data == NULL {data = GetFromDB()// 可以利用原子鎖來寫入數據保證數據一致性redis.SET(hotKey, data, expireTime)redis.SET(bakHotKey, data, expireTime + GenRandom(0, 5))} else {redis.SET(bakHotKey, data, expireTime + GenRandom(0, 5))} } |
在這段代碼中,通過一個大于等于?1?小于?M?的隨機數,得到一個?bakHotKey,程序會優先訪問?bakHotKey,在得不到數據的情況下,再訪問原來的?hotkey,并將?hotkey?的內容寫回?bakHotKey。值得注意的是,bakHotKey?的過期時間是?hotkey?的過期時間加上一個較小的隨機正整數,這是通過坡度過期的方式,保證在?hotkey?過期時,所有?bakHotKey?不會同時過期而造成緩存雪崩。
總結
在這一篇文章中我們首先分析了在?Redis?中熱?Key?帶來的一些問題,同時也介紹了在海量的?Redis?Key?中找到熱?Key?的一些方法,最后也提到了在解決熱?Key?問題中我們常用的一些辦法;總結來說,Redis?熱?Key?問題首先是請求流量過大造成的,但是更深層次原因還是出現了流量傾斜,單個?Redis?實例承擔的流量過大造成的,了解到了本質原因,解決的思路也就簡單了,就是要想盡一切辦法將單個實例承擔的流量打散,讓每個機器均衡承擔熱?Key?的流量,不要出現流量傾斜,保證系統的穩定性。
參考鏈接
-
如何快速定位 Redis 熱 key
-
如何處理redis集群中hot key和big key
-
談談redis的熱key問題如何解決
-
redis緩存使用中的熱key問題
-
有贊透明多級緩存解決方案(TMC)
總結
以上是生活随笔為你收集整理的Redis 热 Key 发现以及解决办法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图解 Redis 五种数据结构底层实现
- 下一篇: Redis 新特性篇:100% 掌握多线