Redis扛并發的能力是非常強的,所以高并發場景下經常會使用Redis,但是Redis單分片的寫入瓶頸在2w左右,讀瓶頸在10w左右,如果在超高并發下即使是集群部署Redis,單分片的Redis也是有可能扛不住的,如下圖所示:
雖然Redis做了集群部署,但是Redis的key只會存在一個分片上,此時超高并發下redis1很有可能會被打垮。那么在超高的并發如何解決某個熱key帶來的單分片被打垮的問題呢?下面聊聊Redis分key來解決這個問題的方案。
1、什么是Redis分key
Redis分key就是將一個熱點key通過拆分成若干key,然后讓這若干個key分散到Redis集群的不同節點,如下圖所示:
將熱點key拆分成3個小key,然后通過Redis的算法將這3個key分散到Redis集群的分片上(集群有多少個分片,就拆分成幾個key)。這樣由原先的一個key拆分成3個小key,在超高并發下由這3個key共同的來承擔原先一個熱點key扛的流量。
2、拆分后的key分散到集群的分片上
拆分key的思路可以很好的解決單個熱點key可能打垮Redis集群中某個分片的問題,但是我們如何保證一個小key落到一個分片上呢?首先我們來回顧一下Redis集群中key落分片的原理,如下所示的Redis的集群:
從原理上分析key落在哪個節點上是經過了兩次的映射,第一次映射是CRC16計算出來key哈希值除以16384之后得到是對應的槽,第二次映射是槽映射到redis的節點,這樣可以知道key落在哪個分片上。
根據上述的原理,我們可以通過Redis的命令來獲取Redis集群上的集群關系來計算key落在哪個分片上。我們現在為了保證一個key落在一個分片上,可以通過手動的方式來設置key,設置的過程如下:
(1)手寫第一個key_longxia,然后自己手動根據CRC16和槽映射關系之后就知道它落到了哪個節點(假設是redis0上)如下所示
2)準備第二個key(如key_longxia01),假設計算之后發現也落到了redis0上,那么我們換一個key(如key_biancheng),經過計算發現其落在redis1上,如下所示:
(3)同樣的方式,準備第三個key(如key_long),保證其可以落在redis2上即可,如下所示:
分key的時候,我們不要追求 key 是有規律的了,可以隨便加點前綴與后綴,只要保證每個小key都分散到集群的分片上即可。
通過上述的試探我們得到了3個拆分后的小key,并且這些小key可以落到集群的節點上,整理出這些拆分后的key如下所示:
3、分key的工作原理
手動嘗試出來的三個key我們寫固定到代碼中(或者放在配置中心上)。當業務請求過來之后,我們可以通過業務id與拆分出來的key數量取余數的方式映射出當前請求打到哪個key上(如key_longxia),然后通過這個可以經過redis的兩次映射找到對應的節點,找到節點后就可以操作數據了。
結論:(1)Redis分可以的原理就是將一個熱點key拆分成若干個小key后分散不集群的不同節點上(集群有幾個節點就拆分成幾個小key)(2)為保證key可以分散到集群節點上,采用的是手動嘗試的方式來獲取拆分后的小key。(3)分key的方案常用于超高并發業務場景下,如搶優惠券、實時榜單等。