redis(五)-集羣

參考資料:
redis 4.x cookbook 中文版;
redis官方文檔
注: 本文redis的版本爲: 5.0.3

redis學習路徑

集羣:

在互聯網應用的系統中,單個redis實例不能提供穩定高效同時具備數據冗餘和高可用性能的鍵值對存儲服務;
所以我們通常會對redis進行水平擴展;

  • 哨兵(Sentinel)

由於單個哨兵進程也有可能出現宕機或斷連,所以哨兵通常需要存在3個或者更多的進程;當多個哨兵進程檢測到主實例的下線,將會通過內部選舉,推出一個哨兵進程來將某個從實例進行提升爲主實例;

監控與通知:
對redis服務進行監控,以及將故障通知其他程序或管理員;
自動化故障轉移:
1.當沒有配置哨兵時,在主從複製中,如果主實例掛掉/因意外斷連後,需要人工將從實例提升爲主實例;
2.配置哨兵後,哨兵會根據各個從實例配置的優先級來進行評選提升;
配置服務提供者:
通過對應的客戶端重新配置腳本,可以在每次故障轉移後,告訴客戶端,新的主機地址;
如何找到監控主實例的從實例:
sentinel會每隔固定時間想主實例發送:info replication命令,獲取主實例的從實例詳細信息;
如何找到其他sentinel:
所有sentinel在運行後都會每隔固定時間向名爲_sentinel_:hello的頻道發送sentinel本身信息以及監控的主機信息;因此訂閱此頻道即可得到所有sentinel的信息;

注意,此處的配置文件不可直接使用;

# 默認情況下,不能從127.0.0.1以外的地方訪問redis-sentinel;
# 可以通過bind指定ip;
# 也可以通過 protected-mode no 來禁用保護(意思就是任意地方都可訪問)
#
# bind 127.0.0.1 192.168.1.1
#
# protected-mode no

# port <sentinel-port>
# 監聽的端口
port 26379

# 是否作爲守護進程(如果需要後臺運行,選擇yes)
daemonize no

# 指定爲守護進程後,將在下面指定位置保存pid文件;
pidfile /var/run/redis-sentinel.pid

# 指定哨兵日誌的輸出文件,如果以空字符串指定,在非守護進程狀態時,將進行標準輸出(輸出到命令行);在守護進程狀態運行時,日誌將輸出到/dev/null中;
logfile ""

# sentinel announce-ip <ip>
# sentinel announce-port <port>
#
# sentinel在進行監控後,會向一個名爲 _sentinel_:hello的頻道中發送消息,消息的內容包括:哨兵本身的信息,哨兵監控的主實例信息和狀態;
# 
# 如果不配置,將會默認發佈本地ip和端口;
# 如果只聲明ip,那端口會是默認的26379;
# 如果只聲明port,那ip會是默認的127.0.0.1;
# 通常情況下配置這裏是因爲要從外部通過NAT訪問,或者是因爲docker之類的容器的端口映射導致找不到主從實例或其他哨兵;
# sentinel announce-ip 1.2.3.4

# dir <working-directory>
# 設置工作目錄;
dir /tmp

# sentinel monitor <master-name> <ip> <redis-port> <quorum>
#
# 告訴Sentinel監視此主服務器,並僅在至少<quorum>個哨兵同意的情況下,才能將其視爲O_DOWN(客觀地處於Down)狀態.
#
# 判定一個master是否宕機,必須要由仲裁會(所有已知的sentinel)的大部分通過,才能裁定;所以纔會需要3個以上的哨兵才能進行裁定;
#
# 主實例的從實例,是由sentinel自行發現,因此不需要配置;
# 注意從實例晉升時,會重寫配置文件;
# 所有實例命名應該在標準範圍內:A-z 0-9 以及 ".-_".
sentinel monitor mymaster 127.0.0.1 6379 2

# 設定監視的master/slave的連接密碼(主從服務都得使用同一個密碼)
#
# sentinel auth-pass mymaster MySUPER--secret-0123passw0rd


# 多少毫秒內,master無法應答,則認爲是宕機,默認值是30s(30000ms);
sentinel down-after-milliseconds mymaster 30000

# sentinel parallel-syncs <master-name> <numreplicas>
#
# 配置故障轉移後,同時與主實例進行同步的從服務數量;
# 故障轉移後,某個副本晉升爲新的主實例,這時需要進行數據同步,如果我們在主從複製中,設定當主實例暫停服務時,從服務器可以提供舊數據;
# 那麼這個值應該設定的儘量小,如果所有從實例都與主實例進行同步,那此時的所有查詢都將丟失;
# 雖然設定的值越小,全部同步完成的時間就越長,但是這
sentinel parallel-syncs mymaster 1

