天天看點

利用redis-sentinel+keepalived實作redis高可用

為上層應用提供高可靠、低延遲、低(無限接近0)資料損失的redis緩存服務

采用同一網絡内的三台主機(可以是實體主機、虛拟機或docker容器),要求三台主機之間都能互相通路,每一台主機上都安裝redis-server、redis-sentinel和keepalived。

redis-server負責提供redis緩存服務,三台主機間的關系是master-slave-slave

redis-sentinel負責提供redis高可用,三台主機間的關系與redis-server相同

keepalived負責提供vip位址供上層應用使用,三台主機的關系是master-backup-backup,vip始終在redis-server master上,保證對上層應用可寫可讀。

三台主機的備援度是1,也就是說當有一台主機當機時另外兩台中至少有一台主機可以提供redis緩存服務

redis-server提供單執行個體的redis緩存服務,redis-sentinel能在一台主機挂掉時自動的将某一台可用主機上的redis-server由slave狀态切換成master狀态。

keepalived通過vrrp_script檢測目前主機上的redis-server是否以master狀态運作,如果目前主機上的redis-server正在以master狀态運作,則将vrrp_instance标記為存活狀态,并配置設定vip;如果目前主機上的redis-server正在以slave狀态運作,則将vrrp_instance标記為錯誤狀态。當某台主機當機後,其他兩台主機上的keepalived會将vip切換到新的master(目前主機上的redis-server正在以master狀态運作)上。

由于keepalived的vip切換有延遲(大約40ms),是以上層應用不能過分依賴redis,例如大規模并發性的短時間内向redis插入大量資料。

利用redis-sentinel+keepalived實作redis高可用

如圖所示,有三台主機,分别辨別為redis1、redis2、redis3,它們的角色和配置等資訊如下:

主機辨別

redis1

redis2

redis3

ip位址

192.168.1.241

192.168.1.242

192.168.1.243

預設配置

redis-server master          

keepalived master

redis-server slave          

keepalived backup

vip

步驟概述

安裝:安裝redis-server、redis-sentinel、keepalived

配置:配置redis1、redis2、redis3,主要是編輯各個服務的配置檔案

啟動:先啟動redis-server、再啟動redis-sentinel、最後自動keepalived

驗證:模拟一台主機當機,主機網絡中斷,redis-server、redis-sentinel、keepalived三個服務任何一個發生故障的情況。

(1)設定主機名(建議設定為fqdn格式)、同步時間、更改檔案描述符最大打開數量、更改核心參數、配置編譯環境、配置防火牆在此就不贅述了。

(2)安裝redis-server和redis-sentinel

redis的安裝由于隻是bin二進制可執行檔案和data目錄比較重要,是以簡化安裝如下    

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<code># http://download.redis.io/redis-stable.tar.gz     </code>

<code>wget -c http:</code><code>//download</code><code>.redis.io</code><code>/releases/redis-3</code><code>.0.7.</code><code>tar</code><code>.gz     </code>

<code>tar</code> <code>zxf redis-3.0.7.</code><code>tar</code><code>.gz     </code>

<code>cd</code> <code>redis-3.0.7     </code>

<code>make</code>     

<code>cd</code>     

<code>\</code><code>cp</code> <code>redis-3.0.7</code><code>/src/redis-benchmark</code> <code>/usr/local/sbin/</code>     

<code>\</code><code>cp</code> <code>redis-3.0.7</code><code>/src/redis-check-aof</code> <code>/usr/local/sbin/</code>     

<code>\</code><code>cp</code> <code>redis-3.0.7</code><code>/src/redis-check-dump</code> <code>/usr/local/sbin/</code>     

<code>\</code><code>cp</code> <code>redis-3.0.7</code><code>/src/redis-cli</code> <code>/usr/local/sbin/</code>     

<code>\</code><code>cp</code> <code>redis-3.0.7</code><code>/src/redis-sentinel</code> <code>/usr/local/sbin/</code>     

<code>\</code><code>cp</code> <code>redis-3.0.7</code><code>/src/redis-server</code> <code>/usr/local/sbin/</code>     

<code>mkdir</code> <code>/etc/redis</code>     

<code>mkdir</code> <code>-p </code><code>/data/redis-6379/</code>

