搭建redis-sentinel(哨兵機制)集羣

redis怎麼才能作到高可用
對於redis主從架構,slave能夠對應多個自己能夠保障高可用,可是對於一個master節點,若是宕機,整個緩存系統就沒法進行寫的操做,顯然整個系統會沒法作到高可用
sentinel哨兵能夠監測master節點是否正常運行(會自動識別出全部的slave信息),若是出現宕機,則會在對應的slave節點中經過投票的方式來選取一個slave節點做爲新的master節點,
舊的master節點恢復以後會被接管成爲新的master節點的slave節點。同時sentinel哨兵節點自己也是集羣的方式部署來保障自身的高可用,而且一個sentinel是能夠同時監聽多個master節點

對於sentinel哨兵節點的一些核心概念:redis


一、sdown和odown轉換機制算法

sdown和odown兩種失敗狀態json

sdown是主觀宕機,就一個哨兵若是本身以爲一個master宕機了,那麼就是主觀宕機vim

odown是客觀宕機,若是quorum數量的哨兵都以爲一個master宕機了,那麼就是客觀宕機centos

sdown達成的條件很簡單,若是一個哨兵ping一個master,超過了is-master-down-after-milliseconds指定的毫秒數以後,就主觀認爲master宕機緩存

sdown到odown轉換的條件很簡單,若是一個哨兵在指定時間內,收到了quorum指定數量的其餘哨兵也認爲那個master是sdown了,那麼就認爲是odown了,客觀認爲master宕機安全

二、哨兵集羣的自動發現機制服務器

哨兵互相之間的發現,是經過redis的pub/sub系統實現的,每一個哨兵都會往__sentinel__:hello這個channel裏發送一個消息,這時候全部其餘哨兵均可以消費到這個消息,並感知到其餘的哨兵的存在網絡

每隔兩秒鐘,每一個哨兵都會往本身監控的某個master+slaves對應的__sentinel__:hello channel裏發送一個消息,內容是本身的host、ip和runid還有對這個master的監控配置架構

每一個哨兵也會去監聽本身監控的每一個master+slaves對應的__sentinel__:hello channel,而後去感知到一樣在監聽這個master+slaves的其餘哨兵的存在

每一個哨兵還會跟其餘哨兵交換對master的監控配置,互相進行監控配置的同步

三、slave配置的自動糾正

哨兵會負責自動糾正slave的一些配置,好比slave若是要成爲潛在的master候選人,哨兵會確保slave在複製現有master的數據; 若是slave鏈接到了一個錯誤的master上,好比故障轉移以後,那麼哨兵會確保它們鏈接到正確的master上

四、slave->master選舉算法

若是一個master被認爲odown了,並且majority哨兵都容許了主備切換,那麼某個哨兵就會執行主備切換操做,此時首先要選舉一個slave來

會考慮slave的一些信息

(1)跟master斷開鏈接的時長
(2)slave優先級
(3)複製offset
(4)run id

若是一個slave跟master斷開鏈接已經超過了down-after-milliseconds的10倍,外加master宕機的時長,那麼slave就被認爲不適合選舉爲master

