1. 程式人生 > >Redis架構第四天:Redis Cluster的理論+實踐總結

Redis架構第四天:Redis Cluster的理論+實踐總結

Redis集群 RedisCluster 實踐總結

1.怎麽才能夠突破單機瓶頸,讓redis支撐海量數據
支撐N個redis master node,每個master node都可以掛載多個slave node
多master + 讀寫分離 + 高可用

對比replication+sentinal:
replication+sentinal:數據量很少,主要承載高並發場景,提高吞吐量,保證redis的高可用性
reids cluster:海量數據+高並發+高可用

2.數據分布算法
redis cluster架構中,開放兩個端口,例如6379,另一個16379,16379是用來通信的,集群總線,用來進行故障檢測,配置更新,故障轉移授權
redis cluster的hash slot算法:hash slot和matser掛鉤:hash算法的其中之一而已,key--->index。 共有16384個hash slot,平均分布在各個master,

數據和hash slot掛鉤: 對每個key計算CRC16值,然後對16384取模,可以獲取key對應的hash slot
移動hash slot的成本是非常低的

3.redis cluster常識:
1>redis cluster: 自動,master+slave復制和讀寫分離,master+slave高可用和主備切換,支持多個master的hash slot支持數據分布式存儲

redis cluster管理工具redis-trib.rb詳情:https://blog.csdn.net/huwei2003/article/details/50973967

4.redis cluster簡單部署和安裝

1>在3臺機器上啟動6個redis實例

創建文件夾 cluster管理的配置文件 日誌文件 dump 可執行文件
mkdir -p /etc/redis-cluster
mkdir -p /var/log/redis
mkdir -p /var/redis/7001
mkdir -p /var/redis/7002
mkdir -p /var/redis/7003
mkdir -p /var/redis/7004
mkdir -p /var/redis/7005
mkdir -p /var/redis/7006
mkdir -p /etc/redis

參考其中的一個配置:
port 7001
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7001.conf

cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7001.pid
dir /var/redis/7001
logfile /var/log/redis/7001.log
bind 192.168.31.187
appendonly yes

在/etc/redis下放6個配置文件,分別為: 7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf

在/etc/init.d下,放6個啟動腳本,分別為: redis_7001, redis_7002, redis_7003, redis_7004, redis_7005, redis_7006

2>創建集群
強烈推薦博客 redis集群部署及踩過的坑:https://blog.csdn.net/lsxf_xin/article/details/79442198 寫的很詳細

遇到的問題:
redis requires Ruby version >= 2.2.2問題
解決參考地址:https://www.cnblogs.com/carryping/p/7447823.html

問題中的問題:GPG version 2.1.17 have a bug which cause failures during fetching keys from remote server. Please downgrade or upgrade to newer version (if available) or use the second method described above.
詳見博客:https://blog.csdn.net/lsxf_xin/article/details/79442198

redis-trib.rb create --replicas 1 172.16.55.133:7001 172.16.55.133:7002 172.16.55.134:7003 172.16.55.134:7004 172.16.55.135:7005 172.16.55.135:7006

success message:
Using 3 masters:
172.16.55.133:7001
172.16.55.134:7003
172.16.55.135:7005
Adding replica 172.16.55.134:7004 to 172.16.55.133:7001
Adding replica 172.16.55.135:7006 to 172.16.55.134:7003
Adding replica 172.16.55.133:7002 to 172.16.55.135:7005
....

4.驗證cluster
1>高可用
殺死matser,看下slave是否切換,再回復過來,看原先master是否變成slave
2>redis cluster的時候,就沒有所謂的讀寫分離的概念了
matser的橫向擴展:達到提高吞吐量的效果

5.認知
什麽叫做多master的寫入,就是每條數據只能存在於一個master上,不同的master負責存儲不同的數據,分布式的數據存儲

100w條數據,5個master,每個master就負責存儲20w條數據,分布式數據存儲

大型的java系統架構,還專註在大數據系統架構,分布式,分布式存儲,hadoop hdfs,分布式資源調度,hadoop yarn,分布式計算,hadoop mapreduce/hive
分布式的nosql數據庫,hbase,分布式的協調,zookeeper,分布式通用計算引擎,spark,分布式的實時計算引擎,storm -----路漫漫其修遠兮,吾將上下而求索

你在redis cluster寫入數據的時候,其實是你可以將請求發送到任意一個master上去執行
但是,每個master都會計算這個key對應的CRC16值,然後對16384個hashslot取模,找到key對應的hashslot,找到hashslot對應的master
如果對應的master就在自己本地的話,set mykey1 v1,mykey1這個key對應的hashslot就在自己本地,那麽自己就處理掉了
但是如果計算出來的hashslot在其他master上,那麽就會給客戶端返回一個moved error,告訴你,你得到哪個master上去執行這條寫入的命令

高並發、高可用、高性能、可擴展、分布式系統

6.擴容
1>單機情況下:讀吞吐量10w/s,寫吞吐量6w/s,和當前redis的存儲的容量有關啊
單機情況下,容量6g,8g
水平擴容,成倍

