Redis集群節點擴容及其 Redis 哈希槽


Redis 集群中內置了 16384 個哈希槽,當需要在 Redis 集群中放置一個 key-value

 

時,redis 先對 key 使用 crc16 算法算出一個結果,然后把結果對 16384 求余數,

這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,redis 會根據節點數量大

致均等的將哈希槽映射到不同的節點。

Redis 集群沒有使用一致性hash, 而是引入了哈希槽的概念。

Redis 集群有16384個哈希槽,每個key通過CRC16校驗后對16384取模來決定放置哪個槽.集群的每個節點負責一部分hash槽。這種結構很容易添加或者刪除節點,並且無論是添加刪除或者修改某一個節點,都不會造成集群不可用的狀態。

使用哈希槽的好處就在於可以方便的添加或移除節點。

當需要增加節點時,只需要把其他節點的某些哈希槽挪到新節點就可以了;

當需要移除節點時,只需要把移除節點上的哈希槽挪到其他節點就行了;

在這一點上,我們以后新增或移除節點的時候不用先停掉所有的 redis 服務。

 

 

"用了哈希槽的概念,而沒有用一致性哈希算法,不都是哈希么?這樣做的原因是為什么呢?"
Redis Cluster是自己做的crc16的簡單hash算法,沒有用一致性hash。Redis的作者認為它的crc16(key) mod 16384的效果已經不錯了,雖然沒有一致性hash靈活,但實現很簡單,節點增刪時處理起來也很方便。

"為了動態增刪節點的時候,不至於丟失數據么?"
節點增刪時不丟失數據和hash算法沒什么關系,不丟失數據要求的是一份數據有多個副本。

“還有集群總共有2的14次方,16384個哈希槽,那么每一個哈希槽中存的key 和 value是什么?”
當你往Redis Cluster中加入一個Key時,會根據crc16(key) mod 16384計算這個key應該分布到哪個hash slot中,一個hash slot中會有很多key和value。你可以理解成表的分區,使用單節點時的redis時只有一個表,所有的key都放在這個表里;

改用Redis Cluster以后會自動為你生成16384個分區表,你insert數據時會根據上面的簡單算法來決定你的key應該存在哪個分區,每個分區里有很多key。

 

 

 

[架構描述]

 

redis

組件版本:

redis:5.0.8

節點架構:

3主3從、6主機

擴容后架構:

6主6從、12主機

 

[問題描述]

 

Redis(RemoteDictionary Server ),即遠程字典服務,是一個開源的使用ANSIC語言編寫、支持網絡、可基於內存亦可持久化的日志型、Key-Value數據庫,並提供多種語言的API。

 

redis是一個key-value存儲系統,支持存儲的value類型包括string(字符串)、list(鏈表)、set(集合)、zset(sortedset--有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。

 

某業務系統采用rediscluster架構,由於數據量的增長導致部分數據還未過期時就被redis最大內存限制給刪除掉,所以業務在當前三柱三從架構無法滿足業務數據量持續增長的情況,需要擴容節點至六主六從。

 

[結構及詳細說明]

 

Redis集群大致架構圖:

一組RedisCluster是由多個Redis實例組成,官方推薦使用6實例,其中3個為主節點,3個為從結點。一旦有主節點發生故障的時候,RedisCluster可以選舉出對應的從結點成為新的主節點,繼續對外服務,從而保證服務的高可用性。那么對於客戶端來說,知道知道對應的key是要路由到哪一個節點呢?原來,RedisCluster把所有的數據划分為16384個不同的槽位,可以根據機器的性能把不同的槽位分配給不同的Redis實例,對於Redis實例來說,他們只會存儲部門的Redis數據,當然,槽的數據是可以遷移的,不同的實例之間,可以通過一定的協議,進行數據遷移。

 

需要把3主3從擴容為6主6從,就需要增加6個節點,依次添加3個主節點hash槽,再添加3個從節點手動分配給主節點。

 

 

[操作過程]

 

1、創建節點

復制原有集群節點的配置文件更改端口目錄等然后再啟動redis,要添加6個節點需創建6個節點並啟動:

./redis-server../6001/redis.conf

./redis-server../6002/redis.conf

./redis-server../6003/redis.conf

./redis-server../6004/redis.conf

./redis-server../6005/redis.conf

./redis-server../6006/redis.conf

 

2、添加主節點

第一個ip:port為需要添加的節點ip和端口,第二個ip:port為當前集群中的節點和端口;先后執行以下命令:

./redis-cli--cluster add-node 192.168.8.20:6001 192.168.8.10:7001 -a 123456

./redis-cli--cluster add-node 192.168.8.21:7002 192.168.8.10:7001 -a 123456

……

 

3、分配hash槽

新添加的節點沒有哈希槽,並不能正常存儲數據,需要給新添加的節點分配哈希槽。

 

  1. 重新分配哈希槽

./redis-cli--cluster reshard  ip:port -a passwd

 

  1. 輸入要分配多少個哈希槽(數量)

 

  1. 輸入指定要分配哈希槽的節點ID

 

  1. 選擇需要分配的哈希槽來源

輸入all需要分配給目標節點的哈希槽來着當前集群的其他主節點(每個節點拿出的數量為集群自動決定)

 

分配哈希槽有兩種方式

(1)將所有節點用作哈希槽的源節點。

(2)在指定的節點拿出指定數量的哈希槽分配到目標節點:

 

4、添加從節點

添加6004節點(slave的添加方法,master為7004)

#節點ID是主節點的ID

#192.168.8.20:6004 是新加的從節點

#192.168.8.10:7004 作為從節點的主節點

 

./redis-cli--cluster add-node --cluster-slave --cluster-master-idxxxxxxxxxxxxxxxxxxx 192.168.8.20:6004 192.168.8.10:7004

 

[總結]

 

1、redis擴容一般有兩種方法,一種是在線擴容,一種是離線擴容,從業務的角度來說,在線擴容是最方便的方法,但在線擴容有個問題是,過程中如果某個槽正在操作會導致遷移槽是發送錯誤,需要人工干預。

 

2、離線擴容是比較快速的方法,人工干預比較少由集群自動分配哈希槽,缺點是需停掉業務。

 

3、一般來說業務上線前會對redis緩存數據量有一個預估,從而對架構的硬件配置有個預估,就不會產生擴容這個操作,但往往業務數據量是一個動態的,無法預估的,所以需要通過擴容節點的操作慢在業務的需求,需要保證擴容過程正保證數據的正確性。

 

 


免責聲明!

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



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