歡迎光臨
每天分享高質量文章

Redis開發設計規範及案例分析

作者:張家江

來自:樂得技術(ID:lede_tech)

 

引言

redis不是垃圾桶也不是 SUPER MAN,能力和資源都有限,不合理的使用會降低它的健康度,嚴重時甚至會引起redis抖動、阻塞等進而導致服務不可用,每一個使用redis的開發人員都應當掌握規範的開發和使用方法。本文整理出redis開發過程中七個較常出現的使用不合理的場景,並輔以案例進行分析說明。

 

 

01
合理使用集合類

案例

某活動需求,每天10點對昨天參加某活動的用戶進行推送提醒。開發人員使用redis儲存每天參加活動的用戶,通過ZRANGEBYSCORE命令獲取標的用戶進行提醒,提醒完後使用ZREMRANGEBYSCORE命令從redis中清除這批用戶。某一天ZRANGEBYSCOREZREMRANGEBYSCORE均出現了慢日誌報警,排查發現這一天參加該活動的用戶約有5萬。

 

 
分析

 

案例中使用了redis的sortedset來儲存用戶信息,其中value是用戶的賬號、score是用戶參加活動的時間,由於ZRANGEBYSCOREZREMRANGEBYSCORE命令的時間複雜度是 O(log(N) + M),其中M是操作的元素個數,N是集合元素總數,本例中當用戶數量為5萬時出現慢日誌。可以通過縮小每次查詢的集合數量,可以將一天分成多段,分批次查詢,比如把查24小時範圍的用戶改為查4小時範圍的用戶,分別查6次處理即可。

 

Q

如果用戶參加活動的時間很集中,在某一

時間段比如晚18點到22點查出來

數量還是特別多怎麼辦?

A

可以把粒度分得更細一些比如1小時或者30分鐘,如果確定用戶參加活動集中某個時間點,可以考慮使用ZSCAN遍歷操作並刪除。另外,對於標的時間範圍有確定的首尾元素時,還可以通過ZRANK命令查出元素的位置,通過 ZRANGE ZREMRANGEBYRANK來進行查詢和刪除操作,這樣每次操作可以控制運算元量,有效避免慢日誌。

 

 

 
小結

 

使用 sortedset、set、list、hash等集合類O(N)操作時要評估當前元素個數的規模以及將來的增長規模,對於短期就可能變為大集合的key,要預估O(N)操作的元素數量,避免全量操作,可以使用HSCANSSCANZSCAN進行漸進操作。集合元素數量過大在使用過程中會影響redis的實際性能,元素個數建議儘量不要超過5000,元素數量過大可考慮拆分成多個key進行處理。

 

 

02

合理設置過期時間

案例1

某投票功能,用於統計今日環比昨日的增長數量,開發人員使用redis儲存每天的投票數,key設計為vote_count_{date},其中{date}為當天的日期,由於沒有設置過期時間,一年以後產生了360多個key,實際在用的key始終只有2個。

 
分析

 

該案例中,每個生成的key在2天以後都不會再使用了,可將key加上過期時間。

 

案例2

某統計功能,用戶會不定期的匯入一批資料進 redis,每一批資料需要在30分鐘後、1天后、3天后、7天后進行計算統計,統計結果發給用戶。開發人員使用redis的同一個sortedset儲存這些匯入的資料,每天定時任務執行計算任務。由於沒有清理,導致大量結束計算任務的廢棄資料殘留redis。

 

 
分析

 

該案例中,每一批資料都有相應的生命周期,在匯入的第7天執行完最後一次計算任務生命周期結束,由於集合里的元素不能單獨設置過期時間,可在代碼邏輯中對最後一次使用這批資料後進行清理操作。

 

 

 
小結

 

如果key沒有設置超時時間,會導致一直占用記憶體。對於可以預估使用生命周期的key應當設置合理的過期時間或在最後一次操作時進行清理,避免垃圾資料殘留redis。

 

 

03

合理利用批操作命令

案例

某運營需求,需要給用戶生成短鏈,短鏈由短鏈前綴+短碼組成,根據短碼找到用戶對應的手機號,開發人員使用redis hash結構儲存短碼到手機號的映射。接口每次會匯入5萬個手機號。

 

 
分析

 

下麵是開發人員的三種操作redis方案的偽代碼

方案1直接使用redisHSET逐個設置

for(50000;)
HSET(key,短碼,手機號)

結果:失敗。redis ops飆升,同時接口響應超時

方案2:改用redis的 HMSET一次將所有元素設置到hash中

map 50000個元素
HMSET(key,map)

結果:失敗。出現redis慢日誌

方案3依然使用 HMSET,只是每次設置500個,迴圈100次

map 500個元素
for(100;)
HMSET(key,map)

結果:成功

 