2>redis-trib腳本的簡單實用 CRUD
redis-trib.rb推薦博客:https://blog.csdn.net/huwei2003/article/details/50973967

添加主節點: redis-trib.rb add-node 192.168.31.227:7007 192.168.31.187:7001 將數據進行平分

reshared一些數據:redis-trib.rb reshard 192.168.31.187:7001 重新分配數據
How many slots do you want to move (from 1 to 16384)? 1
What is the receiving node ID?
*** The specified node is not known or not a master, please retry.
What is the receiving node ID?

刪除node:
先將數據轉移 redis-trib.rb del-node 192.168.31.187:7001 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db
當你清空了一個master的hashslot時,redis cluster就會自動將其slave掛載到其他master上去

添加slave節點:redis-trib.rb add-node --slave --master-id 28927912ea0d59f6b790a50cf606602a5ee48108 192.168.31.227:7008 192.168.31.187:7001
。。。

7.增加冗余slave,slave自動遷移
比如現在有10個master,每個有1個slave,然後新增了3個slave作為冗余,有的master就有2個slave了,有的master出現了salve冗余
如果某個master的slave掛了,那麽redis cluster會自動遷移一個冗余的slave給那個master
只要多加一些冗余的slave就可以了
為了避免的場景,就是說,如果你每個master只有一個slave,萬一說一個slave死了,然後很快,master也死了,那可用性還是降低了
但是如果你給整個集群掛載了一些冗余slave,那麽某個master的slave死了,冗余的slave會被自動遷移過去,作為master的新slave,此時即使那個master也死了
還是有一個slave會切換成master的
之前有一個master是有冗余slave的,直接讓其他master其中的一個slave死掉,然後看有冗余slave會不會自動掛載到那個master
master NodeId:fbf899c61190cb7fc4cf75c197ed787d929bea29
實驗success

-----------------------------------------------------------------理論知識----------------------------------------------------------------------------------------------

8.節點間的內部通信機制 cluster理論知識
1、基礎通信原理

(1)redis cluster節點間采取gossip協議進行通信
跟集中式不同,不是將集群元數據(節點信息,故障,等等)集中存儲在某個節點上,而是互相之間不斷通信,保持整個集群所有節點的數據是完整的
維護集群的元數據用得,集中式,一種叫做gossip
集中式:好處在於,元數據的更新和讀取,時效性非常好,一旦元數據出現了變更,立即就更新到集中式的存儲中,其他節點讀取的時候立即就可以感知到; 不好在於,所有的元數據的跟新壓力全部集中在一個地方,可能會導致元數據的存儲有壓力
gossip:好處在於,元數據的更新比較分散,不是集中在一個地方,更新請求會陸陸續續,打到所有節點上去更新,有一定的延時,降低了壓力; 缺點,元數據更新有延時,可能導致集群的一些操作會有一些滯後
我們剛才做reshard,去做另外一個操作,會發現說,configuration error,達成一致

(2)10000端口
每個節點都有一個專門用於節點間通信的端口,就是自己提供服務的端口號+10000,比如7001,那麽用於節點間通信的就是17001端口
每隔節點每隔一段時間都會往另外幾個節點發送ping消息,同時其他幾點接收到ping之後返回pong

(3)交換的信息

故障信息,節點的增加和移除,hash slot信息,等等

2、gossip協議

gossip協議包含多種消息,包括ping,pong,meet,fail,等等
meet: 某個節點發送meet給新加入的節點,讓新節點加入集群中,然後新節點就會開始與其他節點進行通信
redis-trib.rb add-node
其實內部就是發送了一個gossip meet消息,給新加入的節點,通知那個節點去加入我們的集群
ping: 每個節點都會頻繁給其他節點發送ping,其中包含自己的狀態還有自己維護的集群元數據,互相通過ping交換元數據
每個節點每秒都會頻繁發送ping給其他的集群,ping,頻繁的互相之間交換數據,互相進行元數據的更新
pong: 返回ping和meet,包含自己的狀態和其他信息,也可以用於信息廣播和更新
fail: 某個節點判斷另一個節點fail之後,就發送fail給其他節點,通知其他節點,指定的節點宕機了

3、ping消息深入

ping很頻繁,而且要攜帶一些元數據,所以可能會加重網絡負擔
每個節點每秒會執行10次ping,每次會選擇5個最久沒有通信的其他節點
當然如果發現某個節點通信延時達到了cluster_node_timeout / 2,那麽立即發送ping,避免數據交換延時過長,落後的時間太長了
比如說,兩個節點之間都10分鐘沒有交換數據了,那麽整個集群處於嚴重的元數據不一致的情況,就會有問題
所以cluster_node_timeout可以調節,如果調節比較大,那麽會降低發送的頻率
每次ping,一個是帶上自己節點的信息,還有就是帶上1/10其他節點的信息,發送出去,進行數據交換
至少包含3個其他節點的信息,最多包含總節點-2個其他節點的信息


