Redis高可用方案
前序
在多數後端專案中,快取這塊兒Redis屬於一枝獨秀。只要是個java程式設計師基本少不了跟redis打交道,無論是專案中實際應用或者跟面試官切磋。我們知道Redis雖然單機QPS也有好幾萬,但生產環境上基本沒人敢上單機。因為分散式環境中,不穩定因素很多,萬一哪天網線被刨斷了或者伺服器掛了。影響到客戶就不得了了。那麼為了應對Redis的單機故障,我們一般有如下的三種高可用方案。
Redis高可用方案
方案一(主從+keepalived+VIP)
適用場景:之前的單機模式下,在redis負載高時可能會崩潰。故給主節點增加從節點做備用節點,在主掛掉時立馬提升為新主。該場景適用於redis負載不是很大,對redis高可用有需求並且客戶端對主從切換無感的場景。
Keepalived:叢集管理中高可用的一個服務軟體,通過健康檢查指令碼去檢測例項節點。當檢查失敗時會將對應節點的priority值減少。若主節點priority值比備用節點的小時,執行切換VIP指令碼跟從節點升主指令碼。
VIP:虛擬ip繫結至主節點,一旦主節點掛掉後,由keepalived重新繫結在新主節點上。
優點:應用端連線方面不用改變。
缺點:不能進行讀寫分離,主節點壓力還是很大
修改點:客戶端不需要修改。
方案二(主從+sentinel叢集)
適用場景:在系統對redis請求併發高的情況下,方案1場景中主節點負載壓力過高。
此時需要主從讀寫分離來減輕主節點壓力,並增加快取服務的高併發。客戶端通過連線
Sentinel獲取主從節點資訊,並將自己的讀寫請求分別傳送至主從節點進行請求分流,減輕主節點壓力。
Sentinel哨兵:哨兵是一個執行在特殊模式下的 Redis 程序,哨兵主要負責的就是三個任務:監控、選主和通知。哨兵執行過程中週期性向所有主從節點發送PING命令,主從節點會給哨兵回覆PONG命令。若主節點未在規定時間內回覆哨兵,則哨兵標記該主節點為主觀下線,之後會通知其它哨兵節點對該主節點進行檢測。如果超過一半哨兵都判定為主觀下線,則該主節點會被標記為客觀下線。隨後從該主節點的從節點中選出新主節點。之後會通知其餘從節點進行replicaof命令和新主節點建立聯絡,通知客戶端讓他們把操作命令發到新的主節點上。
讀寫分離:在該模式下為分擔master節點的請求壓力,可在客戶端上增加讀寫分離的邏輯,之後讀請求走從節點,寫請求走主節點。
增加從節點:
啟動新的節點並在新節點上執行如下命令即可
slaveof IP PORT(IP和PORT是需要關聯的主節點ip和埠)
優點:高可用並能有效減少master上的請求壓力
缺點:修改東西較多,如果寫請求多,主節點依然有壓力大的風險。
修改點:
1、 客戶端連線方式得改為sentinel模式,
2、 要實現讀寫分離得修改Jedis連線相關的邏輯
方案三(cluster叢集)
適用場景:當系統對redis的請求負載持續升高時,方案2場景中單個主節點最終因負載過高而崩潰。此時將redis升級為叢集模式,該模式下通過分槽機制將請求分散至各master節點,大大減輕單個master節點壓力,而且各master節點都有自己的從節點,在主節點掛掉時,其對應的從節點會及時補充為新主節點。該方案適用於系統對redis請求壓力高,並對redis有高併發高可用的需求場景。
叢集模式:redis cluster叢集將16384個Slot(槽位)分給叢集主節點。之後客戶端請求過來時候會先計算key的雜湊值並跟16384取模得到對應槽位。之後根據槽位跟主節點對應關係將該請求傳送至相應主節點。每個叢集節點均維護一份節點跟槽位的對映關係。 如果在一個節點上操作另外一個節點上的key,會返回去相應節點操作的提示資訊。 Master節點內部集成了Sentinel, 故不需單獨起Sentinel叢集,當有主節點掛掉時,其他Master節點會感知到並從其從節點中選出新主節點。
增加節點:當需要擴充套件記憶體增加叢集節點時,連線任一主節點並依次執行如下命令:\ redis-cli -a 密碼 --cluster add-node 新節點IP:埠 已存在節點IP:埠(增加叢集節點) 執行成功後再執行下面命令 redis-cli -a 密碼 --cluster reshard 已存在節點IP:埠(給新節點分配槽數) 根據提示分配指定槽數,分配成功後表示新主節點增加成功。再次執行增加節點命令給叢集增加從節點。然後再登入新增從節點,執行如下命令,對剛增加的新主從進行關聯。 首先登入進新從節點redis-cli -a -c -h 新從節點IP -p 從節點埠 然後執行cluster replicate 2728a594a0498e98e4b83a537e19f9a0a3790f38 這樣便在叢集中新增了一對主從節點。
優點:支援高可用、高併發
缺點:佔用資源大
修改點:
1、 客戶端連線方式得改為叢集模式
部署步驟
方案1部署步驟
1、 Redis主從安裝(記得在從節點配置檔案加一行slaveof 主節點ip 埠)
mkdir /opt/software –p
cd /opt/software
wget http://download.redis.io/releases/redis-5.0.8.tar.gz
yum –y install gcc gcc-c++
tar –zxvf redis-5.0.8.tar.gz
mv redis-5.0.8 /usr/local/src
cd /usr/local/src/reids-5.0.8/
make
make install PREFIX=/usr/local/redis
vi /usr/local/src/reids-5.0.8/redis.conf(編輯配置檔案)\ 修改bind 127.0.0.1 為 bind 0.0.0.0
修改 protected-mode yes 為protected-mode no
若為從節點需要在配置檔案最後增加一句 slaveof 主節點IP 主節點埠
2、 keepalived軟體安裝(主從節點均要安裝)
yum安裝即可:yum –y install keepalived
3、 登入進入redis主節點,編輯/etc/keepalikved/keepalived.conf
global_defs {
router_id redis_master
}
vrrp_script chk_redis
{
script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379"
interval 2
timeout 2
fall 3
weight -20
}
vrrp_instance redis {
state MASTER
interface 網絡卡名稱
virtual_router_id 100
priority 100
#nopreempt # no seize,must add
advert_int 1
authentication { #all node must same
auth_type PASS
auth_pass 1111
}
unicast_src_ip 主節點IP
unicast_peer {
從節點IP
}
virtual_ipaddress {
VIP地址
}
track_script {
chk_redis
}
notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1 從節點IP 從節點埠"
notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1 從節點IP 從節點埠"
notify_fault /etc/keepalived/scripts/redis_fault.sh
notify_stop /etc/keepalived/scripts/redis_stop.sh }
4、 登入從節點編輯/etc/keepalived/keepalived.conf內容如下:
global_defs {
router_id redis1
script_user root
enable_script_security
} vrrp_script chk_redis
{
script "/etc/keepalived/scripts/redis_check.sh 127.0.0.1 6379"
interval 2
timeout 2
fall 3
weight -20
} vrrp_instance redis {
state BACKUP
interface eth0
virtual_router_id 100
priority 90
#nopreempt # no seize,must add
advert_int 1
authentication { #all node must same
auth_type PASS
auth_pass 1111
}
unicast_src_ip 從節點IP
unicast_peer {
主節點IP
}
virtual_ipaddress {
VIP
}
track_script {
chk_redis
}
notify_master "/etc/keepalived/scripts/redis_master.sh 127.0.0.1 主節點IP 主節點埠"
notify_backup "/etc/keepalived/scripts/redis_backup.sh 127.0.0.1 主節點IP 主節點埠"
notify_fault /etc/keepalived/scripts/redis_fault.sh
notify_stop /etc/keepalived/scripts/redis_stop.sh
}
5、 建立存放keepalived所用指令碼的目錄
make /etc/keepalived/scripts –p
6、 在步驟4中建立的目錄下建立以下指令碼:
redis_backup.sh:
!/bin/bash
REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3"
LOGFILE="/etc/keepalived/log/keepalived-redis-state.log"
echo "[backup]" >> $LOGFILE
date >> $LOGFILE
echo "Run SLAVEOF cmd ..." >> $LOGFILE
$REDISCLI SLAVEOF $2 $3 >> $LOGFILE 2>&1
sleep 15
redis_check.sh:
!/bin/bash
ALIVE=/usr/local/bin/redis-cli -h $1 -p $2 PING
LOGFILE="/etc/keepalived/log/keepalived-redis-check.log"
echo "[CHECK]" >> $LOGFILE
date >> $LOGFILE
if [[ $ALIVE == "PONG" ]]; then :
echo "SUCCESS:reidis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1
exit 0
else
echo "FAILED:redis-cli -h $1 -p $2 PING $ALIVE" >> $LOGFILE 2>&1
exit 1
fi
redis_fault.sh:
!/bin/bash
LOGFILE=/etc/keepalived/log/keepalived-redis-state.log
echo "[fault]" >> $LOGFILE
date >> $LOGFILE
redis_master.sh:
!/bin/bash
REDISCLI="/usr/local/bin/redis-cli -h $1 -p $3"
LOGFILE="/etc/keepalived/log/keepalived-redis-state.log"
echo "[master]" >> $LOGFILE
date >> $LOGFILE
echo "Being master...." >> $LOGFILE 2>&1
echo "Run MASTER cmd ..." >> $LOGFILE 2>&1
\$REDISCLI SLAVEOF $2 $3 >> $LOGFILE
sleep 10
delay 10 s wait data async cancel sync
echo "Run SLAVEOF NO ONE cmd ..." >> $LOGFILE
\$REDISCLI SLAVEOF NO ONE >> $LOGFILE 2>&1
redis_stop.sh:
!/bin/bash
LOGFILE=/etc/keepalived/log/keepalived-redis-state.log
echo "[stop]" >> $LOGFILE
date >> $LOGFILE
這些指令碼從節點也需要複製過來一份
給這些指令碼賦予執行許可權
chmod a+x /etc/keepalived/scripts/*.sh
7、 啟動redis跟keepalived軟體
方案2部署步驟
1、 參考方案1部署步驟1,安裝redis一主兩從並啟動
2、 sentinel配置(主從節點均需配置)
首先建立一個放置sentinel配置檔案的目錄
mkdir –p /etc/sentinel
然後將redis安裝目錄中的sentinel配置檔案複製至/etc/sentinel下
cp /usr/local/src/reids-5.0.8/sentinel.conf /etc/sentinel/
編輯sentinel.conf如下:
監聽埠
port 26379
設定daemonize為yes,否則不會採用守護程序啟動,啟動命令會阻塞
daemonize yes
pidfile 加上埠
pidfile "/var/run/redis-sentinel_26379.pid"
自定義logfile檔案的位置
logfile "/opt/redis/logs/sentinel_26379.log"
dir "/tmp"
sentinel都指向redis叢集的主節點
sentinel monitor mymaster 主節點IP 主節點埠 2
acllog-max-len 128
sentinel deny-scripts-reconfig yes
sentinel resolve-hostnames no
protected-mode no
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
3、 啟動主從節點上的sentinel
nohup redis-sentinel /etc/sentinel/sentinel.conf &
方案3部署步驟
該步驟以三主三從為例,想搭建更多節點叢集同理
1、 參照方案1部署步驟1,在三臺機器上分別安裝redis
2、 分別在三臺機器上建立存放叢集節點配置檔案的資料夾
mkdir –p /etc/redis-cluster
mkdir /etc/redis-cluster/6379 /etc/redis-cluster/6380
3、 從redis安裝目錄中複製redis.conf至上面的6379跟6380中
cp /usr/local/src/reids-5.0.8/redis.conf /etc/redis-cluster/6379
4、 修改配置檔案內容如下:
(1)daemonize yes
(2)port 6379(根據目錄名代表的埠號進行修改)
(3)pidfile /var/run/redis_6379.pid # 把pid程序號寫入pidfile配置的檔案
(4)dir /usr/local/redis-cluster/6379/(指定資料檔案存放位置,必須要指定不同的目錄位置,不然會丟失資料)
(5)cluster-enabled yes(啟動叢集模式)
(6)cluster-config-file nodes-6379.conf(叢集節點資訊檔案,這裡800x最好和port對應上)
(7)cluster-node-timeout 10000
(8)# bind 127.0.0.1(bind繫結的是自己機器網絡卡的ip,如果有多塊網絡卡可以配多個ip,代表允許客戶端通過機器的哪些網絡卡ip去訪問,內網一般可以不配置bind,註釋掉即可)
(9)protected-mode no(關閉保護模式)
(10)appendonly yes
如果要設定密碼需要增加如下配置:
(11)requirepass 密碼 (設定redis訪問密碼)
(12)masterauth 密碼 (設定叢集節點間訪問密碼,跟上面一致)
5、將上面修改的配置檔案,複製到6380,修改第2、3、4、6項的埠號,可進行批量替換:%s/源字串/目的字串/g
6、另外兩臺機器也需做上面幾步
7、分別啟動6個redis例項
Redis-server /etc/redis-cluster/6379/redis.conf
8、建立redis叢集
Redis-cli –a 密碼 --cluster create –cluster-replicas 1 節點1IP:6379 節點1IP:6380 節點2IP:6379 節點2IP:6380 節點3IP:6379 節點2IP:6380