Redis集羣以及自動故障轉移測試

 

在Redis中,與Sentinel(哨兵)實現的高可用相比,集羣(cluster)更多的是強調數據的分片或者是節點的伸縮性,若是在集羣的主節點上加入對應的從節點,集羣還能夠自動故障轉移,所以相比Sentinel(哨兵)仍是有很多優點的。
如下簡單測試Redis的集羣(單機多實例的模式),來體驗一下集羣的自動故障轉移功能,同時結合Python,來觀察自動故障轉移過程當中應用程序端的表現。node

redis集羣實例安裝python

啓動6個redis集羣實例,集羣模式,除了正常的配置項目以外,須要在每一個主節點中增長集羣配置redis

cluster-enabled yes       # 開啓集羣模
cluster-node-timeout 1000  # 節點超時時間,單位毫秒,設置一個較小的超時時間,目的是爲了後面測試自動故障轉移的效果

分配slot & 主節點握手數據庫

主節點分配slot給主節點,三個主節點分配16383個slot
8001主----->8004從
8002主----->8005從
8003主----->8006從緩存

#!/bin/bash
for ((i=0;i<=16383;i++))
do
if [ $i -le 5461 ]; then
  /usr/local/redis5_1/bin/redis-cli -h 127.0.0.1 -p 8001 -a root CLUSTER ADDSLOTS $i
elif [ $i -gt 5461 ]&&[ $i -le 10922 ]; then
  /usr/local/redis5_1/bin/redis-cli -h 127.0.0.1 -p 8002 -a root CLUSTER ADDSLOTS $i
elif [ $i -gt 10922 ]; then
  /usr/local/redis5_1/bin/redis-cli -h 127.0.0.1 -p 8003 -a root CLUSTER ADDSLOTS $i
fi
donebash

分配完slot以後,在第一個主節點上執行cluster meet 127.0.0.1 8002,cluster meet 127.0.0.1 8003
無須在其餘兩個主節點上meet另外兩個主節點,隨後三個主節點之間關係肯定會自動肯定,目前集羣中是三個主節點異步

添加主節點對應的從節點,須要登陸到每一個主節點的實例上,執行性能

三個從節點分別加入到主節點以後,此時6個節點所有加入到集羣中測試

 

Python鏈接至集羣測試spa

這裏須要安裝redis-py-cluster依賴包

#!/usr/bin/env python3
import time
from time import ctime,sleep
from rediscluster import StrictRedisCluster

startup_nodes = [
    {"host":"111.231.253.***", "port":8001},
    {"host":"111.231.253.***", "port":8002},
    {"host":"111.231.253.***", "port":8003},
    {"host":"111.231.253.***", "port":8004},
    {"host":"111.231.253.***", "port":8005},
    {"host":"111.231.253.***", "port":8006}
]
redis_conn= StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True,password="root")

for i in range(0, 100000):
    try:
        redis_conn.set('name' + str(i), str(i))
        print('setting name' + str(i) +"--->" + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
    except:
        print("connect to redis cluster error")
        time.sleep(2)

執行上述寫入測試腳本以後,數據基本上均勻地落在三個節點上

 

自動故障轉移測試

修改Python腳本,每隔1s寫入一條數據,目的是便於觀察在主節點宕機,集羣自動故障轉移這個時間段之以內(1s鐘左右),對於應用程序的影響,或者說應用程序在自動故障轉移先後的表現。
以下腳本循環往Redis集羣中寫入數據,執行期間,強制殺掉一個主節點,觀察應用程序鏈接狀況。
同時,若是發生異常,暫停應用程序2s,由於上面一開始配置的集羣故障轉移時間是1s,若是應用程序暫停2s,徹底能夠跳過故障轉移的過程,
當故障轉移完成以後,應用程序又恢復成正常狀態,雖然8001節點宕機,應用程序繼續鏈接8001節點,可是應用程序徹底無感知。

import time
from time import ctime,sleep
from rediscluster import StrictRedisCluster

startup_nodes = [
    {"host":"111.231.253.***", "port":8001},
    {"host":"111.231.253.***", "port":8002},
    {"host":"111.231.253.***", "port":8003},
    {"host":"111.231.253.***", "port":8004},
    {"host":"111.231.253.***", "port":8005},
    {"host":"111.231.253.***", "port":8006}
]
redis_conn= StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True,password="root")

for i in range(0, 100000):
    try:
        redis_conn.set('name' + str(i), str(i))
        print('setting name' + str(i) +"--->" + time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())))
        time.sleep(1)
    except:
        print("connect to redis cluster error")
        time.sleep(2)

發如今殺掉主節點以後,僅發生了一次鏈接錯誤,隨後由於Redis集羣的自動故障轉移成功,對應於程序來講是透明的,所以應用程序隨後正常工做,不受其中一個主節點宕機的影響。

集羣此時的狀態,8001節點宕機,明顯,8001對應的從節點8004接管主節點,升級爲master,對外提供服務

觀察升級爲主節點的8004實例日誌,會發如今強制殺掉原8001主節點以後,1秒鐘以內,成功替代8001升級爲master節點
若是在故障轉移的過程當中,沒有應用程序訪問Redis,應用程序甚至徹底不知道Redis集羣發生了故障轉移,只要不發生集羣中某一個節點的主從節點同時宕機,整個集羣就沒有問題,且對應用程序徹底透明。

隨後重啓宕機的8001節點,會發現8001節點自動變爲其原從節點(8004)的從節點

總體上來看,Redis集羣的配置和使用以及自動故障轉移仍是比較簡單易容的,這裏沒有用redis-trib.rb 而是採用手動分配slot和建立集羣的方式,目的是瞭解完整的配置流程。
須要注意的是:
1,若是開啓了密碼驗證模式,全部的主從節點必須配置masterauth,由於某一個節點宕機重啓以後,會自動變爲從節點,此時若是想要從master複製數據,就必須須要主節點的密碼
2,StrictRedisCluster決定了全部主從節點的密碼必需要是同樣的。

表面上看Redis集羣簡單易用,自動故障轉移是沒有問題的,保證了高可用,看似沒有問題。
若是細想,這個過程仍是有問題的,有沒有發現,雖然故障轉移保證了高可用,可是當從節點升級爲主節點以後,若是保證升級爲主節點的從節點(8004)必定可以徹底複製原主節點(8001)上的數據?

補充:剛寫完就發現,redis在主從複製上,有一個wait 命令,以下

wait命令可讓默認的異步複製變爲同步複製,
wait numsslave timeout,含義是等待複製到的slave節點的個數和超時時間,若是超時間爲0,表示會一直等待(同步到從節點)
若是從節點不可達,則wait會一直阻塞主節點,此時主節點是沒法對外提供服務的。

 

這個就相似於MySQL的半同步複製,主節點上的數據,必定要同步(雖然是relaylog)到從節點,主節點纔會提交。不過回頭想一想,取決於如何去對待Redis或者怎麼使用Redis,Redis更多的時候是做爲一個緩存使用,而不是落地的數據庫,既然是緩存,就應該更多地去考慮性能。

相關文章
相關標籤/搜索