Redis 鍵值設計使用總結
前言
對redis的使用,想必做過后端開發(fā)的同學都不陌生,redis為key/value非關系型數(shù)據(jù)庫,使用起來簡單高效,支持的數(shù)據(jù)類型也比較豐富,幾乎在日常開發(fā)中沒有不涉及的;
但如果對redis使用比較深入的話,還需要綜合考慮多方面的因素,比如使用redis時如何兼具高效與性能,如何設計合理的key以達到存取時最高效等等,這都是應該考慮的,下面結合redis中一個比較簡單但也容易的問題,關于redis的鍵值設計做一個全面的探討;
Redis使用中不規(guī)范的現(xiàn)象
- Redis 存儲的key命名不規(guī)范,比較隨意;
- Redis 被當成存儲庫使用,存在數(shù)據(jù)丟失風險,且無重新加載方案;
- Redis 緩存key,未設置過期時間, 緩存低頻數(shù)據(jù)占用大量內(nèi)存, 進而導致服務崩潰;
- Redis 緩存大量big key, 應用獲取時會占用大量網(wǎng)絡帶寬,刪除也容易造成阻塞;
- Redis 客戶端使用不當,導致其它客戶端連接timeout, 原因可能客戶端密碼錯誤,且沒有使用連接池,大量連接重試導致系統(tǒng)端口資源耗光;
- Redis 客戶端命令使用不當,導致大量的慢查詢,影響其它應用業(yè)務,比如在業(yè)務高峰期時使用 keys* 或flushall 這樣的命令;
Redis 使用業(yè)務場景推薦與建議
- 高并發(fā)場景:熱點數(shù)據(jù)緩存, 可提升系統(tǒng)整體響應速度,降低數(shù)據(jù)庫IO壓力 ;
- 限時場景:利用Redis expire命令設置session過期和續(xù)期、手機驗證碼等;
- 排行榜: 利用Redis list 和 sorted sets 數(shù)據(jù)結構能實現(xiàn)各種復雜的排行榜應用;
- 數(shù)據(jù)集合操作:利用Redis list、set、sorted set, 方便進行數(shù)據(jù)計算, 如交集、并集、差集等;
- 連續(xù)簽到:可以利用redis的bitmap數(shù)據(jù)結構實現(xiàn)簽到相關的業(yè)務;
- 計數(shù)器:利用Redis incr、incrby命令實現(xiàn)api調(diào)用次數(shù)統(tǒng)計, api限流等場景;
- 分布式鎖:利用 Redis 的 setnx 功能來編寫分布式的鎖, 典型開源組件比如redisson;
如何設計出優(yōu)雅的key
可以這么說,線上關于redis的性能優(yōu)化這個問題上,不合理的key的設計經(jīng)常是引發(fā)問題的根因,究其本質,就個人看到的情況來說,大多數(shù)同學在對redis使用過程中,對于key的設計幾乎是沒有什么概念的,因為大多數(shù)同學使用的場景就是 key/val ,對應的數(shù)據(jù)結構就是 字符串key/字符串val;
稍微對redis有更深入的了解的同學,在進行存儲時,可能會知道 key的設計盡量短一點,中間最好有層次感,最好以 : 進行分割 ......
那么如何才能設計出比較優(yōu)雅的key呢?下面結合小編實際使用中的經(jīng)驗以及踩過的坑,來具體談談;
一、遵循如下幾個最佳實踐約定
- 遵循基本格式:[業(yè)務名稱]:[數(shù)據(jù)名]:[id];
- key的長度不超過44字節(jié);
- 不要包含特殊字符;
關于上面幾條建議,這樣做有如下幾點好處:
- 可讀性強,比如當我們設計這樣的key結構, order:user:10,一眼看過去就知道這是關于用戶訂單相關的key;
- 方便維護管理,不同的應用,或者不同的業(yè)務采用不同的前綴,在可視化客戶端工具或者命令行中很方便進行key的查找定位;
- 避免key沖突,避免在使用過程中多個人都用userId這樣的值作為key引發(fā)的緩存key沖突;
- 更節(jié)省內(nèi)存: key是string類型,底層編碼包含int、embstr和raw三種。embstr在小于44字節(jié)使用,采用連續(xù)內(nèi)存空間,內(nèi)存占用更小;
推薦值:
- 單個key的value小于10KB;
- 對于集合類型的key,建議元素數(shù)量小于1000;
二、盡量避免bigkey
1、什么是bigkey呢
BigKey通常以Key的大小和Key中成員的數(shù)量來綜合判定,例如:
- Key本身的數(shù)據(jù)量過大:一個String類型的Key,它的值為5 MB;
- Key中的成員數(shù)過多:一個ZSET類型的Key,它的成員數(shù)量為10,000個;
- Key中成員的數(shù)據(jù)量過大:一個Hash類型的Key,它的成員數(shù)量雖然只有1,000個但這些成員的Value(值)總大小為100 MB;
2、BigKey的危害
網(wǎng)絡阻塞
- 對BigKey執(zhí)行讀請求時,少量的QPS就可能導致帶寬使用率被占滿,導致Redis實例,乃至所在物理機變慢;
數(shù)據(jù)傾斜
- BigKey所在的Redis實例內(nèi)存使用率遠超其他實例,無法使數(shù)據(jù)分片的內(nèi)存資源達到均衡;
Redis阻塞
- 對元素較多的hash、list、zset等做運算會耗時較舊,使主線程被阻塞;
CPU壓力
- 對BigKey的數(shù)據(jù)序列化和反序列化會導致CPU的使用率飆升,影響Redis實例和本機其它應用;
3、如何發(fā)現(xiàn)BigKey
在安裝的機器上執(zhí)行 redis-cli --bigkeys命令
- 利用redis-cli提供的--bigkeys參數(shù),可以遍歷分析所有key,并返回Key的整體統(tǒng)計信息與每個數(shù)據(jù)的Top1的big key;
通過scan掃描
- 編寫程序,利用scan掃描Redis中的所有key,利用strlen、hlen等命令判斷key的長度(此處不建議使用MEMORY USAGE);
使用第三方工具
- 利用第三方工具,如 Redis-Rdb-Tools 分析RDB快照文件,全面分析內(nèi)存使用情況;
使用網(wǎng)絡監(jiān)控
- 自定義工具,監(jiān)控進出Redis的網(wǎng)絡數(shù)據(jù),超出預警值時主動告警;
三、使用恰當?shù)臄?shù)據(jù)類型
正如上面所說,很多初次使用redis的同學,對于很多業(yè)務場景,都是一個key/val的簡單的結構搞定,而不會深入思考這樣做是否合理,或者說這樣做以后會不會引發(fā)相關的性能方面的問題;
對于這個問題,從根本上來說,需要深入了解并掌握redis的常用的數(shù)據(jù)類型,在這個基礎上,才能針對不同的業(yè)務場景,設計出高效的存儲存儲結構數(shù)據(jù);
讓我們思考一下,如何緩存用戶對象列表這樣的數(shù)據(jù)呢?
- 方案1:key為usrId,value為對象的序列化字符串,數(shù)據(jù)結構類似下面這樣;
優(yōu)點:存取方便,簡單粗暴,存取時只需要做下json和對象的互轉即可;
缺點:數(shù)據(jù)耦合,不夠靈活,一旦對象新增了字段或刪減了字段,緩存重建的成本非常大;
- 方案2:使用一個list結構,緩存用戶ID列表,數(shù)據(jù)結構如下;
優(yōu)點:對內(nèi)存的占用小,操作高效;
缺點:獲取到val之后,需要進一步查庫才能得到完整的對象;
方案3:使用hash結構,緩存對象,數(shù)據(jù)如下所示;
優(yōu)點:底層使用ziplist,空間占用小,可以靈活訪問對象的任意字段;
缺點:編碼上相對復雜;
Redis 緩存在實際應用中的使用建議
- 【推薦】對緩存進行預熱。在訪問數(shù)據(jù)前,應先對緩存進行預熱,避免大量請求直接進入數(shù)據(jù)存儲層;應根據(jù)業(yè)務情況劃分合適的冷熱數(shù)據(jù),對熱點數(shù)據(jù)進行預熱。如許可授權信息, apikey等;
- 【推薦】配合使用本地緩存。使用本地緩存能更穩(wěn)定、更快速地訪問到數(shù)據(jù),但在分布式架構下,要慎用本地緩存,避免造成服務器節(jié)點帶狀態(tài)。同時由于本地緩存直接占用應用服務器的資源,要避免過度占用資源導致應用節(jié)點崩潰;
- 【推薦】緩存變更策略,應先更新數(shù)據(jù)庫,再更新緩存;
- 【推薦】一次業(yè)務調(diào)用需要訪問多次redis服務端,可采用pipleline或其它批量操作方式;
- 【推薦】大List,Set,Hash,存儲的數(shù)量巨大。獲得大量元素時延遲較大阻塞其他命令.建議切割成多個小的list,set,hash;
使用業(yè)務規(guī)范
不管是redis,還是其他開發(fā)中使用到的中間件,具體到開發(fā)使用時,最好都應該提前制定出一套合理的規(guī)范,這個規(guī)范應該是大多數(shù)開發(fā)人員認可并在實踐中得到檢驗,且能有效規(guī)避一些問題的,一旦指定為規(guī)范,應該成為指導內(nèi)部開發(fā)人員日常的規(guī)則,這里提如下幾點:
- Redis 應該定位為緩存數(shù)據(jù), 不可用于存儲大規(guī)模數(shù)據(jù)(不可替代數(shù)據(jù)庫);
- Redis 適合讀多寫少場景,如存在高頻寫入,低頻查詢場景,則不推薦使用;
- 在不確定key的存活時間時,最好設置過期時間,控制 key 的生命周期;
- 應該考慮冷熱數(shù)據(jù)分離,對于查詢, 高頻次業(yè)務查詢走Redis,低頻查詢考慮走數(shù)據(jù)庫;
- Redis 有數(shù)據(jù)丟失風險,程序處理數(shù)據(jù)時,應該考慮數(shù)據(jù)丟失后能自動從數(shù)據(jù)庫加載并緩存到Redis;
- 謹慎使用O(N)命令, 如list, set, hash 數(shù)據(jù)結構操作時, hgetall、lrange、smembers、zrange等并非不能使用,優(yōu)先考慮使用 hscan、sscan、zscan 代替。
以上就是Redis 鍵值設計使用總結的詳細內(nèi)容,更多關于Redis 鍵值設計的資料請關注腳本之家其它相關文章!
相關文章
Redis創(chuàng)建并修改Lua 環(huán)境的實現(xiàn)方法
為了在Redis服務器中執(zhí)行Lua腳本, Redis在服務器內(nèi)嵌了一個Lua環(huán)境, 并對這個Lua環(huán)境進行了一系列修改,本文主要介紹了Redis創(chuàng)建并修改Lua 環(huán)境的實現(xiàn)方法,具有一定的參考價值,感興趣的可以了解一下2024-05-05redis執(zhí)行l(wèi)ua腳本的實現(xiàn)方法
redis在2.6推出了腳本功能,允許開發(fā)者使用Lua語言編寫腳本傳到redis中執(zhí)行。本文就介紹了redis執(zhí)行l(wèi)ua腳本的實現(xiàn)方法,感興趣的可以了解一下2021-11-11SpringBoot整合Mybatis-plus和Redis實現(xiàn)投票功能
投票功能是一個非常常見的Web應用場景,這篇文章將為大家介紹一下如何將Redis和Mybatis-plus整合到SpringBoot中,實現(xiàn)投票功能,感興趣的可以了解一下2023-05-05redis?sentinel監(jiān)控高可用集群實現(xiàn)的配置步驟
這篇文章主要介紹了redis?sentinel監(jiān)控高可用集群實現(xiàn)的配置步驟,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2022-04-04