# sentinel failover-timeout <master-name> <milliseconds>
#
# 以毫秒爲單位指定故障切換超時;如下幾種形式都會 用到這個值:
#
# - 對一個已經嘗試過故障轉移(超時)的主機,進行重新故障轉移時,將會耗費兩倍於故障轉移超時的時間;
#
# - 由於當前哨兵的配置導致將從實例複製到一個錯誤主實例下後,再強制使用正確的主機對該從實例進行復制;(這個過程所需的時間等於故障轉移超時的時間,計算是從哨兵檢測到自己配置錯誤的時刻開始)
#
# - 取消已經在進行晉升的動作(還沒有任何副本連接到晉升後的master);(這個過程所需的時間,等於故障轉移超時的時間);
#
# - 將所有從實例的主實例配置爲本次晉升的新主實例的最長等待時間;(這時間等於故障轉移超時的時間,注意,在超過此時間之後,還是一樣會進行主從配置,但是進度將不由本配置文件決定);
#
# 默認3分鐘(180000 ms)
sentinel failover-timeout mymaster 180000

# SCRIPTS EXECUTION
# 腳本執行
# notification-script(通知腳本) 用於 故障轉移後通知系統管理員;
# reconfig-script(重新配置腳本) 用於 故障轉移後重新配置客戶端;
# 
# 下面是腳本的運行規則:
#
# 如果腳本以"1"退出,則稍後會重試執行(當前最多設置爲10次)
#
# 如果腳本以"2"(或更高的值)退出,則不會重試腳本執行.
#
# 如果腳本因爲收到信號而終止,則行爲與退出代碼1相同.
#
# 一個腳本的最長執行時間是60s;超時後江湖被sigkill殺掉,然後重新嘗試執行;


# NOTIFICATION SCRIPT(通知腳本)
#
# sentinel notification-script <master-name> <script-path>
#
# 爲在警告級別中生成的哨兵事件調用指定的腳本(例如: -sdown, -odown等等);
# 這個腳本應該通過郵件/SMS或其他消息渠道通知管理員;
#
# 這個腳本只有兩個傳入參數,事件類型,事件描述;
#
# 如果此項配置,必須可執行,否則哨兵啓動失敗;
# 示例:
sentinel notification-script mymaster /usr/sentinel/script/notification.sh

# CLIENTS RECONFIGURATION SCRIPT(客戶端重配置腳本)
#
# sentinel client-reconfig-script <master-name> <script-path>
#
# 故障轉移完成後,調用此配置的腳本通知客戶端新主機的地址;
# 
# 將會傳遞如下參數給腳本:
# 主機名稱 角色(leader/observer) 狀態(始終是failover) from-ip/from-port (指故障轉移前的主機地址/端口) to-ip/to-port(指故障轉移後的主機地址/端口)
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 這個腳本應該可以進行多線程調用.
#
# 示例:
sentinel client-reconfig-script mymaster /usr/sentinel/script/reconfig.sh

# SECURITY
#
# 默認情況下,哨兵運行後不能修改腳本,可以避免將腳本改爲其他某些不可執行文件,從而導致觸發故障轉移後調用文件出錯;
sentinel deny-scripts-reconfig yes

# 重命名命令,可以將主實例及其從實例的某些命令,修改爲非常規命令名;
# 下面的意思是:將 mymaster 及其 從實例 的 CONFIG 命令重命名爲 guessme
# SENTINEL rename-command mymaster CONFIG GUESSME
#
# 在配置此項後,哨兵在mymaster實例及其從實例上使用config時將以guessme代替
# 也可以使用Sentinel Set在運行時執行此配置.
#
# 要將命令設置回其原始名稱(撤消重命名),可以只將命令重命名爲其自身:
#
# SENTINEL rename-command mymaster CONFIG CONFIG
# 日誌文件位置:
logfile /var/log/redis/sentinel.log

  • redis cluster

redis3.0開始支持的官方集羣解決方案

通常一個健壯的redis集羣,需要三個主節點,三個從節點;所以我們需要先配置好6個redis;
大致過程:同一個機器上可以啓動主從節點,複製redis.conf,修改端口/pid文件名/rdb文件名/日誌文件名/aof文件名;複製後的文件可以命名爲redis-6379.conf(其實就是用端口作區分);
分別啓動這6個主從服務;
然後從實例上執行集羣發現命令:

