天天看點

Redis 阻塞之内在因素 API

API或資料結構不合理

通常Redis執行指令速度非常快, 但也存在例外, 如對一個包含上萬個元素的hash結構執行hgetall操作, 由于資料量比較大且指令算法複雜度是O(n) , 這條指令執行速度必然很慢。 這個問題就是典型的不合理使用API和資料結構。 對于高并發的場景我們應該盡量避免在大對象上執行算法複雜度超過O(n) 的指令。

如何發現慢查詢

Redis原生提供慢查詢統計功能, 執行slowlog get{n}指令可以擷取最近的n條慢查詢指令, 預設對于執行超過10毫秒的指令都會記錄到一個定長隊列中, 線上執行個體建議設定為1毫秒便于及時發現毫秒級以上的指令。 如果指令執行時間在毫秒級, 則執行個體實際OPS隻有1000左右。 慢查詢隊列長度預設128, 可适當調大。 慢查詢本身隻記錄了指令執行時間, 不包括資料網絡傳輸時間和指令排隊時間, 是以用戶端發生阻塞異常後, 可能不是目前指令緩慢, 而是在等待其他指令執行。 需要重點比對異常和慢查詢發生的時間點, 确認是否有慢查詢造成的指令阻塞排隊。發現慢查詢後, 開發人員需要作出及時調整。 可以按照以下兩個方向去調整:

1) 修改為低算法度的指令, 如hgetall改為hmget等, 禁用keys、 sort等指令。

2) 調整大對象: 縮減大對象資料或把大對象拆分為多個小對象, 防止一次指令操作過多的資料。 大對象拆分過程需要視具體的業務決定, 如使用者好友集合存儲在Redis中, 有些熱點使用者會關注大量好友, 這時可以按時間或其他次元拆分到多個集合中。

如何發現大對象

Redis本身提供發現大對象的工具, 對應指令: redis-cli-h{ip}-p{port}bigkeys。 内部原理采用分段進行scan操作, 把曆史掃描過的最大對象統計出來便于分析優化, 運作效果如下:

# redis-cli --bigkeys
# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).
[00.00%] Biggest string found so far 'ptc:-571805194744395733' with 17 bytes
[00.00%] Biggest string found so far 'RVF#2570599,1' with 3881 bytes
[00.01%] Biggest hash found so far 'pcl:8752795333786343845' with 208 fields
[00.37%] Biggest string found so far 'RVF#1224557,1' with 3882 bytes
[00.75%] Biggest string found so far 'ptc:2404721392920303995' with 4791 bytes
[04.64%] Biggest string found so far 'pcltm:614' with 5176729 bytes
[08.08%] Biggest string found so far 'pcltm:8561' with 11669889 bytes
[21.08%] Biggest string found so far 'pcltm:8598' with 12300864 bytes
..忽略更多輸出...
-------- summary -------
Sampled 3192437 keys in the keyspace!
Total key length in bytes is 78299956 (avg len 24.53)
Biggest string found 'pcltm:121' has 17735928 bytes
Biggest hash found 'pcl:3650040409957394505' has 209 fields
2526878 strings with 954999242 bytes (79.15% of keys, avg size 377.94)
0 lists with 0 items (00.00% of keys, avg size 0.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
665559 hashs with 19013973 fields (20.85% of keys, avg size 28.57)
0 zsets with 0 members (00.00% of keys, avg size 0.00)      

根據結果彙總資訊能非常友善地擷取到大對象的鍵, 以及不同類型資料結構的使用情況。

CPU飽和象

單線程的Redis處理指令時隻能使用一個CPU。 而CPU飽和是指Redis把單核CPU使用率跑到接近100%。 使用top指令很容易識别出對應Redis程序的CPU使用率。 CPU飽和是非常危險的, 将導緻Redis無法處理更多的指令, 嚴重影響吞吐量和應用方的穩定性。 對于這種情況, 首先判斷目前Redis的并發量是否達到極限, 建議使用統計指令redis-cli-h{ip}-p{port}--stat擷取目前

Redis使用情況, 該指令每秒輸出一行統計資訊, 運作效果如下:

# redis-cli --stat
------- data ------ --------------------- load -------------------- - child -
keys mem clients blocked requests connections
3789785 3.20G 507 0 8867955607 (+0) 555894
3789813 3.20G 507 0 8867959511 (+63904) 555894
3789822 3.20G 507 0 8867961602 (+62091) 555894
3789831 3.20G 507 0 8867965049 (+63447) 555894
3789842 3.20G 507 0 8867969520 (+62675) 555894
3789845 3.20G 507 0 8867971943 (+62423) 555894      
cmdstat_hset:calls=198757512,usec=27021957243,usec_per_call=135.95      

繼續閱讀