緩存在咱們平常開發中佔據着舉足輕重的地位,經過緩存組件可讓咱們的系統有着多方位的提高空間。而Redis就一個表明性的緩存組件。正巧最近使用Redis比較頻繁,因此打算經過文章記錄一下在Redis開發中遇到的問題和一些開發規範。文章已發佈在Github,將會持續保持更新,歡迎star和補充git
Key的設計
易於管理
即能經過名稱大概知道所涉及業務。一般咱們會以service:characteristics來進行命名,如pubg_chat:uid:room_id的形式,這樣能夠儘量避免衝突(固然,不一樣業務使用不一樣的Redis是更好的)github
儘可能簡潔
Redis本質上是一個內存數據庫,而內存的大小是遠小於硬盤的。若是Key過大的話,會致使Redis所能存儲的內容變少。因此在平常中推薦Key可以儘量的簡介明瞭,用縮寫來代替完整的單詞redis
避免特殊字符
如逗號、換行、空格和引號等轉義字符都是不該該使用的算法
設置生命週期
- Redis不該當成爲一個永久存儲的組件,爲每個Key都設置他的過時時間
- 若是確實須要Redis永久存儲某類內容,那麼因當採用異步「續命」的方式來進行,而不該該在一開始就爲其設置永久的生命週期,避免後續須要變動時帶來的維護災難
Value的使用
規避大Key!
- Redis單線程的,它會在執行完一個命令後纔會執行其餘命令
- 首先大Key在傳輸鍵值對時,會對網絡形成壓力(帶寬問題),而且有的proxy會將大內容分片傳輸,進而再次增長了網絡傳輸時間
- 其次,如list、hash這類結構,若是使用O(n)的指令或者使用del命令,那麼會形成嚴重的阻塞
- 因此一般而言,string 類型控制在 10KB 之內,hash、list、set、zset 元素個數不要超過 5000
- ps:一般可採用hash的方式分割大key
value的壓縮
可考慮使用protobuf、MessagePack等方式進行序列化,這樣一能夠提高redis的利用率,二提升了序列化的效率,三是能提供value跨語言的能力數據庫
命令使用
避免頻繁對string作append
能夠考慮使用list進行替代數組
集合類操做
- O(n)指令應注意。對於set,zset,list,hash等集合類,應注意O(n)命令對於性能的影響。一般應該避免直接使用O(n)指令,可用HSCAN,SSCAN,ZSCAN進行漸進操做,防止命令的阻塞
- 漸進式刪除。不該該直接使用del,而應該本身寫腳本一點點的刪除
禁用危險命令
keys、flushall、flushdb......這種不用多說,一來直接Redis就懵圈了,人也楞了緩存
合理利用Pipeline模式
- 在mget大量數據時,proxy會拆包和解包,會致使proxy層的壓力增長,而pipeline模式會直接轉發。因此在批量獲取的狀況下,pipeline的效率通常都會優於mget
- 同時應該注意兩點:
- mget是原子操做,pipeline不是。因此業務上不可盲目採用
- pipeline是能夠發送不一樣命令的,固然使用lua也能夠實現這一點
避免沒必要要的指令
如部分Redis Client會有TestOnBorrow之類的探測指令,在沒有特殊要求的狀況下應當避免此類指令,以減少redis負載和網絡壓力安全
對Lua應當作特殊要求
- 全部key都應該由KEYS數組來傳遞
- 全部value都應該由ARGS數組來傳遞
- 全部key,必須在1個slot上
性能查詢指令
- slowlog get,查詢慢命令
- info commandstats,查詢執行過的命令信息,包含用時和次數等
- client list,查詢引發阻塞的命令
客戶端使用
避免混用實例
不一樣的業務線應該作到實例的拆分,避免混用致使的連鎖問題:如key重合、命令阻塞等網絡
使用鏈接池
每次使用都新建鏈接會有幾個問題:app
- 形成redis的負擔增長
- 浪費網絡資源
- 影響執行效率
- 難以維護
熔斷
Redis本質也是一個「服務」,因此熔斷機制不可少
鑑權
避免無關服務的濫用或致使數據出錯
避免做爲消息隊列
Redis其實還可以支持消息隊列的應用,但其讀寫效率是不及其餘MQ如Kafka、RabbitMQ等。且因爲其結構的設置,不太可以支撐MQ的一些主要特性,因此應當避免使用。
其餘
淘汰策略
根據⾃⾝業務類型,選好maxmemory-policy(最⼤內存淘汰策略),設置好過時時間 默認策略是volatile-lru,即超過最⼤內存後,在過時鍵中使⽤lru算法進⾏key的剔除,保證不過時數據不被 刪除,可是可能會出現OOM問題
- allkeys-lru:根據LRU算法刪除鍵,無論數據有沒有設置超時屬性,直到騰出⾜夠空間爲⽌
- allkeys-random:隨機刪除全部鍵,直到騰出⾜夠空間爲⽌。
- volatile-random:隨機刪除過時鍵,直到騰出⾜夠空間爲⽌
- volatile-ttl:根據鍵值對象的ttl屬性,刪除最近將要過時數據。若是沒有,回退到noeviction策略
- noeviction:不會剔除任何數據,拒絕全部寫⼊操做並返回客⼾端錯誤信息"(error) OOM command not allowed when used memory",此時Redis只響應讀操做
- 4.0後推出的allkey-lfu和volatile-lfu
- 能夠認爲這是對於lru算法的進一步改進
- allkey-lfu:從全部鍵中驅逐使用頻率最少的鍵
- volatile-lfu:從全部配置了過時時間的鍵中驅逐使用頻率最少的鍵
不濫用Redis事務
Redis事務不像DB的事務這麼「安全」,也不支持回滾,因此不該當過多的使用。由於這塊我沒怎麼使用過,詳見官方文檔
參考資料