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獲取執行的總時長:
隨機生成指定長度的字符串方法如下:
運行main方法三次,數據表現基本一致,下圖是運行輸出的三組數據:
第一組測試數據
第二組測試數據
第三組測試數據
根據上面三組數據生成的柱狀圖如下:
當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的描述有如下的一些規則
- 非常長的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以內,實際也和元素字節數有關)。
