本篇文章帶大家了解一下redis中的主從復制、哨兵、集群,希望對大家有所幫助!
一、redis 主從復制
1. 主從復制的概述
主從復制,是指將一臺服務器的數據,復制到其他的Redis服務器。前者稱為主節點(Master),后者稱為從節點(Slave);數據的復制是單向的,只能由主節點到從節點。
默認情況下,每臺Redis服務器都是主節點;且一個主節點可以有多個從節點,但一個從節點只能有一個主節點。【相關推薦:Redis視頻教程】
2. 主從復制的作用
● 數據冗余:主從復制實現了數據的熱備份,是持久化之外的一種數據冗余方式。
● 故障恢復:當主節點出現問題時,可以由從節點提供服務,實現快速的故障恢復;實際上是一種服務的冗余。
● 負載均衡:在主從復制的基礎上,配合讀寫分離,可以由主節點提供寫服務,由從節點提供讀服務(即寫Redis數據時應用連接主節點,讀Redis數據時應用連接從節點),分擔服務器負載;有其是在寫少讀多的場景下,通過多個從節點分擔讀負載,可以大大提高Redis服務器的并發量。
● 高可用基石:除了上述作用以外,主從復制還是哨兵和集群能夠實施的基礎,因此說主從復制是Redis高可用的基礎。
3. 主從復制的流程
(1)若啟動一個Slave機器進程,則它會向Master機器發送一個“sync command”命令,請求同步連接。
(2)無論是第一次連接還是重新連接,Master機器都會啟動一個后臺進程,將數據快照保存到數據文件中(執行rdb操作),同時Master還會記錄修改數據的所有命令并緩存在數據文件中。
(3)后臺進程完成緩存操作之后,Master機器就會向Slave機器發送數據文件,Slave端機器將數據文件保存到硬盤上,然后將其加載到內存中,接著Master機器就會將修改數據的所有操作一并發送給Slave端機器。若Slave出現故障導致宕機,則恢復正常會自動重新連接。
(4)Master機器收到Slave端機器的連接后,將其完整的數據文件發送給Slave端機器,如果Master同時收到多個Slave發來的同步請求,則Master會在后臺啟動一個進程以保存數據文件,然后將其發送給所有的Slave端機器,確保所有的Slave端機器都正常。
4. 搭建Redis主從復制
4.1 服務器IP配置
服務器 | 主機名 | IP |
---|---|---|
Master節點 | master | 192.168.122.10 |
Slave1節點 | slave1 | 192.168.122.11 |
Slave2節點 | slave2 | 192.168.122.12 |
4.2 各服務器防火墻環境
systemctl?stop?firewalld?&&?systemctl?disable?firewalld setenforce?0
4.3 各服務器安裝Redis
redis 安裝詳見往期博客:
NoSQL 之 redis 詳解
傳入安裝包到/opt目錄 yum?install?-y?gcc?gcc-c++?make tar?zxvf?redis-5.0.7.tar.gz?-C?/opt/ cd?/opt/redis-5.0.7/ make make?PREFIX=/usr/local/redis?install cd?/opt/redis-5.0.7/utils ./install_server.sh ...... Please?select?the?redis?executable?path?[] #輸入/uar/local/redis/bin/redis-server ln?-s?/usr/local/redis/bin/*?/usr/local/bin/
4.4 修改Redis配置文件(Master節點操作)
Master:192.168.122.10
[root@master?~]#?vim?/etc/redis/6379.conf ? ##70行,修改監聽地址為0.0.0.0,表示監聽任何地址 bind?0.0.0.0 ##137行,開啟守護進程 daemonize?yes ##172行,指定日志文件目錄 logfile?/var/log/redis_6379.log ##264行,指定工作日志 dir?/var/lib/redis/6379 ##700行,開啟AOF持久化功能 appendonly?yes
4.5 修改Redis配置文件(Slave節點操作)
Slave1:192.168.122.11
[root@slave1?utils]#?vim?/etc/redis/6379.conf? ? ##70行,修改監聽地址為0.0.0.0,表示監聽任何地址 bind?0.0.0.0 ##137行,開啟守護進程 daemonize?yes ##172行,指定日志文件目錄 logfile?/var/log/redis_6379.log ##264行,指定工作日志 dir?/var/lib/redis/6379 ##288行,添加要同步的Master節點IP和端口 replicaof?192.168.122.10?6379 ##700行,開啟AOF持久化功能 appendonly?yes ? [root@slave1?utils]#?/etc/init.d/redis_6379?restart Stopping?... Redis?stopped Starting?Redis?server...
Slave2:192.168.122.12
[root@slave2?utils]#?vim?/etc/redis/6379.conf? ? ##70行,修改監聽地址為0.0.0.0,表示監聽任何地址 bind?0.0.0.0 ##137行,開啟守護進程 daemonize?yes ##172行,指定日志文件目錄 logfile?/var/log/redis_6379.log ##264行,指定工作日志 dir?/var/lib/redis/6379 ##288行,添加要同步的Master節點IP和端口 replicaof?192.168.122.10?6379 ##700行,開啟AOF持久化功能 appendonly?yes ? [root@slave2?utils]#?/etc/init.d/redis_6379?restart Stopping?... Redis?stopped Starting?Redis?server...
4.6 驗證主從效果
4.6.1 在Master節點上看日志
[root@master?~]#?tail?-f?/var/log/redis_6379.log? 1002:M?23?Sep?2021?16:46:33.569?*?Background?saving?terminated?with?success 1002:M?23?Sep?2021?16:46:33.569?*?Synchronization?with?replica?192.168.122.11:6379?succeeded 1002:M?23?Sep?2021?16:46:34.519?*?Replica?192.168.122.12:6379?asks?for?synchronization 1002:M?23?Sep?2021?16:46:34.519?*?Full?resync?requested?by?replica?192.168.122.12:6379 1002:M?23?Sep?2021?16:46:34.519?*?Starting?BGSAVE?for?SYNC?with?target:?disk 1002:M?23?Sep?2021?16:46:34.519?*?Background?saving?started?by?pid?7941 7941:C?23?Sep?2021?16:46:34.521?*?DB?saved?on?disk 7941:C?23?Sep?2021?16:46:34.521?*?RDB:?0?MB?of?memory?used?by?copy-on-write 1002:M?23?Sep?2021?16:46:34.591?*?Background?saving?terminated?with?success 1002:M?23?Sep?2021?16:46:34.591?*?Synchronization?with?replica?192.168.122.12:6379?succeeded
4.6.2 在Master節點驗證從節點
[root@master?~]#?redis-cli?info?replication #?Replication role:master connected_slaves:2 slave0:ip=192.168.122.11,port=6379,state=online,offset=910,lag=0 slave1:ip=192.168.122.12,port=6379,state=online,offset=910,lag=0 master_replid:9d7fa17fc64cd573f5b81457183831d97dfad7dc master_replid2:0000000000000000000000000000000000000000 master_repl_offset:910 second_repl_offset:-1 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:1 repl_backlog_histlen:910
二、Redis 哨兵模式
1. 哨兵模式的核心功能
在主從復制的基礎上,哨兵引入了主節點的自動故障轉移。
2. 哨兵模式的原理
哨兵(sentinel)是一個分布式系統,用于對主從結構中每臺服務器進行監控,當出現故障時通過投票機制選擇新的Master并將所有Slave連接到新的Master。所以整個運行哨兵的集群的數量不得少于3個節點。
3. 哨兵模式的作用
● 監控:哨兵會不斷地檢查主節點和從節點是否運作正常。
● 自動故障轉移:當主節點不能正常工作時,哨兵會開始自動故障轉移操作,它會將失效主節點的其中一個從節點升級為新的主節點,并讓其他從節點改為復制新的主節點。
● 通知提醒:哨兵可以將故障轉移的結果發送給客戶端。
4. 哨兵模式的結構
哨兵結構由兩部分組成,哨兵節點和數據節點:
● 哨兵節點:哨兵系統由一個或多個節點組成,哨兵節點是特殊的redis節點,不存儲數據。
● 數據節點:主節點和從節點都是數據節點。
5. 哨兵模式的工作形式
哨兵的啟動依賴于主從模式,所以須把主從模式安裝好的情況下再去做哨兵模式,所有節點上都需要部署哨兵模式,哨兵模式會監控所有的Redis工作節點是否正常,當Master出現問題的時候,因為其他節點與主節點失去聯系,因此會投票,投票過半就會認為這個Master的確出現問題,然后會通知哨兵間,然后從Slaves中選取一個作為新的Master。
6. 故障轉移機制
-
由哨兵節點定期監控發現主節點是否出現了故障。每個哨兵節點每隔1秒會向主節點、從節點及其他哨兵節點發送一次ping命令做一次心跳檢測。如果主節點在一定時間范圍內不回復或者是回復一個錯誤消息,那么這個哨兵就會認為這個主節點主觀下線了(單方面的)。當超過半數哨兵節點認為該主節點主觀下線了,這樣就客觀下線了。
-
當主節點出現故障,此時哨兵節點會通過Raft算法(選舉算法)實現選舉機制共同選舉出一個哨兵節點為leader,來負責處理主節點的故障轉移和通知。所以哨兵集群的主機數量不得少于三個節點。
- 由leader哨兵節點執行故障轉移,過程如下:
● 將某一個從節點升級為新的主節點,讓其他從節點指向新的主節點;
● 若原主節點恢復也變成從節點,并指向新的主節點;
● 通知客戶端主節點已經更換。
需要特別注意的是,客觀下線是主節點才有的概念;如果從節點和哨兵節點發生故障,被哨兵主觀下線后,不會再有后續的客觀下線和故障轉移操作。
7. 主節點的選舉
-
過濾掉不健康的(已下線的),沒有回復哨兵ping響應的從節點。
-
選擇配置文件中從節點優先級配置最高的(replica-priority,默認值為100)。
-
選擇復制偏移量最大,也就是復制最完整的從節點。
8. 搭建Redis哨兵模式
8.1 服務器IP配置
服務器 | 主機名 | IP |
---|---|---|
Master節點 | master | 192.168.122.10 |
Slave1節點 | slave1 | 192.168.122.11 |
Slave2節點 | slave2 | 192.168.122.12 |
8.2 各服務器防火墻環境
systemctl?stop?firewalld?&&?systemctl?disable?firewalld setenforce?0
8.3 修改Redis哨兵模式的配置文件(所有節點操作)
vim?/opt/redis-5.0.7/sentinel.conf ? ##17行,取消注釋,關閉保護模式 protected-mode?no ##21行,Redis哨兵默認的監聽端口 port?26379 ##26行,指定sentienel為后臺啟動 daemonize?yes ##36行,指定日志存放路徑 logfile?"/var/log/sentinel.log" ##65行,指定數據庫存放路徑 dir?"/var/lib/redis/6379" ##84行,修改,指定該哨兵節點監控192.168.122.10?6379這個主節點,該主節點的名稱是mymaster ##最后的2的含義與主節點的故障判定有關;至少需要2個哨兵節點同意,才能判定故障并進行故障轉移 sentinel?monitor?mymaster?192.168.122.10?6379?2 ##113行,判定服務器down掉的時間周期,默認30000毫秒(30秒) sentinel?down-after-milliseconds?mymaster?30000 ##146行,故障節點的最大超時時間為180000毫秒(180秒) sentinel?failover-timeout?mymaster?180000
8.4 啟動哨兵模式
注意:需先啟動master,再啟動slave
cd?/opt/redis-5.0.7/ redis-sentinel?sentinel.conf?&
8.5 查看哨兵信息
Master:192.168.122.10
[root@master?redis-5.0.7]#?redis-cli?-p?26379?info?sentinel #?Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=192.168.122.10:6379,slaves=2,sentinels=3
三、Redis 群集模式
1. Redis集群的概述
集群,即Redis Cluster,是Redis 3.0開始引入的分布式存儲方案。
2. Redis集群
集群由多個節點(Node)組成,Redis的數據分布在這些節點中。集群中的節點分為主節點和從節點;只有主節點負責讀寫請求和集群信息的維護;從節點只進行主節點數據和狀態信息的復制。
3. Redis集群的作用
集群的作用,可以歸納為兩點:
3.1 數據分區
數據分區(或稱數據分片)是集群最核心的功能。
集群將數據分散到多個節點,一方面突破了Redis單機內存大小的限制,存儲容量大大增加;另一方面每個主節點度可以對外提供讀服務和寫服務,大大提高了集群的響應能力。
Redis單機內存大小受限問題,在介紹持久化和主從復制時都有體積;例如,如果單機內存太大,bgsave和bgrewriteaof的fork操作可能導致主進程阻塞,主從環境下主機切換時可能導致從節點長時間無法提供服務,全量復制階段主節點的復制緩沖區可能溢出。
3.2 高可用
集群支持主從復制和主節點的自動故障轉換(與哨兵類似);當任一節點發生故障時,集群仍然可以對外提供服務。
4. Redis集群的數據分片
● Redis集群引入了哈希槽的概念
● Redis集群有16384個哈希槽(編號0-16383)
● 集群的每個節點負責一部分哈希槽
● 每個key通過CRC16校驗后對16384取余來決定放置哪個哈希槽,通過這個值,去找到所對應的節點,然后直接跳轉到這個對應的節點上進行存取操作。
5. 哈希槽
5.1 哈希槽的分配
-
哈希槽可按照集群主機數平均分配(默認分配)
以3個節點組成的集群為例:
節點A包含0-5460號哈希槽
節點B包含5461-10922號哈希槽
節點C包含10923-16383號哈希槽 -
也可以根據主機的性能以及功能自定義分配
以3個節點組成的集群為例:
節點A性能最差,包含0-2000號哈希值
節點B性能中等,包含2001-7000號哈希值
節點C性能最強,包含7001-16383號哈希值
5.2 哈希槽的使用
集群搭建的時候,需要給集群的節點分配插槽,0~16383
在node1執行set a a
-
使用crc16算法對key進行計算,得到一個數字,然后對這個數字進行求余16384(crc16 : a = 26384l;26384 % 16384 = 10000)
-
查找包含10000的插槽的節點,找到了node2,自動跳轉到node2
-
在node2上執行set a a命令
node3上執行get a
-
a –> 10000
-
跳轉到node2
-
在node2執行get a
6. Redis集群的主從復制模型
集群中具有A、B、C三個節點,如果節點B失敗了,整個集群就會因缺少5461-10922這個范圍的槽而不可以用。
以每個節點添加一個從節點A1、B1、C1整個集群便有了三個Master節點和三個Slave節點組成,在節點B失敗后,集群選舉B1位為新的主節點繼續服務。當B和B1都失敗后,集群將不可用。
7. 搭建Redis群集模式
7.1 服務器IP配置
redis的集群一般需要6個節點,3主3從。方便起見,這里在同一臺服務器上模擬;
以端口號進行區分,3個主節點端口號6001/6002/6003,對應的從節點端口號6004/6005/6006。
服務器 | 主機名 | IP | 主端口 | 從端口 |
---|---|---|---|---|
Node1節點 | node | 192.168.122.10 | 6001 | 6004 |
Node2節點 | node | 192.168.122.10 | 6002 | 6005 |
Node3節點 | node | 192.168.122.10 | 6003 | 6006 |
7.2 服務器防火墻環境
systemctl?stop?firewalld?&&?systemctl?disable?firewalld setenforce?0
7.3 創建集群配置目錄及文件
[root@node?~]#?cd?/etc/redis [root@node?redis]#?mkdir?-p?redis-cluster/redis600{1..6} [root@node?redis]#?for?i?in?{1..6} >?do >?cp?/opt/redis-5.0.7/redis.conf?/etc/redis/redis-cluster/redis600$i >?cp?/opt/redis-5.0.7/src/redis-cli?/opt/redis-5.0.7/src/redis-server?/etc/redis/redis-cluster/redis600$i >?done [root@node?redis]#?ls?-R?redis-cluster/ redis-cluster/: redis6001??redis6002??redis6003??redis6004??redis6005??redis6006 ? redis-cluster/redis6001: redis-cli??redis.conf??redis-server ? redis-cluster/redis6002: redis-cli??redis.conf??redis-server ? redis-cluster/redis6003: redis-cli??redis.conf??redis-server ? redis-cluster/redis6004: redis-cli??redis.conf??redis-server ? redis-cluster/redis6005: redis-cli??redis.conf??redis-server ? redis-cluster/redis6006: redis-cli??redis.conf??redis-server
7.4 開啟群集功能
僅以redis6001為例,其他5個文件夾的配置文件以此類推修改,特別注意端口號的修改。
[root@node?redis]#?cd?redis-cluster/redis6001 [root@node?redis6001]#?vim?redis.conf? ? ##69行,注釋掉bind項,默認監聽所有網卡 #bind?127.0.0.1 ##88行,修改,關閉保護模式 protected-mode?no ##92行,修改,redis監聽端口 port?6001 ##136行,開啟守護進程,以獨立進程啟動 daemonize?yes ##832行,取消注釋,開啟群集功能 cluster-enabled?yes ##840行,注銷注釋,群集名稱文件設置 cluster-config-file?nodes-6001.conf ##846行,注銷注釋,群集超時時間設置 cluster-node-timeout?15000 ##700行,修改,開啟AOF持久化 appendonly?yes
7.5 啟動redis節點
分別進入那六個文件夾,執行命令:“redis-server redis.conf”,來啟動redis節點
[root@node?redis6001]#?for?d?in?{1..6} >?do >?cd?/etc/redis/redis-cluster/redis600$i >?^C [root@node?redis6001]#?for?d?in?{1..6} >?do >?cd?/etc/redis/redis-cluster/redis600$d >?redis-server?redis.conf >?done [root@node1?redis6006]#?ps?-ef?|?grep?redis root????????992??????1??0?13:45??????????00:00:07?/usr/local/redis/bin/redis-server?0.0.0.0:6379 root???????2289??????1??0?14:41??????????00:00:00?redis-server?*:6001?[cluster] root???????2294??????1??0?14:41??????????00:00:00?redis-server?*:6002?[cluster] root???????2299??????1??0?14:41??????????00:00:00?redis-server?*:6003?[cluster] root???????2304??????1??0?14:41??????????00:00:00?redis-server?*:6004?[cluster] root???????2309??????1??0?14:41??????????00:00:00?redis-server?*:6005?[cluster] root???????2314??????1??0?14:41??????????00:00:00?redis-server?*:6006?[cluster] root???????2450???2337??0?14:50?pts/0????00:00:00?grep?--color=auto?redis
7.6 啟動集群
[root@node?redis6006]#?redis-cli?--cluster?create?127.0.0.1:6001?127.0.0.1:6002?127.0.0.1:6003?127.0.0.1:6004?127.0.0.1:6005?127.0.0.1:6006?--cluster-replicas?1
六個實例分為三組,每組一主一從,前面的做主節點,后面的做從節點。下面交互的時候需要輸入yes才可以成功創建。
–replicas 1表示每個主節點有1個從節點。
7.7 測試集群
[root@node1?redis6006]#?redis-cli?-p?6001?-c #加-c參數,節點之前就可以互相跳轉 127.0.0.1:6001>?cluster?slots #查看節點的哈希槽編號范圍 1)?1)?(integer)?0 #哈希槽起始編號 ???2)?(integer)?5460 #哈希槽終止編號 ???3)?1)?"127.0.0.1" ??????2)?(integer)?6001 #node節點主 ??????3)?"18e59f493579facea29abf90ca4050f566d66339" ???4)?1)?"127.0.0.1" ??????2)?(integer)?6004 #node節點從 ??????3)?"2635bf6a0c286ef910ec5da03dbdc7cde308c588" 2)?1)?(integer)?10923 ???2)?(integer)?16383 ???3)?1)?"127.0.0.1" ??????2)?(integer)?6003 ??????3)?"51460d417eb56537e5bd7e8c9581c66fdd817b3c" ???4)?1)?"127.0.0.1" ??????2)?(integer)?6006 ??????3)?"51a75667dcf21b530e69a3242a3e9f81f577168d" 3)?1)?(integer)?5461 ???2)?(integer)?10922 ???3)?1)?"127.0.0.1" ??????2)?(integer)?6002 ??????3)?"6381d68c06ddb7ac43c8f7d7b8da0644845dcd59" ???4)?1)?"127.0.0.1" ??????2)?(integer)?6005 ??????3)?"375ad927116d3aa845e95ad5f0586306e7ff3a96" 127.0.0.1:6001>?set?num?1 OK 127.0.0.1:6001>?get?num "1" 127.0.0.1:6001>?keys?* 1)?"num" 127.0.0.1:6001>?quit [root@node1?redis6006]#?redis-cli?-p?6002?-c 127.0.0.1:6002>?keys?* #6002端口無鍵值對 (empty?list?or?set) 127.0.0.1:6002>?get?num ->?Redirected?to?slot?[2765]?located?at?127.0.0.1:6001 "1" #6002端口獲取到num鍵位于6001端口,切換到6001端口并顯示鍵值 127.0.0.1:6001>?set?key1?11111 ->?Redirected?to?slot?[9189]?located?at?127.0.0.1:6002 OK #6001端口創建鍵值對,將其存至6002端口,并切換至6002端口 127.0.0.1:6002>
更多編程相關知識,請訪問:Redis視頻教程!!