二、面向集群的jedis內部實現原理

開發,jedis,redis的java client客戶端,redis cluster,jedis cluster api
jedis cluster api與redis cluster集×××互的一些基本原理
1、基於重定向的客戶端
redis-cli -c,自動重定向
(1)請求重定向
客戶端可能會挑選任意一個redis實例去發送命令,每個redis實例接收到命令,都會計算key對應的hash slot
如果在本地就在本地處理,否則返回moved給客戶端,讓客戶端進行重定向
cluster keyslot mykey,可以查看一個key對應的hash slot是什麽
用redis-cli的時候,可以加入-c參數,支持自動的請求重定向,redis-cli接收到moved之後,會自動重定向到對應的節點執行命令

(2)計算hash slot

計算hash slot的算法,就是根據key計算CRC16值,然後對16384取模,拿到對應的hash slot
用hash tag可以手動指定key對應的slot,同一個hash tag下的key,都會在一個hash slot中,比如set mykey1:{100}和set mykey2:{100}

(3)hash slot查找
節點間通過gossip協議進行數據交換,就知道每個hash slot在哪個節點上

2、smart jedis

(1)什麽是smart jedis
基於重定向的客戶端,很消耗網絡IO,因為大部分情況下,可能都會出現一次請求重定向,才能找到正確的節點
所以大部分的客戶端,比如java redis客戶端,就是jedis,都是smart的
本地維護一份hashslot -> node的映射表,緩存,大部分情況下,直接走本地緩存就可以找到hashslot -> node,不需要通過節點進行moved重定向

(2)JedisCluster的工作原理

在JedisCluster初始化的時候,就會隨機選擇一個node,初始化hashslot -> node映射表,同時為每個節點創建一個JedisPool連接池
每次基於JedisCluster執行操作,首先JedisCluster都會在本地計算key的hashslot,然後在本地映射表找到對應的節點
如果那個node正好還是持有那個hashslot,那麽就ok; 如果說進行了reshard這樣的操作,可能hashslot已經不在那個node上了,就會返回moved
如果JedisCluter API發現對應的節點返回moved,那麽利用該節點的元數據,更新本地的hashslot -> node映射表緩存
重復上面幾個步驟,直到找到對應的節點,如果重試超過5次,那麽就報錯,JedisClusterMaxRedirectionException
jedis老版本,可能會出現在集群某個節點故障還沒完成自動切換恢復時,頻繁更新hash slot,頻繁ping節點檢查活躍,導致大量網絡IO開銷
jedis最新版本,對於這些過度的hash slot更新和ping,都進行了優化,避免了類似問題

(3)hashslot遷移和ask重定向

如果hash slot正在遷移,那麽會返回ask重定向給jedis
jedis接收到ask重定向之後,會重新定位到目標節點去執行,但是因為ask發生在hash slot遷移過程中,所以JedisCluster API收到ask是不會更新hashslot本地緩存
已經可以確定說,hashslot已經遷移完了,moved是會更新本地hashslot->node映射表緩存的


三、高可用性與主備切換原理

redis cluster的高可用的原理,幾乎跟哨兵是類似的

1、判斷節點宕機

如果一個節點認為另外一個節點宕機,那麽就是pfail,主觀宕機
如果多個節點都認為另外一個節點宕機了,那麽就是fail,客觀宕機,跟哨兵的原理幾乎一樣,sdown,odown
在cluster-node-timeout內,某個節點一直沒有返回pong,那麽就被認為pfail
如果一個節點認為某個節點pfail了,那麽會在gossip ping消息中,ping給其他節點,如果超過半數的節點都認為pfail了,那麽就會變成fail

2、從節點過濾

對宕機的master node,從其所有的slave node中,選擇一個切換成master node
檢查每個slave node與master node斷開連接的時間,如果超過了cluster-node-timeout * cluster-slave-validity-factor,那麽就沒有資格切換成master
這個也是跟哨兵是一樣的,從節點超時過濾的步驟

3、從節點選舉

哨兵:對所有從節點進行排序,slave priority,offset,run id
每個從節點,都根據自己對master復制數據的offset,來設置一個選舉時間,offset越大(復制數據越多)的從節點,選舉時間越靠前,優先進行選舉
所有的master node開始slave選舉投票,給要進行選舉的slave進行投票,如果大部分master node(N/2 + 1)都投票給了某個從節點,那麽選舉通過,那個從節點可以切換成master
從節點執行主備切換,從節點切換為主節點

4、與哨兵比較

整個流程跟哨兵相比,非常類似,所以說,redis cluster功能強大,直接集成了replication和sentinal的功能
沒有辦法去給大家深入講解redis底層的設計的細節,核心原理和設計的細節,那個除非單獨開一門課,redis底層原理深度剖析,redis源碼
對於咱們這個架構課來說,主要關註的是架構,不是底層的細節,對於架構來說,核心的原理的基本思路,是要梳理清晰的

Redis架構第四天:Redis Cluster的理論+實踐總結