概述 Redis 在 3.0 之後開始支持 Cluster(集群)模式,特點如下: 支持節點的自動發現:可向集群動態添加節點,並自動融入 支持 slave-master 選舉和容錯:多個 master 宕機後,選舉出新的 master 繼續工作 線上分片:當有新的節點加入時,為新節點分配 slot ...
概述
Redis 在 3.0 之後開始支持 Cluster(集群)模式,特點如下:
- 支持節點的自動發現:可向集群動態添加節點,並自動融入
- 支持 slave-master 選舉和容錯:多個 master 宕機後,選舉出新的 master 繼續工作
- 線上分片:當有新的節點加入時,為新節點分配 slot 空間,從其他節點處獲取,並攜帶數據
搭建
以 Ubuntu 18.04.5,redis-7.0.4 為例,要想讓集群正常運作至少需要三個 master 節點,為了高可用,每個 master 節點至少要有一個 slave 節點,這裡以一臺機器的六個埠作演示,分別是 7000、7001、7002、7003、7004、7005
創建多個 redis 配置文件(以其中一個為例,區別在於埠號和部分配置文件命名)
# 開啟遠程連接
bind * -::*
# 配置埠號,每個配置文件分別配置 7001/.../7005
port 7000
# 啟用守護進程
daemonize yes
# 進程配置文件名,redis_7000/.../redis_7005
pidfile "/var/run/redis_7000.pid"
# rdb文件名,dump-7000/.../dump-7005
dbfilename dump-7000.rdb
# 開啟 AOF 持久化
appendonly yes
# aof文件名,appendonly-7000/./appendonly-7005
appendfilename "appendonly-7000.aof"
# 開啟集群模式
cluster-enabled yes
# 節點配置文件名,nodes-7000/.../nodes-7005
cluster-config-file nodes-7000.conf
# 節點超時時間
cluster-node-timeout 15000
創建 7000-7005 文件夾,把對應的配置文件放進去
指定不同配置文件啟動六個節點,例如
./redis-server 7000/redis.conf
將六個節點組合成集群,在組合之前,請確保以下條件:
- 所有節點正常啟動後
- nodes-xxx.conf 文件都正常生成
- 如果有開啟防火牆,放行 7000-7005、17000-17005 埠,前者用於客戶端通信,後者用於集群間通信
# redis會自動規劃集群部署,例如這裡會以前三個為主節點,後三個分別作從節點
redis-cli --cluster create --cluster-replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005
使用 redis-cli --cluster check 命令來查看節點信息
# 後面的ip:port使用集群任一節點即可
redis-cli --cluster check 127.0.0.1:7000
也可以通過 redis-cli 連接任一節點,使用如下命令查看節點信息
# 使用普通方式登錄,存儲數據時可能會出現MOVED重定向操作,所以應該加上-c以集群方式登錄
redis-cli -c -p 7000
# 查看節點所在集群信息
cluster nodes
一般使用 cluster nodes 命令,信息更詳細
以 7000 為例,講解每項的含義:
- id:28df8f39d35ad2ddaeddad2ef0b11c77f381a26a,節點 ID,這個值在節點啟動時創建,作為唯一標識
- ip:port:127.0.0.1:7000@17000,節點的通信地址
- flags:myself,master:逗號分割的標記位,可能的值及含義如下:
- myself:當前連接的節點
- master:節點是 master
- slave: 節點是 slave
- fail?:當前節點無法聯繫,但邏輯上是可達的(非 FAIL 狀態)
- fail:節點處於 FAIL 狀態.,大部分節點都無法與其取得聯繫,則會將該節點由 PFAIL 狀態升級為 FAIL 狀態
- handshake:還未取得信任的節點,當前正在與其進行握手
- noaddr:沒有地址的節點(No address known for this node)
- noflags:連個標記都沒有(No flags at all)
- master:28df8f39d35ad2ddaeddad2ef0b11c77f381a26a,這裡是 7004 節點的信息,因為該節點是 slave 節點,所以會列出所屬 master 節點的 ID,也就是 7000
- ping-sent:-0,最近一次發送 ping 的時間,這個時間是一個 unix 毫秒時間戳,0 代表沒有發送過
- pong-recv:1661445823000,最近一次收到pong的時間,使用 unix 時間戳表示
- config-epoch:1,節點的 epoch 值(如果該節點是從節點,則為其主節點的 epoch 值),每當節點發生失敗切換時,都會創建一個新的且遞增的 epoch 值,如果多個節點競爭同一個哈希槽,epoch 值更高的節點更容易搶奪到
- link-state:connected,集群匯流排使用的鏈接的狀態,我們使用這個鏈接與集群中其他節點進行通信,值可以是 connected 或 disconnected
- slot:0-5460,哈希槽值或者一個哈希槽範圍,有關哈希槽值的內容在下麵講解
哈希槽(slot)
Redis 集群把把所有的物理節點(向外提供服務的 master)映射到 [0 - 16383] slot 上,即所有 master 均分 16384 大小的 slot 空間,每個 master 占有一定的 slot 空間
當存儲數據時,首先會對 key 使用 CRC16 演算法進行加密,將得到的值 mod 16384,這樣一來 key 的值始終在 0-16383 之間,Redis 則根據 key 值將其放入對應範圍的節點,比如算出來的 key 值是 3000,7000 節點的 slot 空間是 [0 - 5460],那麼就會放到 7000 節點,平均集群的壓力
同理,當獲取數據時,也會對 Key 進行同樣的計算,根據得到的值去對應的節點獲取數據
註意:slot 不是值集群所能存儲數據的容量,16384 也並不是說只能存 16384 個鍵,它僅僅表示每個節點的一個存儲範圍,key 值落到那個範圍,就找對應範圍的節點服務
以之前搭建的集群為例,客戶端連接 7000 節點,存儲一個測試數據,Redis 會自動計算 Key 值,如果計算結果在 7001 節點的範圍,則重定向到 7001 節點存儲
獲取值也是同理
其他命令
向集群動態添加主節點,先啟動 7006 服務,再執行以下命令:
# redis-cli --cluster add-node [新加入節點] [原始集群中任意節點]
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
向集群動態添加從節點,先啟動 7007 服務,再執行以下命令:
# redis-cli --cluster add-node --cluster-slave [--master-id master節點id] [新加入節點] [原始集群中任意節點]
# 如果沒有指定主節點,redis會隨機給副本數少的主節點添加當前副本節點
redis-cli --cluster add-node --cluster-slave 127.0.0.1:7007 127.0.0.1:7000
這個時候我們查看集群狀態,會發現新添加的 7006 節點沒有分配 slot
沒有 slot 是不能處理數據的,所以需要重新分配集群 slot
# redis-cli --cluster reshard [原始集群中任意節點] --cluster-from [源slot節點id,多個id用逗號分隔] --cluster-to [接收slot節點id] --cluster-slots [分配slot大小]
redis-cli --cluster reshard 127.0.0.1:7000 --cluster-from 28df8f39d35ad2ddaeddad2ef0b11c77f381a26a --cluster-to a8e9320b93498f2dcdc689e61ffec73f79d3a6d6 --cluster-slots 1024
刪除節點
# redis-cli --cluster del-node [集群中任意節點] [刪除節點id]
redis-cli --cluster del-node 127.0.0.1:7000 ac949f85aa8becb811d1f0a46d18f41075e63051