(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state

接下來會對slave進行排序

(1)按照slave優先級進行排序,slave priority越低,優先級就越高
(2)若是slave priority相同,那麼看replica offset,哪一個slave複製了越多的數據,offset越靠後,優先級就越高
(3)若是上面兩個條件都相同,那麼選擇一個run id比較小的那個slave

五、quorum和majority

每次一個哨兵要作主備切換,首先須要quorum數量的哨兵認爲odown,而後選舉出一個哨兵來作切換,這個哨兵還得獲得majority哨兵的受權,才能正式執行切換

若是quorum < majority,好比5個哨兵,majority就是3,quorum設置爲2,那麼就3個哨兵受權就能夠執行切換

可是若是quorum >= majority,那麼必須quorum數量的哨兵都受權,好比5個哨兵,quorum是5,那麼必須5個哨兵都贊成受權,才能執行切換

六、configuration epoch

哨兵會對一套redis master+slave進行監控,有相應的監控的配置

執行切換的那個哨兵,會從要切換到的新master(salve->master)那裏獲得一個configuration epoch,這就是一個version號,每次切換的version號都必須是惟一的

若是第一個選舉出的哨兵切換失敗了,那麼其餘哨兵,會等待failover-timeout時間,而後接替繼續執行切換,此時會從新獲取一個新的configuration epoch,做爲新的version號

七、configuraiton傳播

哨兵完成切換以後,會在本身本地更新生成最新的master配置,而後同步給其餘的哨兵,就是經過以前說的pub/sub消息機制

這裏以前的version號就很重要了,由於各類消息都是經過一個channel去發佈和監聽的,因此一個哨兵完成一次新的切換以後,新的master配置是跟着新的version號的

其餘的哨兵都是根據版本號的大小來更新本身的master配置的

 

1redis安裝

解壓完成後能夠看到INSTALL和README.md文件,查看以獲取更多有用信息。

在README文件中能夠獲取到軟件的安裝步驟。如下安裝步驟基於此。

#step1 進入文件夾,執行編譯命令

[root@ redis-3.2.8]# make

#step2 爲了後面開發測試的方便,把啓動腳本,配置文件,日誌文件統一放到redis目錄下

[root@ redis-3.2.8]# mkdir /usr/local/redis
[root@ redis-3.2.8]# mkdir /usr/local/redis/logs
[root@ redis-3.2.8]# mkdir /usr/local/redis/bin
[root@ redis-3.2.8]# mkdir /usr/local/redis/conf
[root@ redis-3.2.8]# mkdir /etc/sentinel
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26377
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26378
[root@ redis-3.2.8]# mkdir -p /var/sentinel/26379 [root@ redis-3.2.8]# cp redis.conf sentinel.conf /usr/local/redis/conf/ [root@ src]# cp redis-server redis-sentinel redis-cli /usr/local/redis/bin/

#step3 開啓Redis服務,檢測其可用性

[root@ bin]# redis-server ../conf/redis.conf 

能夠看到日誌信息

其中有3個警告

第一個警告:The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

意思是:TCP  backlog設置值,511沒有成功,由於 /proc/sys/net/core/somaxconn這個設置的是更小的128.

第二個警告:overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to/etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.

意思是:overcommit_memory參數設置爲0!在內存不足的狀況下,後臺程序save可能失敗。建議在文件 /etc/sysctl.conf 中將overcommit_memory修改成1。

第三個警告:you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix thisissue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain thesetting after a reboot. Redis must be restarted after THP is disabled.

意思是:你使用的是透明大頁,可能致使redis延遲和內存使用問題。執行 echo never > /sys/kernel/mm/transparent_hugepage/enabled 修復該問題。

臨時解決方法:

  echo 511 > /proc/sys/net/core/somaxconn

  echo "vm.overcommit_memory=1" > /etc/sysctl.conf

  echo never > /sys/kernel/mm/transparent_hugepage/enabled。

永久解決方法:

vim /etc/sysctl.conf
net.core.somaxconn = 512
vm.overcommit_memory = 1
sysctl -p  #-p 從指定的文件加載系統參數,如不指定即從/etc/sysctl.conf中加載

[root@centos224]# vi /etc/rc.local
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi

Redis server使用默認端口6379啓動成功。

#step4 修改配置文件,使其之後臺服務方式運行。

複製代碼
#what?局域網內本機IP。
#我是部署到同一機器上因此IP都同樣,端口不一樣
bind 127.0.0.1
#修改默認端口,避免被惡意腳本掃描。
port 9999
loglevel debug
logfile /usr/local/redis/logs/redis.log.9999
#爲服務設置安全密碼
requirepass redispass
#以守護進程方式運行 daemonize yes
複製代碼

#step5 從新啓動redis。

[root@ bin]# redis-cli -p 9999 -a redispass shutdown
我使用腳本啓動方式
  啓動腳本 redis_init_script 位於位於Redis的 /utils/ 目錄下,redis_init_script腳本代碼以下:
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
 
#redis服務器監聽的端口
REDISPORT=9999
 
#服務端所處位置
EXEC=/usr/local/bin/redis-server
 
#客戶端位置
CLIEXEC=/usr/local/bin/redis-cli
 
#redis的PID文件位置,須要修改
PIDFILE=/var/run/redis_${REDISPORT}.pid
 
#redis的配置文件位置,需將${REDISPORT}修改成文件名
CONF="/etc/redis/${REDISPORT}.conf"
 
case "$1" in
    start)
        if [ -f $PIDFILE ]
        then
                echo "$PIDFILE exists, process is already running or crashed"
        else
                echo "Starting Redis server..."
                $EXEC $CONF
        fi
        ;;
    stop)
        if [ ! -f $PIDFILE ]
        then
                echo "$PIDFILE does not exist, process is not running"
        else
                PID=$(cat $PIDFILE)
                echo "Stopping ..."
                $CLIEXEC -p $REDISPORT shutdown
                while [ -x /proc/${PID} ]
                do
                    echo "Waiting for Redis to shutdown ..."
                    sleep 1
                done
                echo "Redis stopped"
        fi
        ;;
    *)
        echo "Please use start or stop as first argument"
        ;;
