遇到大key、熱key問題,主要是去拆分
大key問題
業務場景中經常會有各種大key的情況, 比如:
1. 單個簡單的key存儲的value很大(例如排行榜信息,key是固定的,value排行榜幾十萬的數據)
2. hash、set、zset、list中存儲過多的元素(以萬為單位)
由於redis是單線程運行的,如果一次操作的value很大會對整個redis的響應時間造成負面影響,所以,業務上能拆則拆,
解決方案:
1. 現在本地計算最后存儲在哪個key中,計算出key的hash值,默認是通過(pin)的hash值,模除100,然后確認存在那個key上面
2. 取得時候,同樣也需要計算,即
newHashKey = hashKey + (hash(field) % 10000);hset(newHashKey, field, value);hget(newHashKey, field)
熱key問題:
解釋:熱門的key值,被頻繁的訪問,例如秒殺的信息,導致redis直接死掉
解決方案: 通過把熱門的key,放在不同的服務器,即通過redis分片的策略,線上的Redis一般都是集群進行部署,對於Redis-Cluster模式,熱點的key會導致部分分片的負載非常高而被拖垮
1. 可以將熱key,通過輪詢放在不同的服務器,
2. 查詢的時候,同樣按照輪詢,查詢不同的服務器,(然后通過拼接各台服務器的數據)降低單台服務器的壓力
一、緩存讀熱點key問題:
某個熱點緩存model讀取流量極大。帶來問題:
- 讀緩存問題:讀流量集中到某key,導致指定緩存機器壓力過大
- 寫緩存問題:緩存失效時,大量線程穿透構建緩存,帶來db和服務壓力。
解決:
- 讀緩存問題
- 將緩存在分布式服務機器做二次緩存
- 備份熱點Key:即將熱點Key+隨機數,隨機分配至Redis其他節點中。這樣訪問熱點key的時候就不會全部命中到一台機器上了。
- 限流熔斷保護。
- 寫緩存問題
- 使用互斥鎖(mutex key),只讓一個線程構建緩存,其他線程等待構建緩存的線程執行完,重新從緩存獲取數據就可以了(如下圖)。
- redis上不設置過期時間,過期時間存在key對應的value里,如果發現要過期了,通過一個后台的異步線程進行緩存的構建,也就是“邏輯”過期。對於性能非常友好,唯一不足的就是構建緩存時候,其余線程(非構建緩存的線程)可能訪問的是老數據。
- 使用互斥鎖(mutex key),只讓一個線程構建緩存,其他線程等待構建緩存的線程執行完,重新從緩存獲取數據就可以了(如下圖)。
二、緩存大key問題
Redis使用過程中經常會有各種大key的情況, 比如單個簡單的key存儲的value很大。
由於redis是單線程運行的,如果一次操作的value很大會對整個redis的響應時間造成負面影響,導致IO網絡擁塞。
解決:
將整存整取的大對象,分拆為多個小對象。可以嘗試將對象分拆成幾個key-value, 使用multiGet獲取值,這樣分拆的意義在於分拆單次操作的壓力,將操作壓力平攤到多個redis實例中,降低對單個redis的IO影響;