(3)安裝keepalived

<code># http://www.keepalived.org/documentation.html     </code>

<code>wget -c http:</code><code>//www</code><code>.keepalived.org</code><code>/software/keepalived-1</code><code>.2.19.</code><code>tar</code><code>.gz     </code>

<code>tar</code> <code>zxf keepalived-1.2.19.</code><code>tar</code><code>.gz     </code>

<code>cd</code> <code>keepalived-1.2.19     </code>

<code>.</code><code>/configure</code> <code>--prefix=</code><code>/usr/local/keepalived</code>     

<code>make</code> <code>install</code>     

<code>cp</code> <code>/usr/local/keepalived/sbin/keepalived</code> <code>/usr/sbin/</code>     

<code>cp</code> <code>/usr/local/keepalived/etc/sysconfig/keepalived</code> <code>/etc/sysconfig/</code>     

<code>cp</code> <code>/usr/local/keepalived/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/keepalived</code> <code>/etc/init</code><code>.d/     </code>

<code>mkdir</code> <code>/etc/keepalived</code>

keepalived的配置檔案在後面添加

(4)redis1上的redis-sentinel配置檔案

<code>cat</code> <code>&gt;</code><code>/etc/redis/sentinel</code><code>.conf&lt;&lt;eof    </code>

<code>port 26379     </code>

<code>dir</code> <code>/tmp</code>     

<code>sentinel monitor mymaster 192.168.1.241 6379 2     </code>

<code>sentinel down-after-milliseconds mymaster 30000     </code>

<code>sentinel parallel-syncs mymaster 1     </code>

<code>sentinel failover-timeout mymaster 180000     </code>

<code>eof</code>

redis2和redis3上的redis-sentinel配置檔案與redis1上的redis-sentinel配置檔案内容相同。

(5)redis1上的redis-server的配置檔案

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

<code>cat</code> <code>&gt; </code><code>/etc/redis/redis-6379</code><code>.conf &lt;&lt;eof     </code>

<code># maxmemory 268435456     </code>

<code>maxmemory 256mb     </code>

<code>daemonize </code><code>yes</code>     

<code>pidfile </code><code>/data/redis-6379/redis-6379</code><code>.pid     </code>

<code>port 6379     </code>

<code>bind 0.0.0.0     </code>

<code>tcp-backlog 511     </code>

<code>timeout 0     </code>

<code>tcp-keepalive 0     </code>

<code>loglevel notice     </code>

<code>logfile </code><code>/data/redis-6379/redis</code><code>.log     </code>

<code>databases 16     </code>

<code>save 900 1     </code>

<code>save 300 10     </code>

<code>save 60 10000     </code>

<code>stop-writes-on-bgsave-error </code><code>yes</code>     

<code>rdbcompression </code><code>yes</code>     

<code>rdbchecksum </code><code>yes</code>     

<code>dbfilename dumpredis-6379.rdb     </code>

<code>dir</code> <code>/data/redis-6379</code>     

<code>slave-serve-stale-data </code><code>yes</code>     

<code>slave-</code><code>read</code><code>-only </code><code>yes</code>     

<code>repl-diskless-</code><code>sync</code> <code>no     </code>

<code>repl-diskless-</code><code>sync</code><code>-delay 5     </code>

<code># repl-ping-slave-period 10     </code>

<code># repl-timeout 60     </code>

<code>repl-disable-tcp-nodelay no     </code>

<code># repl-backlog-size 1mb     </code>

<code># repl-backlog-ttl 3600     </code>

<code>slave-priority 100     </code>

<code># min-slaves-to-write 3     </code>

<code># min-slaves-max-lag 10     </code>

<code>appendonly no     </code>

<code>appendfilename </code><code>"appendonly.aof"</code>     

<code>appendfsync everysec     </code>

<code>no-appendfsync-on-rewrite no     </code>

<code>auto-aof-rewrite-percentage 100     </code>

<code>auto-aof-rewrite-min-size 64mb     </code>

<code>aof-load-truncated </code><code>yes</code>     

<code>lua-</code><code>time</code><code>-limit 5000     </code>

<code>slowlog-log-slower-than 10000     </code>

<code>slowlog-max-len 128     </code>

<code>latency-monitor-threshold 0     </code>