esac

能夠根據你本身端口進行修改

mkdir /etc/redis
cp redis.conf /etc/redis/9999.conf
將啓動腳本複製到/etc/init.d目錄下,本例將啓動腳本命名爲redisd(一般都以d結尾表示是後臺自啓動服務)。
cp redis_init_script /etc/init.d/redis_9999
./redis_9999 start

2開啓主從複製(master-slave)

主從模式的兩個重要目的,提高系統可靠性和讀寫分離提高性能。

這裏經過修改端口的方式,再啓動端口爲9997和9998的服務做爲備(從)機。

備機啓動須要修改配置文件部分屬性(在9999配置的基礎上)。

複製代碼
port 9997
logfile /usr/local/redis/logs/redis.log.9997
#指定master ip port
slaveof 127.0.0.1 9999
#認證master時須要的密碼。必須和master配置的requirepass 保持一致
masterauth redispass
requirepass redispass protected-mode no
複製代碼

從機9998配置同理

port 9998
logfile /usr/local/redis/logs/redis.log.9998
slaveof 127.0.0.1 9999
masterauth redispass
requirepass redispass protected-mode no

開啓從機服務

[root@ bin]# ./redis_9997 start
[root@ bin]# ./redis_9998 start

查看slave 9998日誌(省略部分信息),能夠看出,slave在啓動時成功鏈接master,並接收到了104字節的同步數據。

6472:S 30 Mar 11:18:17.206 * Connecting to MASTER 127.0.0.1:9999
6472:S 30 Mar 11:18:17.206 * MASTER <-> SLAVE sync started
6472:S 30 Mar 11:18:17.223 * MASTER <-> SLAVE sync: receiving 104 bytes from master
6472:S 30 Mar 11:18:17.223 * MASTER <-> SLAVE sync: Finished with success

redis作一個基準的壓測

你若是要對本身剛剛搭建好的redis作一個基準的壓測,測一下你的redis的性能和QPS(query per second)

redis本身提供的redis-benchmark壓測工具,是最快捷最方便的,固然啦,這個工具比較簡單,用一些簡單的操做和場景去壓測

一、對redis讀寫分離架構進行壓測,單實例寫QPS+單實例讀QPS

redis-3.2.8/src

./redis-benchmark -h 127.0.0.1

-c <clients> Number of parallel connections (default 50)
-n <requests> Total number of requests (default 100000)
-d <size> Data size of SET/GET value in bytes (default 2)

根據你本身的高峯期的訪問量,在高峯期,瞬時最大用戶量會達到10萬+,-c 100000,-n 10000000,-d 500

一、QPS,本身不一樣公司,不一樣服務器,本身去測試,跟生產環境還有區別

生產環境,大量的網絡請求的調用,網絡自己就有開銷,你的redis的吞吐量就不必定那麼高了

QPS的兩個殺手:一個是複雜操做,lrange,挺多的; value很大,2 byte,我以前用redis作大規模的緩存

作商品詳情頁的cache,多是須要把大串數據,拼接在一塊兒,做爲一個json串,大小可能都幾k,幾個byte

二、水平擴容redis讀節點,提高度吞吐量

就按照上一節課講解的,再在其餘服務器上搭建redis從節點,單個從節點讀請QPS在5萬左右,兩個redis從節點,全部的讀請求打到兩臺機器上去,承載整個集羣讀QPS在10萬+

