代碼實測:給redis中的key取一個正確的名字多么重要


redis對寫入的key長度有限制嗎?

太長的key對性能有影響嗎?

key越長對性能影響越大?

如何評估鍵長度對性能的影響?

talk is cheap, show me the code!

今天我們一起用代碼來驗證一下key的長度對redis讀取key的性能影響。

網絡環境:本地

內存:8G

redis版本:redis-5.0.7

實驗代碼如下,讀寫1000次長度為16、128、512、1024、2048、4096、9012、20000、100000長度的key獲取執行的總時長:

代碼實測:給redis中的key取一個正確的名字多么重要

 

隨機生成指定長度的字符串方法如下:

代碼實測:給redis中的key取一個正確的名字多么重要

 

運行main方法三次,數據表現基本一致,下圖是運行輸出的三組數據:

代碼實測:給redis中的key取一個正確的名字多么重要

第一組測試數據

代碼實測:給redis中的key取一個正確的名字多么重要

第二組測試數據

代碼實測:給redis中的key取一個正確的名字多么重要

第三組測試數據

根據上面三組數據生成的柱狀圖如下:

代碼實測:給redis中的key取一個正確的名字多么重要

 

當key的長度不超過1024即1kb的長度的時候,基本上對性能不造成影響,但是一旦超過1024長度,隨着key長度的增加,耗時也會隨之增加。

所以,key長度對redis讀寫性能的影響是當key長度超過1024字節!因此我們在實際開發過程中可以根據自己的key長度預估對redis是否存在性能影響。

在實際業務開發中,基本上大家的key不會超過1024字節,因此可以在命名的時候,盡量取一些能見名知義的key,不必刻意為了縮短key長度而降低key的可讀性

當有這種key就必須特別長的時候,或者不確定是否超過1024字節,我們可以對key做一次hash后取哈希值作為redis的key,這樣就可以大幅提高redis的性能了。這里推薦大家使用Murmurhash算法,算法詳情見我的文章:MurmurHash算法及應用場景

代碼實測:給redis中的key取一個正確的名字多么重要

 

redis官網對key的描述有如下的一些規則

  • 非常長的key是不推薦的。一個1024 bytes是一個非常壞的注意,不僅僅是因為內存浪費,更是因為在數據集中搜索對比的時候需要耗費更多的成本。當要處理的是匹配一個非常大的值,從內存和帶寬的角度來看,使用這個值的hash值是更好的辦法(比如使用SHA1)。
  • 特別短的key通常也是不推薦的。在寫像u100flw這樣的鍵的時候,有一個小小的要點,我們可以用user:1000:followers代替。可讀性更好,對於key對象和value對象增加的空間占用與此相比來說倒是次要的。當短的key可以很明顯減少空間占用的時候,你的工作就是找到正確的平衡。
  • 嘗試去固定一個schema。比如object-type:id是一個好主意,-和.通常用於多個字符的域,就像comment:1234:reply.to,或者comment:1234:reply-to。
  • 最大的key允許512MB

redis的一些開發規范

key命名設計

(1)【建議】: 可讀性和可管理性 以業務名(或數據庫名)為前綴(防止key沖突),用冒號分隔,比如業務名:表名:id
(2)【建議】: 簡潔性 保證語義的前提下,控制key的長度,當key較多時,內存占用也不容忽視,例如:U_O_P_HS:#userId代表用戶已經購買的商品Id的hash存儲
(3)【強制】:不要包含特殊字符
反例:包含空格、換行、單雙引號以及其他轉義字符

value設計

(1)【強制】:拒絕bigkey(防止網卡流量、慢查詢)
string類型控制在10KB以內,hash、list、set、zset元素個數不要超過5000。
反例:一個包含200萬個元素的list。非字符串的bigkey,不要使用del刪除,
使用hscan、sscan、zscan方式漸進式刪除,同時要注意防止bigkey過期時間自動刪除問題(例如一個200萬的zset設置1小時過期,會觸發del操作,造成阻塞,而且該操作不會不出現在慢查詢中(latency可查)),查找方法和刪除方法
(2)【推薦】:選擇適合的數據類型。
例如:實體類型(要合理控制和使用數據結構內存編碼優化配置,例如ziplist,但也要注意節省內存和性能之間的平衡)
正例:hmset user:1 name tom age 19 favor football
(3).【推薦】:控制key的生命周期,redis不是垃圾桶。 
建議使用expire設置過期時間(條件允許可以打散過期時間,防止集中過期),不過期的數據重點關注idletime。

命令使用

【推薦】O(N)命令關注N的數量 例如hgetall、lrange、smembers、zrange、sinter等並非不能使用,但是需要明確N的值。有遍歷的需求可以使用hscan、sscan、zscan代替。
【推薦】禁用命令 禁止線上使用keys、flushall、flushdb等,通過redis的rename機制禁掉命令,或者使用scan的方式漸進式處理。
【推薦】使用批量操作提高效率
原生命令:例如mget、mset。 非原生命令:可以使用pipeline提高效率。 但要注意控制一次批量操作的元素個數(例如500以內,實際也和元素字節數有關)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM