Redis 集群_主从复制_哨兵模型
1?redis集群簡介
1.1?集群的概念
所謂的集群,就是通過添加服務(wù)器的數(shù)量,提供相同的服務(wù),從而讓服務(wù)器達到一個穩(wěn)定、高效的狀態(tài)。
?
1.1.1?使用redis集群的必要性
問題:我們已經(jīng)部署好了redis,并且能啟動一個redis,實現(xiàn)數(shù)據(jù)的讀寫,為什么還要學(xué)習(xí)redis集群?
答:(1)單個redis存在不穩(wěn)定性。當redis服務(wù)宕機了,就沒有可用的服務(wù)了。
(2)單個redis的讀寫能力是有限的。
?
總結(jié):redis集群是為了強化redis的讀寫能力。
?
1.1.2?如何學(xué)習(xí)redis集群
--說明:(1)redis集群中,每一個redis稱之為一個節(jié)點。
??????(2)redis集群中,有兩種類型的節(jié)點:主節(jié)點(master)、從節(jié)點(slave)。
??????(3)redis集群,是基于redis主從復(fù)制實現(xiàn)。
??????????????????????????
所以,學(xué)習(xí)redis集群,就是從學(xué)習(xí)redis主從復(fù)制模型開始的。
?
2?redis主從復(fù)制
2.1?概念
????主從復(fù)制模型中,有多個redis節(jié)點。
????其中,有且僅有一個為主節(jié)點Master。從節(jié)點Slave可以有多個。
?
只要網(wǎng)絡(luò)連接正常,Master會一直將自己的數(shù)據(jù)更新同步給Slaves,保持主從同步。
? |
?
2.2?特點
(1)主節(jié)點Master可讀、可寫.
(2)從節(jié)點Slave只讀。(read-only)
?
因此,主從模型可以提高讀的能力,在一定程度上緩解了寫的能力。因為能寫仍然只有Master節(jié)點一個,可以將讀的操作全部移交到從節(jié)點上,變相提高了寫能力。
?
2.3?基于配置實現(xiàn)
2.3.1?需求
| 主節(jié)點 | 6380 |
| 從節(jié)點(兩個) | 6381、6382 |
?
2.3.2?配置步驟
(1)在/usr/local目錄下,創(chuàng)建一個/redis/master-slave目錄
| [root@node0719 local]# mkdir ?-p ?redis/master-slave |
?
(2)在master-slave目錄下,創(chuàng)建三個子目錄6380、6381、6382
| [root@node0719 master-slave]# mkdir 6380 6381 6382 |
?
(3)依次拷貝redis解壓目錄下的redis.conf配置文件,到這三個子目錄中。
| [root@node0719 master-slave]# cp /root/redis-3.2.9/redis.conf ./6380/ [root@node0719 master-slave]# cp /root/redis-3.2.9/redis.conf ./6381/ [root@node0719 master-slave]# cp /root/redis-3.2.9/redis.conf ./6382/ |
?
(4)進入6380目錄,修改redis.conf,將port端口修改成6380即可。
| [root@node0719 master-slave]# cd ./6380 [root@node0719 6380]# vim redis.conf |
?
(5)進入6381目錄,修改redis.conf,將port端口改成6381,同時指定開啟主從復(fù)制。
| [root@node0719 6380]# cd ../6381 [root@node0719 6381]# vim redis.conf ? |
?
(6)進入6382目錄,修改redis.conf,將port端口改成6382,同時指定開啟主從復(fù)制。
| [root@node0719 6380]# cd ../6382 [root@node0719 6381]# vim redis.conf ? |
?
2.3.3?測試
(1)打開三個xshell窗口,在每一個窗口中,啟動一個redis節(jié)點。查看日志輸出。(不要改成后臺模式啟動,看不到日志,不直觀)
?cd /usr/local/redis/master-slave/
cd 6381 && /usr/local/bin/redis-server ?./redis.conf
| [root@node0719 master-slave]# cd 6380 && redis-server ./redis.conf |
?
| [root@node0719 master-slave]# cd 6381?&& redis-server ./redis.conf |
?
| [root@node0719 master-slave]# cd 6382?&& redis-server ./redis.conf |
?
?
?
(2)另外再打開三個xshell窗口,在每一個窗口中,登陸一個redis節(jié)點
| [root@node0719 ~]# redis-cli -p 6380 |
?
| [root@node0719 ~]# redis-cli -p 6381 |
?
| [root@node0719 ~]# redis-cli -p 6382 |
?
(3)在主節(jié)點6380上,進行讀寫操作,操作成功
| [root@node0719 ~]# redis-cli -p 6380 127.0.0.1:6380> set user:name zs OK 127.0.0.1:6380> get user:name "zs" 127.0.0.1:6380> |
?
(4)在從節(jié)點6381上
讀操作執(zhí)行成功,并且成功從6380上同步了數(shù)據(jù)
| [root@node0719 ~]# redis-cli -p 6381 127.0.0.1:6381> get user:name "zs" |
?
寫操作執(zhí)行失敗。(從節(jié)點,只能讀,不能寫)
| 127.0.0.1:6381> set user:age 18 (error) READONLY You can't write against a read only slave. |
?
3?Sentinel哨兵模式
3.1?主從模式的缺陷
當主節(jié)點宕機了,整個集群就沒有可寫的節(jié)點了。
?
由于從節(jié)點上備份了主節(jié)點的所有數(shù)據(jù),那在主節(jié)點宕機的情況下,如果能夠?qū)墓?jié)點變成一個主節(jié)點,是不是就可以解決這個問題了呢?
?
答:是的,這個就是Sentinel哨兵的作用。
?
3.2?哨兵的任務(wù)
Redis 的 Sentinel 系統(tǒng)用于管理多個 Redis 服務(wù)器(instance), 該系統(tǒng)執(zhí)行以下三個任務(wù):
監(jiān)控(Monitoring): Sentinel 會不斷地檢查你的主服務(wù)器和從服務(wù)器是否運作正常。
提醒(Notification): 當被監(jiān)控的某個 Redis 服務(wù)器出現(xiàn)問題時, Sentinel 可以通過 API 向管理員或者其他應(yīng)用程序發(fā)送通知。
自動故障遷移(Automatic failover): 當一個主服務(wù)器不能正常工作時, Sentinel 會開始一次自動故障遷移操作, 它會進行選舉,將其中一個從服務(wù)器升級為新的主服務(wù)器, 并讓失效主服務(wù)器的其他從服務(wù)器改為復(fù)制新的主服務(wù)器; 當客戶端試圖連接失效的主服務(wù)器時, 集群也會向客戶端返回新主服務(wù)器的地址, 使得集群可以使用新主服務(wù)器代替失效服務(wù)器。
?
3.2.1?監(jiān)控(Monitoring)
(1)Sentinel可以監(jiān)控任意多個Master和該Master下的Slaves。(即多個主從模式)
(2)同一個哨兵下的、不同主從模型,彼此之間相互獨立。
(3)Sentinel會不斷檢查Master和Slaves是否正常。
| ? |
?
3.2.2?自動故障切換(Automatic failover)
3.2.2.1?Sentinel網(wǎng)絡(luò)
監(jiān)控同一個Master的Sentinel會自動連接,組成一個分布式的Sentinel網(wǎng)絡(luò),互相通信并交換彼此關(guān)于被監(jiān)視服務(wù)器的信息。下圖中,三個監(jiān)控s1的Sentinel,自動組成Sentinel網(wǎng)絡(luò)結(jié)構(gòu)。
疑問:為什么要使用sentinel網(wǎng)絡(luò)呢?
答:當只有一個sentinel的時候,如果這個sentinel掛掉了,那么就無法實現(xiàn)自動故障切換了。
?
在sentinel網(wǎng)絡(luò)中,只要還有一個sentinel活著,就可以實現(xiàn)故障切換。
?
3.2.2.2?故障切換的過程
(1)投票(半數(shù)原則)
當任何一個Sentinel發(fā)現(xiàn)被監(jiān)控的Master下線時,會通知其它的Sentinel開會,投票確定該Master是否下線(半數(shù)以上,所以sentinel通常配奇數(shù)個)。
?
(2)選舉
當Sentinel確定Master下線后,會在所有的Slaves中,選舉一個新的節(jié)點,升級成Master節(jié)點。
其它Slaves節(jié)點,轉(zhuǎn)為該節(jié)點的從節(jié)點。
| ??? ? ????????? (1)投票 ?????????????????????????????(2)選舉 |
?
(3)原Master重新上線
當原Master節(jié)點重新上線后,自動轉(zhuǎn)為當前Master節(jié)點的從節(jié)點。
| ? ? (3)原master重新上線 |
?
3.3?哨兵模式部署
3.3.1?需求
前提:已經(jīng)存在一個正在運行的主從模式。
?
另外,配置三個Sentinel實例,監(jiān)控同一個Master節(jié)點。
?
3.3.2?配置Sentinel
(1)在/usr/local目錄下,創(chuàng)建/redis/sentinels/目錄
| [root@node0719 local]# mkdir?-p?redis/sentinels |
?
(2)在/sentinels目錄下,以次創(chuàng)建s1、s2、s3三個子目錄中
| [root@node0719 sentinels]# mkdir s1 s2 s3 |
?
(3)依次拷貝redis解壓目錄下的sentinel.conf文件,到這三個子目錄中
| [root@node0719 sentinels]# cp??/root/redis-3.2.9/sentinel.conf ?./s1/ [root@node0719 sentinels]# cp ?/root/redis-3.2.9/sentinel.conf??./s2/ [root@node0719 sentinels]# cp??/root/redis-3.2.9/sentinel.conf ?./s3/ |
?
(4)依次修改s1、s2、s3子目錄中的sentinel.conf文件,修改端口,并指定要監(jiān)控的主節(jié)點。(從節(jié)點不需要指定,sentinel會自動識別)
?
S1哨兵配置如下:
?
S2哨兵配置如下:
?
S3哨兵配置如下:
| ? |
?
(5)再打開三個xshell窗口,在每一個窗口中,啟動一個哨兵實例,并觀察日志輸出
| [root@node0719 sentinels]# redis-sentinel??./s1/sentinel.conf |
?
| [root@node0719 sentinels]# redis-sentinel??./s2/sentinel.conf |
?
| [root@node0719 sentinels]# redis-sentinel??./s3/sentinel.conf |
?
核心日志輸出:
?
3.3.3?測試
(1)先關(guān)閉6380節(jié)點。發(fā)現(xiàn),確實重新指定了一個主節(jié)點
?
(2)再次上線6380節(jié)點。發(fā)現(xiàn),6380節(jié)點成為了新的主節(jié)點的從節(jié)點。
?
3.4?結(jié)論
Sentinel哨兵模式,確實能實現(xiàn)自動故障切換。提供穩(wěn)定的服務(wù)。
?
3.5?注意事項
如果哨兵和redis節(jié)點不在同一臺服務(wù)器上,注意IP綁定的問題。
?
(1)主從模型,所有的節(jié)點,使用ip綁定
?
(2)所有的哨兵,也都使用ip去綁定主機
?
(3)所有的哨兵,都是通過主節(jié)點的ip,去監(jiān)控主從模型
?
4?Redis-cluster集群
4.1?哨兵模式的缺陷
在哨兵模式中,仍然只有一個Master節(jié)點。當并發(fā)寫請求較大時,哨兵模式并不能緩解寫壓力。
?
我們知道只有主節(jié)點才具有寫能力,那如果在一個集群中,能夠配置多個主節(jié)點,是不是就可以緩解寫壓力了呢?
答:是的。這個就是redis-cluster集群模式。
?
4.2?Redis-cluster集群概念
(1)由多個Redis服務(wù)器組成的分布式網(wǎng)絡(luò)服務(wù)集群;
(2)集群之中有多個Master主節(jié)點,每一個主節(jié)點都可讀可寫;
(3)節(jié)點之間會互相通信,兩兩相連;
(4)Redis集群無中心節(jié)點。
?
4.3?集群節(jié)點復(fù)制
| ? ? |
在Redis-Cluster集群中,可以給每一個主節(jié)點添加從節(jié)點,主節(jié)點和從節(jié)點直接遵循主從模型的特性。
?
當用戶需要處理更多讀請求的時候,添加從節(jié)點可以擴展系統(tǒng)的讀性能。
?
4.4?故障轉(zhuǎn)移
Redis集群的主節(jié)點內(nèi)置了類似Redis Sentinel的節(jié)點故障檢測和自動故障轉(zhuǎn)移功能,當集群中的某個主節(jié)點下線時,集群中的其他在線主節(jié)點會注意到這一點,并對已下線的主節(jié)點進行故障轉(zhuǎn)移。
| ? ? |
?
集群進行故障轉(zhuǎn)移的方法和Redis Sentinel進行故障轉(zhuǎn)移的方法基本一樣,不同的是,在集群里面,故障轉(zhuǎn)移是由集群中其他在線的主節(jié)點負責(zé)進行的,所以集群不必另外使用Redis Sentinel。
?
4.5?集群分片策略
Redis-cluster分片策略,是用來解決key存儲位置的。
?
集群將整個數(shù)據(jù)庫分為16384個槽位slot,所有key-value數(shù)據(jù)都存儲在這些slot中的某一個上。一個slot槽位可以存放多個數(shù)據(jù),key的槽位計算公式為:slot_number=crc16(key)%16384,其中crc16為16位的循環(huán)冗余校驗和函數(shù)。
集群中的每個主節(jié)點都可以處理0個至16383個槽,當16384個槽都有某個節(jié)點在負責(zé)處理時,集群進入上線狀態(tài),并開始處理客戶端發(fā)送的數(shù)據(jù)命令請求。
| ? ? |
?
4.6?集群redirect轉(zhuǎn)向
由于Redis集群無中心節(jié)點,請求會隨機發(fā)給任意主節(jié)點;
主節(jié)點只會處理自己負責(zé)槽位的命令請求,其它槽位的命令請求,該主節(jié)點會返回客戶端一個轉(zhuǎn)向錯誤;
客戶端根據(jù)錯誤中包含的地址和端口重新向正確的負責(zé)的主節(jié)點發(fā)起命令請求。
| ? ? |
?
4.7?集群搭建
4.7.1?準備工作
(1)安裝ruby環(huán)境
redis集群管理工具redis-trib.rb依賴ruby環(huán)境,首先需要安裝ruby環(huán)境:
?
| yum -y install ruby yum -y install rubygems |
?
(2)安裝ruby和redis的接口程序
拷貝redis-3.0.0.gem至/usr/local下,執(zhí)行安裝:
| gem install /usr/local/redis-3.0.0.gem |
?
4.7.2?集群規(guī)劃
(1)Redis集群最少需要6個節(jié)點,可以分布在一臺或者多臺主機上。
本教案在一臺主機上創(chuàng)建偽分布式集群,不同的端口表示不同的redis節(jié)點,如下:
主節(jié)點:192.168.56.3:7001 192.168.56.3:7002 192.168.56.3:7003
從節(jié)點:192.168.56.3:7004 192.168.56.3:7005 192.168.56.3:7006
?
(2)在/usr/local/redis下創(chuàng)建redis-cluster目錄,其下創(chuàng)建7001、7002。。7006目錄,如下:
| ? ? |
?
(3)將redis解壓路徑下的配置文件redis.conf,依次拷貝到每個700X目錄內(nèi),并修改每個700X目錄下的redis.conf配置文件:
| 必選配置: port 700X bind 192.168.23.3 ??? cluster-enabled yes 建議配置: daemonized ?yes logfile ?/usr/local/redis/redis-cluster/700X/node.log |
4.7.3?啟動每個結(jié)點redis服務(wù)
依次以700X下的redis.conf,啟動redis節(jié)點。(必須指定redis.conf文件)
| redis-server ?/usr/local/redis/redis-cluster/700X/redis.conf |
?
4.7.4?執(zhí)行創(chuàng)建集群命令
進入到redis源碼存放目錄redis/redis-4.10.3/src下,執(zhí)行redis-trib.rb,此腳本是ruby腳本,它依賴ruby環(huán)境。
| ./redis-trib.rb create --replicas 1 192.168.159.10:7001 192.168.159.10:7002 192.168.159.10:7003 192.168.159.10:7004 192.168.159.10:7005 ?192.168.159.10:7006 |
?
創(chuàng)建過程如下:
| ? ? |
?
4.7.5?查詢集群信息
集群創(chuàng)建成功登陸任意redis結(jié)點查詢集群中的節(jié)點情況。
./redis-cli -c -h 192.168.56.3 -p 7001
| ? ? |
?
說明:./redis-cli -c -h 192.168.56.3 -p 7001 ,其中:
| -c表示以集群方式連接redis, -h指定ip地址, -p指定端口號 ? cluster nodes?查詢集群結(jié)點信息; cluster info?查詢集群狀態(tài)信。 |
?
4.8?集群管理
4.8.1?添加主節(jié)點
4.8.1.1?節(jié)點規(guī)劃
集群創(chuàng)建成功后可以向集群中添加節(jié)點,下面是添加一個master主節(jié)點
添加7007節(jié)點,參考集群結(jié)點規(guī)劃章節(jié)添加一個“7007”目錄作為新節(jié)點。
添加節(jié)點,執(zhí)行下邊命令:
./redis-trib.rb add-node ?192.168.23.3:7007 192.168.23.3:7001
| ? ? |
?
查看集群結(jié)點發(fā)現(xiàn)7007已添加到集群中:
| ? ? |
?
4.8.1.2?hash槽重新分配
添加完新的主節(jié)點后,需要對主節(jié)點進行hash槽分配,這樣該主節(jié)才可以存儲數(shù)據(jù)。
redis集群有16384個槽,被所有的主節(jié)點共同分配,通過查看集群結(jié)點可以看到槽占用情況。
| ? |
?
給剛添加的7007結(jié)點分配槽:
第一步:連接上集群
| ./redis-trib.rb reshard 192.168.23.3:7001(連接集群中任意一個可用節(jié)點都行) |
?
第二步:輸入要分配的槽數(shù)量
| ? ? |
?
輸入 500表示要分配500個槽
?
第三步:輸入接收槽的結(jié)點id
| ? |
這里準備給7007分配槽,通過cluster nodes查看7007結(jié)點id為79bbb30bba66b4997b9360dd09849c67d2d02bb9
輸入:79bbb30bba66b4997b9360dd09849c67d2d02bb9
?
第四步:輸入源結(jié)點id
| ? |
?
這里輸入all,表示從其它主節(jié)點中分配。
?
第五步:輸入yes開始移動槽到目標結(jié)點id
| ? |
?
4.8.2?添加從節(jié)點
集群創(chuàng)建成功后可以向集群中添加節(jié)點,下面是添加一個slave從節(jié)點。
添加7008從結(jié)點,將7008作為7007的從結(jié)點。
新增從節(jié)點命令格式:
| ./redis-trib.rb add-node --slave?--master-id masterID?newNodIP:port MasterIP:port ? masterID ??????主節(jié)點id,從cluster ?nodes信息中查看 newNodIP:port ????新增節(jié)點的ip:端口 MasterIP:port ???????主節(jié)點的ip:端口 |
?
執(zhí)行如下命令:
| ./redis-trib.rb add-node --slave --master-id 909c349f5f2d4db015101fb7c4e3c227a74ad382 192.168.4.253:7008?192.168.4.253:7007 |
?
79bbb30bba66b4997b9360dd09849c67d2d02bb9 ?是7007結(jié)點的id,可通過cluster nodes查看。
| ? |
?
注意:
如果原來該結(jié)點在集群中的配置信息已經(jīng)生成cluster-config-file指定的配置文件中(如果cluster-config-file沒有指定則默認為nodes.conf),這時可能會報錯:
| [ERR] Node XXXXXX?is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0 |
?
解決方法:
刪除生成的配置文件nodes.conf,刪除后再執(zhí)行./redis-trib.rb add-node指令。
?
查看集群中的結(jié)點,剛添加的7008為7007的從節(jié)點:
| ? |
?
4.8.3?刪除節(jié)點:
刪除節(jié)點命令格式:
| ./redis-trib.rb del-node nodeIP:port?nodeID nodeIP:port ???待刪除節(jié)點的ip:端口 nodeID ???????待刪除節(jié)點的id,從cluster node中查看 |
注意,刪除已經(jīng)占有hash槽的結(jié)點會失敗,報錯如下:
| [ERR] Node 127.0.0.1:7005 is not empty! Reshard data away and try again. |
?
需要將該結(jié)點占用的hash槽分配出去(參考hash槽重新分配章節(jié))。
?
5?java程序連接redis集群
5.1?連接步驟
5.1.1?第一步:創(chuàng)建項目,導(dǎo)入jar包
| ? |
?
5.1.2?第二步:創(chuàng)建redis集群的客戶端
| package?cn.gzsxt.jedis.test; ? import?java.util.HashSet; import?java.util.Set; import?redis.clients.jedis.HostAndPort; import?redis.clients.jedis.JedisCluster; ? public?class?TestJedisCluster { ? public?static?void?main(String[] args) { //1、創(chuàng)建jedidsCluster客戶端 //創(chuàng)建一個set集合,用來封裝所有redis節(jié)點的信息 Set<HostAndPort> nodes?= new?HashSet<>(); ? nodes.add(new?HostAndPort("192.168.23.12", 7001)); nodes.add(new?HostAndPort("192.168.23.12", 7002)); nodes.add(new?HostAndPort("192.168.23.12", 7003)); nodes.add(new?HostAndPort("192.168.23.12", 7004)); nodes.add(new?HostAndPort("192.168.23.12", 7005)); nodes.add(new?HostAndPort("192.168.23.12", 7006)); nodes.add(new?HostAndPort("192.168.23.12", 7007)); nodes.add(new?HostAndPort("192.168.23.12", 7008)); ? JedisCluster cluster?= new?JedisCluster(nodes); ? String name?= cluster.get("user:id:1:name"); cluster.set("user:id:1:address", "廣東省廣州市廣州尚學(xué)堂"); String address?= cluster.get("user:id:1:address"); ? System.out.println("name:"+name); System.out.println("address:"+address); if(null!=cluster){ cluster.close(); } } } |
?
5.2?注意事項:
連接Redis集群時,需要修改防火墻,開方每一個redis節(jié)點的端口。
?
說明:如果要開發(fā)一個范圍的端口,可以使用冒號來分割,即: 7001:7008,表示開發(fā)7001-7008之間所有的端口
| ? |
?
5.3?測試
| ? |
?
訪問Redis-cluster集群成功!!!
轉(zhuǎn)載于:https://www.cnblogs.com/aknife/p/11190911.html
總結(jié)
以上是生活随笔為你收集整理的Redis 集群_主从复制_哨兵模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 樊登读书怎么拆书赚钱(汉典樊字的基本解释
- 下一篇: 笔记_SQLite入门