將新增的6387節點(空槽號)作為master節點加入原集群
Redis—9—集群(cluster)
是什么
定義
? 由于數據量過大,單個Master復制集難以承擔,因此需要對多個復制集進行集群,形成水平擴展每個復制集只負責存儲整個數據集的一部分,這就是Redis 的集群,其作用是提供在多個Redis節點間共享數據的程序集。
Redist集群是一個提供在多個Redis節點間共享數據的程序集。
Redis集群可以支持多個Master。
能干嗎
-
Redis集群支持多個Master,每個Master又可以掛載多個Slave。
讀寫分離 支持數據的高可用 支持海量數據的讀寫存儲操作
-
由于Cluster自帶Sentinel的故障轉移機制,內置了高可用的支持,無需再去使用哨兵功能。
-
客戶端與Redis的節點連接,不再需要連接集群中所有的節點,只需要任意連接集群中的一個可用節點即可。
-
槽位slot負責分配到各個物理服務節點,由對應的集群來負責維護節點、插槽和數據之間的關系。
集群算法-分片-槽位slot
Redis集群的槽位slot
key通過CRC16來計算得到slot槽位進行存放
Redis集群的分片
分片是什么?
使用Redis集群時我們會將存儲的數據分散到多臺redis機器上,這稱為分片。簡言之,集群中的每個Redis實例都被認為是整個數據的一個分片。
如何找到給定key的分片?
為了找到給定key的分片,我們對key進行CRC16(key)算法處理并通過對總分片數量取模。然后使用確定性哈希函數,這意味著給定的key將多次始終映射到同一個分片,我們可以推斷將來讀取特點key的位置。
它倆的優勢
最大優勢,方便擴縮容和數據分派查找
這種結構很容易添加或者刪除節點,比如如果我想新添加個節點D,我需要從節點ABC中的部分槽到D上,如果我想移除節點A,需要將A中的槽移到B或者C節點上,然后將沒有任何槽的A節點從集群中移除即可,由于從一個節點將哈希槽移動到另一個節點并不會停止服務,所以無論添加刪除或者改變某個節點的哈希槽的數量都不會造成集群不可用的狀態。
slot槽位映射,一般業界有3中解決方案
1,哈希取余分區
2,一致性哈希算法分區
是什么
為了解決分布式緩存數據變動和映射問題,某個機器宕機了,分母數量改變了,自然取余數不ok了。
能干嗎
提出一致性Hash解決方案
目的是當服務器個數發生變動時,盡量減少影響客戶端到服務器的映射關系。
三大步驟
算法構建一致性哈希環
服務器IP節點映射
key落到服務器的落鍵規則
優點:
缺點:一致性哈希算法的數據傾斜問題
一致性Hash算法在服務節點太少時,容易因為節點分布不均勻而造成數據傾斜(被緩存的對象大部分集中緩存在某一臺服務器上)問題,例如系統中只有兩臺服務器。
小總結
為了在節點數目發生改變時盡可能少的遷移數據將所有的存儲節點排列在首尾相接的Hash環上,每個key在計算Hash后會順時針找到臨近的存儲節點存放。而當有節點加入或退出時僅影響該節點在Hash環上順時針相鄰的后續節點。優點
加入和刪除節點只影響哈希環中順時針方向的相鄰的節點,對其他節點無影響。缺點
數據的分布和節點的位置有關,因為這些節點不是均勻的分布在哈希環上的,所有數據在進行存儲時達不到均勻分布的效果。
3,哈希槽分區
是什么
HASH_SLOT = CRC16(key) mod 16384
-
為什么出現
為了解決一致性哈希算法的數據傾斜問題
哈希槽實質上就是一個數組,數組[0,2^14-1]形成hash slot空間。 2^14=16384
-
能干什么
-
解決均勻分配的問題,**在數據和節點之間又加入了一層,把這層成為哈希槽(slot),用于管理數據和節點之間的關系,**現在就相當于節點上方的是槽,槽里放的是數據。
槽解決的是粒度問題,相當于把粒度變大了,這樣便于數據移動。哈希解決的是映射問題,使用key的哈希值來計算所在的槽,便于數據分配。
-
多少個Hash槽
一個集群只能有16384個槽,編號0-16383.這些槽會分配給集群中的所有主節點,分配策略沒有要求。 集群會記錄節點和槽的對應關系,解決了節點和槽的關系后,接下來就需要對key求哈希值,然后對16384取模,余數是幾key就落入相應的槽里。 Hash_SLOT = CRC16(key) mod 16384。以槽為單位移動數據,因為槽的數目是固定的,處理起來比較容易,這樣數據移動問題就解決了。
經典面試題:為什么redis集群的最大槽數是16384個?
① 如果槽位為65536,發送心跳信息的消息頭達8k,發送的心跳包過于龐大。在消息頭中最占空間的是myslots[CLUSTER_SLOTS/8]。當槽位為65536時,這塊的大小是:65536÷8÷1024 = 8kb在消息頭中最占空間的是myslots[CLUSTER_SLOTS/8]。當槽位為65536時,這塊的大小是:16384÷8÷1024 = 2kb因為每秒鐘,redis節點需要發送一定數量的ping消息作為心跳包,如果槽位為65536,這個ping消息的消息頭太大了,浪費帶寬。② redis的集群主節點數量基本上不可能超過1000個。集群節點越多,心跳包的消息體內攜帶的數據越多。如果節點過1000個,也會導致網絡擁堵。因此redis作者不建議redis cluster節點數量超過1000個。那么,對于節點數在1000以內的redis cluster集群,16384個槽位夠用了。沒有必要拓展到65536個。③槽位越小,節點少的情況下,壓縮比高,容易傳輸Redis主節點的配置信息中它所負責的哈希槽是通過一張bitmap的形式來保存到的,在傳輸過程中會對bitmap進行壓縮,但是如果bitmap的填充率slots/N 很高的話(N表示節點數),bitmap的壓縮率就很低。如果節點數很少,而哈希槽數量很多的話,bitmap的壓縮率就很低。
Redis集群不保證強一致性,這意味著在特定的條件下,Redis集群可能會丟掉一些被系統收到的寫入請求命令。(沒有來得及同步就宕機)
集群環境案例步驟
1,3主3從redis集群配置
找3臺真實虛擬機,各自創建 mkdir -p /myredis/cluster
新建6個獨立的redis實例服務 6381 6382 在一號機器 master slave ip 192.168.137.132vim /myredis/cluster.redisCluster6381.confvim /myredis/cluster.redisCluster6382.conf6383 6384 在二號機器 master slave ip 192.168.137.135vim /myredis/cluster.redisCluster6383.confvim /myredis/cluster.redisCluster6384.conf6385 6386 在三號機器 master slave ip 192.168.137.136vim /myredis/cluster.redisCluster6385.confvim /myredis/cluster.redisCluster6386.conf啟動6臺redis主機實例redis-server /myredis/cluster/redisCluster6381.conf...redis-server /myredis/cluster/redisCluster6386.conf
通過redis-cli命令為6臺機器構建集群關系
redis-cli -a 924721 --cluster create --cluster-replicas 1 192.168.137.132:6381 192.168.137.132:6382 192.168.137.135:6383 192.168.137.135:6384 192.168.137.136:6385 192.168.137.136:6386--cluster create 創建集群--cluster-replicas 1 表示為每個master創建一個slave節點鏈接進入6381作為切入點,查看并檢驗集群狀態cluster nodes 查看集群節點
cluster info 查看某一個節點環境配置
新建6個獨立的redis實例服務
通過redis-cli命令為6臺機器構建集群關系
配置文件
bind 0.0.0.0 服務監聽地址,用于客戶端連接,默認本機地址
daemonize yes 是否以后臺daemon方式運行
protected-mode no安全保護模式
port 6381 端口
logfile "/myredis/cluster/cluster6381.log" 日志文件路徑
pidfile "/myredis/cluster/cluster6381.pid" pid文件路徑
dir /myredis/cluster 工作目錄
dbfilename dump6381.rdb 快照RDB持久化
appendonly yes 日志AOF持久化
appendfilename "appendonly6381.aof"
requirepass 924721
masterauth 924721==========================cluster-enabled yes 打開集群
cluster-config-file nodes-6381.conf 集群配置文件
cluster-node timeout 500 集群超時時間
? 真實情況master下邊的slave不一定如圖正好對應
2,3主3從redis集群讀寫
對比6381新增兩個key,查看效果,發現有報錯
為什么報錯
如何解決
防止路由失效加參數-c并新增兩個key
redis-cli -a 924721 -p 6381 -c
重新查看集群信息
查看某個key該屬于對應的槽位值
cluster keyslot 鍵名稱
3,主從容錯切換遷移案例
主6381和從機切換,先停止主機6381,查看對應的真實從機上位
再次啥看集群信息,本次6381主6384從
發現6384主,6381從
隨后,6381原來的主機回來了,不會上位。
集群不保證數據一致性100%ok,一定會有數據丟失情況。
Redis集群不保證強一致性
手動故障轉移 or 節點從屬調整該如何處理?
上面一換后6381、6384主從對調了,和原始設計圖不一樣了,該如何?
重新登錄6381機器
常用命令 cluster failover
4,主從擴容案例
新建6387、6388兩個服務實例配置文件+新建后啟動
啟動87、88兩個新的節點實例,此時他們自己都是master
redis-server redisCluster6387.conf
redis-server redisCluster6388.conf
將新增的6387節點(空槽號)作為master節點加入原集群redis-cli -a 924721 --cluster add-node 192.168.137.136:6387(要加入的IP) 192.168.137.132:6381(目標集群IP)6387就是將要作為master新增節點6381就是原來集群節點里面的領路人,相當于6387拜拜6381的碼頭從而找到組織加入集群檢查集群情況第一次redis-cli -a 924721 --cluster check 192.168.137.132:6381重新分派槽號(reshard)redis-cli -a 924721 --cluster reshard IP地址:端口號redis-cli -a 924721 --cluster reshard 192.168.137.132:6381How many slots do you want to move (from 1 to 16384)? 平均主義:16384/集群數What is the receiving node ID?(需要加入的mid)Source node #1:all(全部接收)檢查集群情況第二次
為主節點6387分配從節點6388redis-cli -a 924721 --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主機節點IDredis-cli -a 924721 --cluster add-node 192.168.137.136:6388 192.168.137.132:6381 --cluster-slave --cluster-master-id 4e5a07db4676c08902684f9d91c4f816f348fea8
檢查集群情況第三次
將新增的6387節點(空槽號)作為master節點加入原集群
檢查集群情況第一次
檢查集群情況第二次
為什么6387是3個新的區間,以前的還是連續?
重新分配成本太高,所以前3家各自勻出來一部分,從6381、6376、6375三個舊節點分別勻出1364個坑位給新節點6387
為主節點6387分配從節點6388
檢查集群情況第三次
5,主從縮容案例
目的:6387和6388下線
檢查集群情況第一次,先獲得從節點6388的節點ID
從集群中將4號從節點6388刪除redis-cli -a 924721 --cluster del-node ip:從機端口 從機6388節點IDredis-cli -a 924721 --cluster del-node 192.168.137.136:6388 ed0100414fd152170e4d4701c025c6feb581be17將6387的槽號清空,重新分配,本例將清出來的槽號都給6381redis-cli -a 924721 --cluster reshard 192.168.137.132:6381檢查集群情況第二次4096個槽位都指給6381,它變成了8192個槽位,相當于全部都給6381了,不然要輸入3次,一鍋端將6387刪除redis-cli -a 924721 --cluster del-node 192.168.137.136:6387 4e5a07db4676c08902684f9d91c4f816f348fea8檢查集群情況第三次,6387/6388被徹底去除
從集群中將4號從節點6388刪除
將6387的槽號清空,重新分配,本例將清出來的槽號都給6381
例子:
本機:
檢查集群情況第二次
將6387刪除
集群常用命令和CRC16算法分析
不在同一個slot槽位下的多鍵操作支持不好,通識占位符登場
Redis集群有16384個哈希槽,每個key通過CRC16校驗之后對16384取模來決定放置哪個槽。集群的每個節點負責一部分hash槽
常用命令
占位符
CRC源碼淺談
常用命令
? 集群是否完整才能對外提供服務
? cluster-require-full-coverage
? cluster countkeysinslot 槽位數字編號
ckVyV6F-1719974834141)]
集群常用命令和CRC16算法分析
不在同一個slot槽位下的多鍵操作支持不好,通識占位符登場
Redis集群有16384個哈希槽,每個key通過CRC16校驗之后對16384取模來決定放置哪個槽。集群的每個節點負責一部分hash槽
常用命令
占位符
[外鏈圖片轉存中…(img-KPO3qqb4-1719974834141)]
[外鏈圖片轉存中…(img-dG5dqv3z-1719974834142)]
CRC源碼淺談
[外鏈圖片轉存中…(img-UJNUmDEl-1719974834142)]
常用命令
? 集群是否完整才能對外提供服務
? cluster-require-full-coverage
[外鏈圖片轉存中…(img-CaP4fIic-1719974834143)]
? cluster countkeysinslot 槽位數字編號
? cluster keyslot 鍵名稱