3 sentinel模式故障自動遷移

Master-slave主從複製避免了數據丟失帶來的災難性後果。

可是單點故障仍然存在,在運行期間master宕機須要停機手動切換。

Sentinel很好的解決了這個問題,當Master-slave模式中的Master宕機後,可以自主切換,選擇另外一個可靠的redis-server充當master角色,使系統仍正常運行。

通常來講sentinel server須要大於等於3個。

這裏經過修改端口的方式開啓3個sentinel server。修改配置文件sentinel.conf部分屬性

複製代碼
#服務運行端口號
port 26379
sentinel monitor mumaster 1270.0.0.1 9999 2 #mymaster爲指定的master服務器起一個別名 #master IP和端口號 #2的含義:當開啓的sentinel server認爲當前master主觀下線的(+sdown)數量達到2時,則sentinel server認爲當前master客觀下線(+odown)系統開始自動遷移。2的計算(建議):
#sentinel server數量的大多數,至少爲count(sentinel server)/2 向上取整。2>3/2(主觀下線與客觀下線?) #master別名和認證密碼。這就提醒了用戶,在master-slave系統中,各服務的認證密碼應該保持一致。 sentinel auth-pass mymaster redispass #以守護進程方式運行 daemonize yes logfile /usr/local/redis/logs/sentinel.log.26379 protected-mode no sentinel down-after-milliseconds mymaster 6000 sentinel failover-timeout mymaster 18000
複製代碼

(多開服務只須要在以上配置基礎上修改端口號,其它保持不變 port 26378/port 26377)

開啓Sentinel服務

redis-sentinel /etc/sentinel/26377.conf
redis-sentinel /etc/sentinel/26378.conf
redis-sentinel /etc/sentinel/26379.conf

啓動以後能夠看到日誌信息,每一個哨兵都能去監控到對應的redis master,並可以自動發現對應的slave,哨兵之間,互相會自動進行發現,用的就是以前說的pub/sub,消息發佈和訂閱channel消息系統和機制

檢查哨兵狀態
redis-cli -h 127.0.0.1 -p 26377 -a "redispass"

sentinel master mymaster
SENTINEL slaves mymaster
SENTINEL sentinels mymaster

SENTINEL get-master-addr-by-name mymaster

哨兵節點相關配置

 

一、哨兵節點的增長和刪除

增長sentinal,會自動發現

刪除sentinal的步驟

(1)中止sentinal進程
(2)SENTINEL RESET *,在全部sentinal上執行,清理全部的master狀態
(3)SENTINEL MASTER mastername,在全部sentinal上執行,查看全部sentinal對數量是否達成了一致

二、slave的永久下線

讓master摘除某個已經下線的slave:SENTINEL RESET mastername,在全部的哨兵上面執行

三、slave切換爲Master的優先級

slave->master選舉優先級:slave-priority,值越小優先級越高

四、基於哨兵集羣架構下的安全認證

每一個slave都有可能切換成master,因此每一個實例都要配置兩個指令

master上啓用安全認證,requirepass
master鏈接口令,masterauth

sentinal,sentinel auth-pass <master-group-name> <pass>

 

五、容災演練

經過哨兵看一下當前的master:SENTINEL get-master-addr-by-name mymaster

把master節點kill -9掉,pid文件也刪除掉

查看sentinal的日誌,是否出現+sdown字樣,識別出了master的宕機問題; 而後出現+odown字樣,就是指定的quorum哨兵數量,都認爲master宕機了

(1)三個哨兵進程都認爲master是sdown了
(2)超過quorum指定的哨兵進程都認爲sdown以後,就變爲odown
(3)哨兵1是被選舉爲要執行後續的主備切換的那個哨兵
(4)哨兵1去新的master(slave)獲取了一個新的config version
(5)嘗試執行failover
(6)投票選舉出一個slave區切換成master,每隔哨兵都會執行一次投票
(7)讓salve,slaveof noone,不讓它去作任何節點的slave了; 把slave提拔成master; 舊的master認爲再也不是master了
(8)哨兵就自動認爲以前的master變成slave,將投票出的slave變成master 
(9)哨兵去探查了一下以前的master(變成來salve)的狀態,認爲它sdown了 

 

