假設有這樣一個使用場景,依次執行下面的5條命令
命令1:hset mall:sale:freq:ctrl:860000000000001 599055114591 1(hash結構,field表示購買的商品ID,value表示購買次數) 簡單說明: mall:sale:freq:ctrl:860000000000001是一個hash表;599055114591表示key;1表示key對應的value 命令2:hset mall:sale:freq:ctrl:860000000000001 599055114592 2 命令3:expire mall:sale:freq:ctrl:860000000000001 3127(設置過時時間) 簡單說明:給hash表mall:mall:sale:freq:ctrl:860000000000001設置過時時間 命令4:set mall:total:freq:ctrl:860000000000001 3 簡單說明:set key vlaue 命令5:expire mall:total:freq:ctrl:860000000000001 3127(設置過時時間) 簡單說明: set key 過時時間 複製代碼
執行一條命令 經歷的過程html
執行一條命令 就須要通過上面的過程,發送命令-〉命令排隊-〉命令執行-〉返回結果 那麼執行5條命令,可想而知,性能優化的空間仍是蠻大的, 下面我們來進行優化一下吧 複製代碼
命令1和命令2 合二爲一
hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2 expire mall:sale:freq:ctrl:860000000000001 3127 set mall:total:freq:ctrl:860000000000001 3 expire mall:total:freq:ctrl:860000000000001 3127 複製代碼
將命令4和命令5合二爲一 命令a: hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2 命令b: expire mall:sale:freq:ctrl:860000000000001 3127 命令c: setex mall:total:freq:ctrl:860000000000001 3127 3 複製代碼
須要注意:RedisCluster中使用pipeline時必須知足pipeline打包的全部命令key在RedisCluster的同一個slot上java
Redis 集羣使用數據分片(sharding)而非一致性哈希(consistency hashing)來實現: 一個 Redis 集羣包含 16384 個哈希槽(hash slot), 數據庫中的每一個鍵都屬於這 16384 個哈希槽的其中一個, 集羣使用公式 CRC16(key) % 16384 來計算鍵 key 屬於哪一個槽, 其中 CRC16(key) 語句用於計算鍵 key 的 CRC16 校驗和 。
集羣中的每一個節點負責處理一部分哈希槽。 舉個例子, 一個集羣能夠有三個哈希槽, 其中: 節點 A 負責處理 0 號至 5500 號哈希槽。 節點 B 負責處理 5501 號至 11000 號哈希槽。 節點 C 負責處理 11001 號至 16384 號哈希槽。 這種將哈希槽分佈到不一樣節點的作法使得用戶能夠很容易地向集羣中添加或者刪除節點。 好比說: 若是用戶將新節點 D 添加到集羣中, 那麼集羣只須要將節點 A 、B 、 C 中的某些槽移動到節點 D 就能夠了。 與此相似, 若是用戶要從集羣中移除節點 A , 那麼集羣只須要將節點 A 中的全部哈希槽移動到節點 B 和節點 C , 而後再移除空白(不包含任何哈希槽)的節點 A 就能夠了。 由於將一個哈希槽從一個節點移動到另外一個節點不會形成節點阻塞, 因此不管是添加新節點仍是移除已存在節點, 又或者改變某個節點包含的哈希槽數量, 都不會形成集羣下線。 複製代碼
由此可知 命令a和命令b在同一個slot上,命令c在另一個slot上 因此命令a和命令b用pipline來處理 複製代碼
vim pipeline.txt hmset mall:sale:freq:ctrl:860000000000001 599055114591 1 599055114592 2 expire mall:sale:freq:ctrl:860000000000001 3127 複製代碼
須要安裝下dos2unixgit
a、brew install dos2unixweb
b、unix2dos pipeline.txtredis
cat pipeline.txt | redis-cli --pipe
複製代碼
由 CRC16(key) % 16384 來計算鍵 key 屬於哪一個槽 可知,key決定了存儲在哪一個slot上,那麼使用hashtag可使得 知足部分key一致的全部key都存儲在同一個slot上spring
好比數據庫
mall:sale:freq:ctrl:{860000000000001} 只要key中有{860000000000001}這一部分,就必定落在同一個slot上vim
**注意:使用hashtag特性 不能把key的離散性變得很是差 **springboot
mall:sale:freq:ctrl:{860000000000001} 這種key仍是與用戶相關
複製代碼
mall:{sale:freq:ctrl}:860000000000001 全部的key都會落在同一個slot上,致使整個Redis集羣出現嚴重的傾斜問題 複製代碼
通過這4次優化 perfect ==> 5條Redis命令壓縮到3條Redis命令,而且3條Redis命令只須要發送一次,而且結果也一次就能所有返回性能優化
這是一組統計數據出來的數據,使用Pipeline執行速度比逐條執行要快,特別是客戶端與服務端的網絡延遲越大,性能體能越明顯
複製代碼
redis提供了mset、mget方法 但沒有提供mdel方法 能夠藉助pipeline實現
複製代碼
原生批命令是原子性,pipeline是非原子性
(原子性概念:一個事務是一個不可分割的最小工做單位,要麼都成功要麼都失敗。原子操做是指你的一個業務邏輯必須是不可拆分的. 處理一件事情要麼都成功,要麼都失敗,原子不可拆分)
原生批命令一命令多個key, 但pipeline支持多命令(存在事務),非原子性
原生批命令是服務端實現,而pipeline須要服務端與客戶端共同完成
使用pipeline組裝的命令個數不能太多,否則數據量過大,增長客戶端的等待時間,還可能形成網絡阻塞,能夠將大量命令的拆分多個小的pipeline命令完成
使用watch後, multi失效,事務失效 WATCH的機制是: 在事務EXEC命令執行時,Redis會檢查被WATCH的key, 只有被WATCH的key從WATCH起始時至今沒有發生過變動,EXEC纔會被執行。 若是WATCH的key在WATCH命令到EXEC命令之間發生過變化,則EXEC命令會返回失敗。 複製代碼
https://gitee.com/pingfanrenbiji/springboot-jedisCluster/blob/master/demo/src/main/java/com/example/pipline/PipelineTest.java
複製代碼
https://www.jianshu.com/p/8849c0b5753d http://www.gxlcms.com/redis-377198.html https://blog.csdn.net/huangbaokang/article/details/88028814 https://blog.csdn.net/w1lgy/article/details/84455579 官方文檔 : http://redisdoc.com/topic/cluster-tutorial.html?highlight=slot 複製代碼
本文使用 mdnice 排版