[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.130 6380
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.129 6380
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.129 6379
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.128 6379
OK
[root@localhost bin]# redis-cli -p 6379 cluster meet 192.168.50.128 6380
OK

再分配哈希槽給三個主節點:
注意這裏如果出現連接失敗異常,就需要去關閉centos的防火牆:

#關閉防火牆
[root@localhost bin]# systemctl stop firewalld.service
#取消開機啓動防火牆
[root@localhost bin]# systemctl disable firewalld.service
Removed /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost bin]# for i in {0..5400}; do redis-cli -h 192.168.50.128 -p 6379 cluster addslots $i; done
OK
OK
...

這裏大致說一下,哈希槽是什麼:
每個哈希槽裏存放了很多的鍵值對;
我們將哈希槽分配給主節點,存鍵值對的時候根據算法用key計算出這一次的鍵值對應該存儲於哪一個哈希槽;
redis中有16383個哈希槽,每個主節點負責一部分哈希槽;如果新加入一個主節點,那麼必須從之前的主節點中,分出一部分交給新的主節點,這樣以確保每個主節點都能接收數據;

分配好哈希槽之後,應聲明主從節點關係:

#先獲取到當前集羣的所有節點信息;第一列是node-id;
[root@localhost bin]# redis-cli -h 192.168.50.129 -p 6379 cluster nodes
23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c 192.168.50.130:6379@16379 master - 0 1592496118000 1 connected 11001-16383
cf05aa186b5ad3a5aa38201648cb5dcdccb42159 192.168.50.129:6380@16380 master - 0 1592496119086 2 connected
ff96cb067229e1ac984dc8ed1e29ab64c32f6bd7 192.168.50.128:6380@16380 master - 0 1592496120094 0 connected
9a2543b264bc93239d8c34f70f2c2ebedc3081eb 192.168.50.128:6379@16379 master - 0 1592496118000 4 connected 0-5400
6c167ad58b9eab89df19b4b458fe7b11492d2b34 192.168.50.129:6379@16379 myself,master - 0 1592496119000 3 connected 5401-11000
e81c63b42150fa81b822f3696401bc1773b65407 192.168.50.130:6380@16380 master - 0 1592496118077 5 connected
#聲明一個節點作爲另一個節點的從節點;
#redis-cli -h 從節點ip -p 從節點端口 cluster replicate 主節點的node-id;
[root@localhost bin]# redis-cli -h 192.168.50.129 -p 6379 cluster replicate cf05aa186b5ad3a5aa38201648cb5dcdccb42159
(error) ERR To set a master the node must be empty and without assigned slots.
[root@localhost bin]# redis-cli -h 192.168.50.129 -p 6380 cluster replicate 6c167ad58b9eab89df19b4b458fe7b11492d2b34
OK
[root@localhost bin]# redis-cli -h 192.168.50.128 -p 6380 cluster replicate 9a2543b264bc93239d8c34f70f2c2ebedc3081eb
OK
[root@localhost bin]# redis-cli -h 192.168.50.130 -p 6380 cluster replicate 23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c
OK
#從新查看集羣節點信息,可以清晰的看到主從關係;
[root@localhost bin]# redis-cli -h 192.168.50.130 -p 6380 cluster nodes
6c167ad58b9eab89df19b4b458fe7b11492d2b34 192.168.50.129:6379@16379 master - 0 1592496683792 3 connected 5401-11000
9a2543b264bc93239d8c34f70f2c2ebedc3081eb 192.168.50.128:6379@16379 master - 0 1592496682785 4 connected 0-5400
ff96cb067229e1ac984dc8ed1e29ab64c32f6bd7 192.168.50.128:6380@16380 slave 9a2543b264bc93239d8c34f70f2c2ebedc3081eb 0 1592496682000 4 connected
e81c63b42150fa81b822f3696401bc1773b65407 192.168.50.130:6380@16380 myself,slave 23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c 0 1592496681000 5 connected
23f615cd065e6e30c3ddbcc4f7b8bdf4a8871b3c 192.168.50.130:6379@16379 master - 0 1592496681000 1 connected 11001-16383
cf05aa186b5ad3a5aa38201648cb5dcdccb42159 192.168.50.129:6380@16380 slave 6c167ad58b9eab89df19b4b458fe7b11492d2b34 0 1592496681775 3 connected

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章