故障恢復,再將舊的master從新啓動,查看是否被哨兵自動切換成slave節點

查看到結果將9999 切換爲slave節點

容災演練日誌
Sentinel ID is ea82430cf7f6d452eb22bbf29b92fcf001c734c8
3010:X 21 Nov 22:37:31.405 # +monitor master mymaster 127.0.0.1 9999 quorum 2
3010:X 21 Nov 23:01:12.589 # +sdown master mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:12.642 # +odown master mymaster 127.0.0.1 9999 #quorum 3/2           -- 進入ODOWN狀態時。有三個哨兵認爲master當機了
3010:X 21 Nov 23:01:12.642 # +new-epoch 7                                                -- 當前配置版本被更新時。
3010:X 21 Nov 23:01:12.642 # +try-failover master mymaster 127.0.0.1 9999                -- 嘗試故障轉移,正等待其餘sentinel的選舉。
3010:X 21 Nov 23:01:12.658 # +vote-for-leader ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7 -- 投票給領導
3010:X 21 Nov 23:01:12.668 # edace82644513417b676ee6eced3184771d6361d voted for ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7
3010:X 21 Nov 23:01:12.668 # 7e68a54266703cbf429f5c6512a50a39ab94b943 voted for ea82430cf7f6d452eb22bbf29b92fcf001c734c8 7
3010:X 21 Nov 23:01:12.716 # +elected-leader master mymaster 127.0.0.1 9999              -- 被選舉爲去執行failover的時候。
3010:X 21 Nov 23:01:12.716 # +failover-state-select-slave master mymaster 127.0.0.1 9999 -- 開始要選擇一個slave當選新master時。
3010:X 21 Nov 23:01:12.792 # +selected-slave slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999 -- 找到了port:9998一個適合的slave來擔當新master
                              -- 當把選擇爲新master的slave的身份進行切換的時候。
3010:X 21 Nov 23:01:12.792 * +failover-state-send-slaveof-noone slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999 
                              -- 等待提高 9998 爲新的master
3010:X 21 Nov 23:01:12.851 * +failover-state-wait-promotion slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:13.699 # +promoted-slave slave 127.0.0.1:9998 127.0.0.1 9998 @ mymaster 127.0.0.1 9999        -- 提高 9998 master
3010:X 21 Nov 23:01:13.699 # +failover-state-reconf-slaves master mymaster 127.0.0.1 9999                         -- Failover狀態變爲reconf-slaves狀態時
3010:X 21 Nov 23:01:13.749 * +slave-reconf-sent slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999     -- 從新配置 9997爲slave
3010:X 21 Nov 23:01:14.770 # -odown master mymaster 127.0.0.1 9999                                                -- 離開ODOWN狀態時。
                             -- inprog 9997 slave被從新配置爲9998的master的slave,但數據複製還未發生時。
3010:X 21 Nov 23:01:14.770 * +slave-reconf-inprog slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999 
                             -- done   9997 slave被從新配置爲9998的master的slave,而且數據複製已經與master同步時。
3010:X 21 Nov 23:01:14.770 * +slave-reconf-done slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9999
3010:X 21 Nov 23:01:14.841 # +failover-end master mymaster 127.0.0.1 9999                                        -- 故障轉移結束
3010:X 21 Nov 23:01:14.841 # +switch-master mymaster 127.0.0.1 9999 127.0.0.1 9998                               -- master由9999 替換爲 9998
3010:X 21 Nov 23:01:14.841 * +slave slave 127.0.0.1:9997 127.0.0.1 9997 @ mymaster 127.0.0.1 9998                -- 檢測到9997slave並添加進slave列表時
3010:X 21 Nov 23:01:14.842 * +slave slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998                -- 檢測到9999slave
3010:X 21 Nov 23:01:44.849 # +sdown slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998                -- 進入SDOWN狀態時;
3010:X 21 Nov 23:04:19.457 # -sdown slave 127.0.0.1:9999 127.0.0.1 9999 @ mymaster 127.0.0.1 9998                -- 離開SDOWN狀態時
相關文章
相關標籤/搜索