對於大量頻繁的hset操作可以使用 HMSET替代減少redis操作次數同時提升處理速度,但是要考慮單次請求操作的數量,避免慢日誌。

 

 

 
小結

 

在redis使用過程中,要正視網絡往返時間,合理利用批量操作命令,減少通訊時延和redis訪問頻次。redis為了減少大量小資料CMD操作的網絡通訊時間開銷 RTT (Round Trip Time),支持多種批操作技術:

  • MSET/HMSET等都支持一次輸入多個key,LPUSH/RPUSH/SADD等命令都支持一次輸入多個value,也要註意每次運算元量不要過多,建議控制在500個以內;
  • PipeLining 樣式 可以一次輸入多個指令。redis提供一個 pipeline 的管道操作樣式,將多個指令彙總到佇列中批量執行,可以減少tcp交互產生的時間,一般情況下能夠有10%~30%不等的性能提升;
  • 更快的是Lua Script樣式,還可以包含邏輯。redis內嵌了 lua 解析器,可以執行lua 腳本,腳本可以通過eval等命令直接執行,也可以使用script load等方式上傳到服務器端的script cache中重覆使用

 

 

 

04

減少不必要的請求

案例

某業務系統,當用戶進入某個頁面時會同時請求多個接口,每個接口都會校驗用戶狀態是否有效,用戶狀態存在redis里並設置有過期時間,對於key未過期但是過期時間大於指定閾值的,需要重新設置有效時間,否則需要使用del命令刪除掉。但是部分key由於過期其實已經不存在了,所以出現部分無效del命令。用戶越多,就會有越多的無效命令。

 

 
分析

 

 

ttl命令對於key不存在的情況會傳回-2,若key不存在則不需要再呼叫del命令,可減少無效請求。

 

 

 
小結

 

redis的所有請求對於不存在的key都會有輸出傳回,合理利用傳回值處理,避免不必要的請求,提升業務吞吐量。

 

 

 

05

避免value設置過大

案例

某開發人員將一個商品集合信息序列化後用redis的字串型別儲存,使用的時候再反序列化成物件串列使用,大小超過1MB,在網絡傳輸的時候由於資料比較大會觸發拆包,會降低redis的吞吐量。

 

 
分析

 

數量比較多時可以考慮改用hash結構儲存,每一個field是商品id,value是該商品物件,如果數量較大可使用hscan獲取。

 

 

 
小結

 

String型別儘量控制在10KB以內。雖然redis對單個key可以快取的物件長度能夠支持的很大,但是實際使用場合一定要合理拆分過大的快取項,1k 基本是redis性能的一個拐點。當快取項超過10k、100k、1m性能下降會特別明顯。關於吞吐量與資料大小的關係可見下麵官方網站提供的示意圖。

 

 

吞吐量與資料大小的關係

 

在局域網環境下只要傳輸的包不超過一個 MTU(以太網下大約 1500 bytes),那麼對於 10、100、1000 bytes不同包大小的處理吞吐能力實際結果差不多。

 

 

 

06

設計規範的key名

 

 

 
可讀性

 

以業務名為前綴,用冒號分隔,可使用業務名:子業務名:id的結構命名,子業務下多單詞可再用下劃線分隔

舉例:活動系統-人拉人紅包活動-id,可命名為 ACTIVITY:INVITE_REDPACKET:001

 

 

 
簡潔性

保證語意的前提下,控制key的長度,當key較多時,記憶體占用也不容忽視

 

 

 
不包含轉義字符

不包含空格、換行、單雙引號以及其他轉義字符

 

 

07

留心禁用命令

 

keys、monitor、flushall、flushdb應當通過redis的rename機制禁掉命令,若沒有禁用,開發人員要謹慎使用。其中flushall、flushdb會清空redis資料;keys命令可能會引起慢日誌;monitor命令在開啟的情況下會降低redis的吞吐量,根據壓測結果大概會降低redis50%的吞吐量,越多客戶端開啟該命令,吞吐量下降會越多。

keys和monitor在一些必要的情況下還是有助於排查線上問題的,建議可在重命名後在必要情況下由redis相關負責人員在redis備機使用,monitor命令可借助redis-faina等腳本工具進行輔助分析,能更快排查線上ops飆升等問題。

 

 

  總      結  

本文整理出的幾點redis開發規範主要是涉及redis客戶端的使用部分,每個開發人員在使用redis開發過程中幾乎都會涉及到上述提到的幾個問題,需要多多留心,提高代碼質量,提升redis的健康度。

 

 


●編號375,輸入編號直達本文

●輸入m獲取文章目錄

推薦↓↓↓

 

Web開發

更多推薦18個技術類公眾微信

涵蓋:程式人生、演算法與資料結構、黑客技術與網絡安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。

 

    赞(0)

    分享創造快樂