<code>notify-keyspace-events </code><code>""</code>     

<code>hash</code><code>-max-ziplist-entries 512     </code>

<code>hash</code><code>-max-ziplist-value 64     </code>

<code>list-max-ziplist-entries 512     </code>

<code>list-max-ziplist-value 64     </code>

<code>set</code><code>-max-intset-entries 512     </code>

<code>zset-max-ziplist-entries 128     </code>

<code>zset-max-ziplist-value 64     </code>

<code>hll-sparse-max-bytes 3000     </code>

<code>activerehashing </code><code>yes</code>     

<code>client-output-buffer-limit normal 0 0 0     </code>

<code>client-output-buffer-limit slave 256mb 64mb 60     </code>

<code>client-output-buffer-limit pubsub 32mb 8mb 60     </code>

<code>hz 10     </code>

<code>aof-rewrite-incremental-fsync </code><code>yes</code>     

(6)redis2與redis3上的redis-server配置檔案

<code>cat</code> <code>&gt; </code><code>/etc/redis/redis-6379</code><code>.conf &lt;&lt;eof    </code>

<code>slaveof 192.168.1.241 6379     </code>

<code>repl-diskless-</code><code>sync</code><code>-delay 5 </code>

<code>    </code> 

(7)redis1上的keepalived配置檔案(vim /etc/keepalived/keepalived.conf)

關于keepalived的配置檔案

keepalived的配置檔案預設是沒有的,當然sample&amp;example檔案還是有的,通常在prefix/etc/sample目錄下。

keepalived master和backup(backups)之間不同的是:

1.優先級的不同,master的優先級priority的數字要高一些

2.global_defs段的router_id都不一樣,實際中可以用任意名字區分也可以用主機名區分

3.backup的配置檔案中還有一個nopreempt字段,意思是設定為非搶占模式,作用是讓master優先擷取到vip,并保證vip是在原先的master上。

<code>! configuration file </code><code>for</code> <code>keepalived     </code>

<code>global_defs {     </code>

<code>   </code><code>notification_email {     </code>

<code>     </code><code>root@localhost     </code>

<code>   </code><code>}     </code>

<code>   </code><code>notification_email_from keepalived@localhost     </code>

<code>   </code><code>smtp_server 127.0.0.1     </code>

<code>   </code><code>smtp_connect_timeout 10     </code>

<code>   </code><code>router_id keepalivedha_1     </code>

<code>}     </code>

<code>vrrp_script chk_http_port {     </code>

<code>    </code><code>script </code><code>"redis-cli info | grep role:master &gt;/dev/null 2&gt;&amp;1"</code>     

<code>    </code><code>interval 1     </code>

<code>    </code><code>timeout 2     </code>

<code>    </code><code>fall 2     </code>

<code>    </code><code>rise 1     </code>

<code>vrrp_sync_group vg_1 {     </code>

<code>    </code><code>group {     </code>

<code>        </code><code>vi_1     </code>

<code>    </code><code>}     </code>

<code>vrrp_instance vi_1 {     </code>

<code>    </code><code>state backup     </code>

<code>    </code><code>interface eth1     </code>

<code>    </code><code>#use_vmac keepalived     </code>

<code>    </code><code>#vmac_xmit_base     </code>

<code>    </code><code>mcast_src_ip 192.168.1.241     </code>

<code>    </code><code>smtp_alert     </code>

<code>    </code><code>virtual_router_id 20    </code>

<code>    </code><code>priority 100     </code>

<code>    </code><code>advert_int 1     </code>

<code>    </code><code>authentication {     </code>

<code>        </code><code>auth_type pass     </code>

<code>        </code><code>auth_pass password     </code>

<code>    </code><code>virtual_ipaddress {     </code>

<code>        </code><code>192.168.1.245     </code>

<code>    </code><code>track_script {     </code>

<code>        </code><code>chk_http_port     </code>

<code>}</code>

(8)redis2上的keepalived配置檔案

<code>! configuration file </code><code>for</code> <code>keepalived    </code>

<code>   </code><code>notification_email_from keepalived@localhost    </code>

<code>   </code><code>router_id keepalivedha_2     </code>

<code>    </code><code>interface eth2     </code>

<code>    </code><code>mcast_src_ip 192.168.1.242     </code>

<code>    </code><code>priority 99     </code>

<code>    </code><code>nopreempt     </code>

(9)redis3上的keepalived配置檔案

<code>   </code><code>router_id keepalivedha_3    </code>

<code>    </code><code>mcast_src_ip 192.168.1.243     </code>

<code>    </code><code>priority 98     </code>

(10)啟動redis-server

<code>redis-server </code><code>/etc/redis/redis-6379</code><code>.conf</code>

<code>tail</code> <code>/data/redis-6379/redis</code><code>.log</code>

(11)啟動redis-sentinel

<code>redis-sentinel </code><code>/etc/redis/redis-sentinel</code><code>.conf</code>

<code>tail</code> <code>/data/redis-6379/redis-sentinel</code><code>.log</code>

(12)啟動keepalived

<code>service keepalived start</code>

<code>tail</code> <code>/var/log/messages</code>

如果keepalived啟動後日志如下圖顯示則表示啟動成功。

利用redis-sentinel+keepalived實作redis高可用
利用redis-sentinel+keepalived實作redis高可用

測試分兩塊内容,一是測試鍵值對的set與get,二是測試自增唯一id的是否可用。

(1)測試redis鍵值對的set與get

先不模拟故障,先測試一下redis的set、get和複制情況

利用redis-sentinel+keepalived實作redis高可用
利用redis-sentinel+keepalived實作redis高可用

再測試一下模拟故障出現時redis的set、get和複制情況

停掉redis1上的redis-server

利用redis-sentinel+keepalived實作redis高可用

redis1上的vip已經被移除

利用redis-sentinel+keepalived實作redis高可用
利用redis-sentinel+keepalived實作redis高可用

檢視redis2上的redis狀态和vip狀态

利用redis-sentinel+keepalived實作redis高可用
利用redis-sentinel+keepalived實作redis高可用

通過上圖的***文字可以看出,vip已經漂移到新的redis-server master了。

注意:vip的漂移過程是需要時間的,時間大概需要10*4ms左右,如下圖所示:

利用redis-sentinel+keepalived實作redis高可用
利用redis-sentinel+keepalived實作redis高可用

此時再次測試一下redis的複制情況

利用redis-sentinel+keepalived實作redis高可用

由上圖可見,redis複制情況正常,上層應用依然可以使用redis緩存服務。

(2)測試自增唯一id(autoincrementing unique identifier)

自增唯一id最常見的應用就是作為關系型資料庫的主鍵,因為主鍵必須確定每個資料項都有唯一id。

它也可以在不支援自增唯一id的資料庫中(比如mongodb)用來替代唯一id(uniqueidentifier,通常是一個哈希值)

它也可以為使用者提供更好的url:比如将/topic/4e491e229f328b0cd900010d修改為/topic/10086。

一個自增唯一id對象最重要的是保證值的唯一性,要做到這一點,自增id的自增incr操作必須是一個原子操作,它應該能在一個原子時間内完成以下兩件事:

增加id值,傳回目前id值,并且它也沒有減法decr和清零reset等操作,因為這些操作破壞了唯一性。

get操作一般隻用于内部檢查,比如觀察值是否溢出,但在一般情況下,自增唯一id對象應該隻有一個incr操作。

先測試一下主機健康狀态下的自增唯一id

利用redis-sentinel+keepalived實作redis高可用

發現各個redis-server中的自增唯一id是好用的。再測試一下某台主機故障狀态下的自增唯一id。先根據ip addr找到vip的主機位置,或者通過redis-cli info檢視role找到redis-server master的主機,然後kill redis-server pid,再進行測試。

利用redis-sentinel+keepalived實作redis高可用
利用redis-sentinel+keepalived實作redis高可用

由此發現redis-server中的自增唯一id仍然是好用的。

如果一台主機當機,則主機啟動後,先啟動redis-server、再啟動redis-sentinel、最後自動keepalived。

如果多台主機當機,則按照一台主機當機的步驟做同樣處理。

如果一台主機的中的某台服務停止,則直接啟動該服務即可。

後續

tag:redis叢集,redis高可用,redis-sentinel,keepalived配置,redis主從複制

--end--

繼續閱讀