twemproxy + redis + sentinel 實現redis集羣高可用

本文主要描述使用 twemproxy + redis + sentinel + 腳本 實現redis集羣的高可用,篇幅有點長(實戰配置文件/命令) 前端

先貼個本文主要標題列表哈 git

  • redis簡介
  • sentinel 功能
  • twemproxy特性
  • twemproxy + redis + sentinel 實現redis集羣高可用架構圖
  • 實戰一 :環境部署
  • 實戰二 :redis 主從配置
  • 實戰三 :sentinel 配置
  • 實戰四 :twemproxy 配置


redis

Redis 是徹底開源免費的,遵照BSD協議,內存中的數據結構存儲系統,它能夠用做數據庫、緩存和消息中間件,是一個高性能的key-value數據庫。 github

前面有篇文檔寫到了redis簡介及安裝和壓測數據:http://www.huangdc.com/246 redis


redis sentinel 

redis sentinel 是redis 官方推薦的redis 高可用(HA)解決方案 算法

sentinel 的功能: sql

  • 監控(Monitoring),sentinel 時刻監控着redis master-slave 是否正常運行
  • 通知(Notification),sentinel 能夠經過api 來通知管理員,被監控的redis master-slave 出現了問題
  • 自動故障轉移(Automatic failover),當redis master 出現故障不可用狀態,sentinel 會開始一次故障轉移,將其中一個 slave 提高爲新的master ,將其餘的slave 將從新配置使用新的master同步,並使用Redis的服務器應用程序在鏈接時收到使用新的地址鏈接
  • 配置提供者(Configuration provider) ,sentinel 做爲在集羣中的權威來源,客戶端鏈接到sentinel來獲取某個服務的當前Redis主服務器的地址和其餘信息。當故障轉移發生時,Sentinel 會報告新地址。


twemproxy (nutcraker)

Twemproxy,也叫nutcraker。是一個twtter開源的一個redis 和memcache 快速/輕量級代理服務器;Twemproxy是一個快速的單線程代理程序,支持Memcached ASCII協議和更新的Redis協議
Twemproxy 經過引入一個代理層,能夠將其後端的多臺 Redis 或 Memcached 實例進行統一管理與分配,使應用程序只須要在 Twemproxy 上進行操做,而不用關心後面具體有多少個真實的 Redis 或 Memcached 存儲 數據庫

twemproxy 的特性: json

  • 支持失敗節點自動刪除
    - 能夠設置從新鏈接該節點的時間
    - 能夠設置鏈接多少次以後刪除該節點
  • 支持設置HashTag
    - 經過HashTag能夠本身設定將兩個key哈希到同一個實例上去
  • 減小與redis的直接鏈接數
    - 保持與redis的長鏈接
    - 減小了客戶端直接與服務器鏈接的鏈接數量
  • 自動分片到後端多個redis實例上
    - 多種hash算法:md五、crc1六、crc32 、crc32a、fnv1_6四、fnv1a_6四、fnv1_3二、fnv1a_3二、hsieh、murmur、jenkins
    - 多種分片算法:ketama(一致性hash算法的一種實現)、modula、random
    - 能夠設置後端實例的權重
  • 避免單點問題
    - 能夠平行部署多個代理層,經過HAProxy作負載均衡,將redis的讀寫分散到多個twemproxy上。
  • 支持狀態監控
    - 可設置狀態監控ip和端口,訪問ip和端口能夠獲得一個json格式的狀態信息串
    - 可設置監控信息刷新間隔時間
  • 使用 pipelining 處理請求和響應
    - 鏈接複用,內存複用
    - 將多個鏈接請求,組成reids pipelining統一貫redis請求
  • 並非支持全部redis命令
    - 不支持redis的事務操做
    - 使用SIDFF, SDIFFSTORE, SINTER, SINTERSTORE, SMOVE, SUNION and SUNIONSTORE命令須要保證key都在同一個分片上。


twemproxy + redis + sentinel 高可用架構


redis20160309162514

  • 前端使用twemproxy (主備節點)作代理,將其後端的多臺Redis實例分片進行統一管理與分配
  • 每個分片節點的redis slave 都是redis master的副本且只讀
  • redis sentinel 持續不斷的監控每一個分片節點的master,當master出現故障且不可用狀態時,sentinel 會通知/啓動自動故障轉移等動做
  • sentinel 能夠在發生故障轉移動做後觸發相應腳本(經過 client-reconfig-script 參數配置 ),腳本獲取到最新的master來修改 twemproxy 配置並重啓 twemproxy


實戰一 :環境部署

實驗環境:(簡單化用三臺主機)

ip 系統 部署軟件 twemproxy服務 redis服務 sentinel服務
192.168.16.23 CentOS 6.7 redis
twemproxy
192.168.16.23:14500 _ 192.168.16.23:26379
192.168.16.22 CentOS 6.7 redis _ 192.168.16.22:4500
192.168.16.22:4501
192.168.16.22:26379
192.168.16.24 CentOS 6.7 redis _ 192.168.16.24:4500
192.168.16.24:4501
192.168.16.24:26379

實驗架構圖:

redis20160309180825

安裝redis

分別在三臺服務器都安裝 redis  (192.168.16.22,192.168.16.23,192.168.16.24 ) 後端

## 下載 && 解壓並安裝
wget http://download.redis.io/releases/redis-3.0.6.tar.gz
tar zxf redis-3.0.6.tar.gz
cd redis-3.0.6
make && make install
 
## 檢查bin文件 及 版本(默認bin文件路徑爲 /usr/local/bin/ ,也能夠在編譯時候加上 --prefix 參數自定義目錄)
[root@vm16-22 ~]# ll /usr/local/bin/redis*
-rwxr-xr-x 1 root root 4589115 Feb 23 15:07 /usr/local/bin/redis-benchmark
-rwxr-xr-x 1 root root   22177 Feb 23 15:07 /usr/local/bin/redis-check-aof
-rwxr-xr-x 1 root root   45395 Feb 23 15:07 /usr/local/bin/redis-check-dump
-rwxr-xr-x 1 root root 4698322 Feb 23 15:07 /usr/local/bin/redis-cli
lrwxrwxrwx 1 root root      12 Feb 23 15:07 /usr/local/bin/redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 6471190 Feb 23 15:07 /usr/local/bin/redis-server
[root@vm16-22 ~]# /usr/local/bin/redis-server -v
Redis server v=3.0.6 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=a1df4a293d9213e9

安裝twemproxy

在 192.168.16.23 服務器安裝 twemproxy api

安裝twemproxy 前,須要安裝autoconf,automake,libtool 軟件包

一、編譯安裝autoconf

## 下載 && 解壓並安裝
wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
tar zxf autoconf-2.69.tar.gz
./configure
make && make install

二、編譯安裝automake

## 下載 && 解壓並安裝
wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
tar zxf automake-1.15.tar.gz
./configure
make && make install

三、編譯安裝libtool

## 下載 && 解壓並安裝
wget https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz
tar zxf libtool-2.4.6.tar.gz
cd libtool-2.4.6
./configure
make && make install

四、編譯安裝twemproxy

## 下載 && 解壓並安裝
wget https://github.com/twitter/twemproxy/archive/master.zip
unzip master.zip
cd twemproxy-master
## 在twemproxy源碼目錄執行autoreconf 生成 configure文件等
aclocal
autoreconf -f -i -Wall,no-obsolete
## 而後編譯安裝
./configure --prefix=/usr/local/twemproxy/
make && make install

注意:若是沒有安裝libtool 的話,autoreconf 的時候會報錯,以下:

configure.ac:133: the top level
configure.ac:36: error: possibly undefined macro: AC_PROG_LIBTOOL
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
autoreconf: /usr/local/bin/autoconf failed with exit status: 1


實戰二 : redis 主從配置

一、建立目錄環境

##
## 在192.168.12.22 , 192.168.12.24 建立目錄
mkdir -p /data/nosql/{redis_4500,redis_4501,sentinel}

## 在192.168.12.23 建立目錄
mkdir -p /data/nosql/sentinel
mkdir -p /usr/local/twemproxy/{conf,logs}


192.168.12.22:4500 -> 192.168.12.24:4500 (主->從)

192.168.12.22:4501 -> 192.168.12.24:4501 (主->從)

二、在 192.168.12.22 配置 192.168.12.22:4500  redis master

在192.168.12.22 配置master文件 /data/nosql/redis_4500/redis.conf  ,文件內容以下:

daemonize yes     ##使用daemon 方式運行程序,默認爲非daemon方式運行
pidfile "/data/nosql/redis_4500/redis.pid"    ##pid文件位置
port 4500            ##監聽端口
bind 192.168.16.22   ##綁定ip
timeout 0            ## client 端空閒斷開鏈接的時間
loglevel warning     ##日誌記錄級別,默認是notice,我這邊使用warning,是爲了監控日誌方便。
                     ## 使用warning後,只有發生告警纔會產生日誌,這對於經過判斷日誌文件是否爲空來監控報警很是方便。
logfile "/data/nosql/redis_4500/redis.log"
databases 16     ##默認是0,也就是隻用1 個db,我這邊設置成16,方便多個應用使用同一個redis server。
                 ##使用select n 命令能夠確認使用的redis db ,這樣不一樣的應用即便使用相同的key也不會有問題。

##下面是SNAPSHOTTING持久化方式的策略。
##爲了保證數據相對安全,在下面的設置中,更改越頻繁,SNAPSHOTTING越頻繁,
##也就是說,壓力越大,反而花在持久化上的資源會越多。
##因此我選擇了master-slave模式,並在master關掉了SNAPSHOTTING。
save 900 1     #在900秒以內,redis至少發生1次修改則redis抓快照到磁盤
save 300 10    #在300秒以內,redis至少發生100次修改則redis抓快照到磁盤
save 60 10000  #在60秒以內,redis至少發生10000次修改則redis抓快照到磁盤
stop-writes-on-bgsave-error yes
rdbcompression yes   ##使用壓縮
rdbchecksum yes
dbfilename "dump.rdb"
dir "/data/nosql/redis_4500"

## replication 設置
slave-serve-stale-data yes
slave-read-only yes
slave-priority 100

###LIMIT 設置
maxmemory 256mb   ##redis最大可以使用的內存量,若是使用redis SNAPSHOTTING的copy-on-write的持久會寫方式,會額外的使用內存,
                  ##爲了使持久會操做不會使用系統VM,使redis服務器性能降低,建議保留redis最大使用內存的一半來留給持久化使用
maxmemory-policy allkeys-lru  ##使用LRU算法刪除設置了過時時間的key,但若是程序寫的時間沒有寫key的過時時間
                              ##建議使用allkeys-lru,這樣至少保證redis不會不可寫入

##append only mode設置
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000

###slow log 設置
slowlog-log-slower-than 10000
slowlog-max-len 128

##advanced config設置,下面的設置主要是用來節省內存的
hash-max-ziplist-entries 1024
hash-max-ziplist-value 2048
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

啓動master 4500 端口:

##
[root@vm16-22 ~]# /usr/local/bin/redis-server /data/nosql/redis_4500/redis.conf


三、在 192.168.12.24 配置 192.168.12.24:4500  redis slave

在 192.168.12.24 配置slave文件 /data/nosql/redis_4500/redis.conf

redis slave 從實例須要多加一個配置參數:  slaveof 192.168.16.22 4500  , 指明master 的ip 和端口

文件內容以下:

daemonize yes
pidfile "/data/nosql/redis_4500/redis.pid"
port 4500     ##監聽端口
bind 192.168.16.24  ##綁定ip
timeout 0
loglevel warning
logfile "/data/nosql/redis_4500/redis.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dump.rdb"
dir "/data/nosql/redis_4500"
slave-serve-stale-data yes
slave-read-only yes
slave-priority 100
maxmemory 256mb      ##緩存大小
maxmemory-policy allkeys-lru
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
hash-max-ziplist-entries 1024
hash-max-ziplist-value 2048
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

# Generated by CONFIG REWRITE
## slave 實例只須要配置 slaveof 便可 
slaveof 192.168.16.22 4500

啓動 slave 實例服務

##
[root@vm16-24 ~]# /usr/local/bin/redis-server /data/nosql/redis_4500/redis.conf

四、192.168.12.22:4501 -> 192.168.12.24:4501  的 master->slave 同理第二、3步驟

五、檢查兩個主從實例信息:

## 查看redis 進程
[root@vm16-22 ~]# ps -ef |grep redis
root     37694     1  0 Mar04 ?        00:10:52 /usr/local/bin/redis-server 192.168.16.22:4501
root     39611 65000  0 22:03 pts/2    00:00:00 grep redis  
root     60304     1  0 Mar04 ?        00:10:07 /usr/local/bin/redis-server 192.168.16.22:4500  

[root@vm16-24 ~]# ps -ef |grep redis
root     36265     1  0 Mar04 ?        00:10:08 /usr/local/bin/redis-server 192.168.16.24:4501
root     63873 24110  0 22:03 pts/0    00:00:00 grep redis
root     65394     1  0 Mar04 ?        00:10:38 /usr/local/bin/redis-server 192.168.16.24:4500 


## 檢查主從信息  info replication
### 4500 端口主信息
[root@vm16-22 ~]# redis-cli -h 192.168.16.22 -p 4500 info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.16.24,port=4500,state=online,offset=96330188,lag=0
master_repl_offset:96330188
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:95281613
repl_backlog_histlen:1048576

### 4500 端口從信息
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4500 info replication
# Replication
role:slave
master_host:192.168.16.22
master_port:4500
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:96354366
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

### 4501 端口主信息
[root@vm16-22 ~]# redis-cli -h 192.168.16.22 -p 4501 info replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.16.24,port=4501,state=online,offset=50410,lag=0
master_repl_offset:50553
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:50552


### 4501 端口從信息
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4501 info replication
# Replication
role:slave
master_host:192.168.16.22
master_port:4501
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:75031
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

六、檢查兩個主從實例同步:

檢查 192.168.12.22:4500 -> 192.168.12.24:4500 (主->從)同步

## 主設置一個key  huangdc
[root@vm16-22 ~]# redis-cli -h 192.168.16.22 -p 4500 set huangdc "i love you"
OK
## 在從獲取
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4500 get huangdc
"i love you"

檢查 192.168.12.22:4501 -> 192.168.12.24:4501 (主->從)同步

## 主設置一個key  huangdc4501
[root@vm16-22 ~]# redis-cli -h 192.168.16.22 -p 4500 set huangdc4501 "i love you 4501"
OK
## 在從獲取
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4500 get huangdc4501
"i love you 4501"

ok , 兩個主從同步沒有問題

實戰三 : sentinel 配置

在三臺服務器配置 sentinel ,sentinel 默認監聽端口是 26379

一、三臺服務器的sentinel 配置文件 /data/nosql/sentinel/sentinel.conf ,內容以下:

# Global
port 26379       ##監聽端口
daemonize yes    ##使用daemon方式運行程序,默認爲非daemon方式運行
dir "/data/nosql/sentinel"
pidfile "/data/nosql/sentinel/sentinel.pid"
loglevel notice
logfile "/data/nosql/sentinel/sentinel.log"
##
## sentinel monitor <master-group-name> <ip> <port> <quorum>     
####行尾的<quorum>是數字
####這個數字代表須要最少多少個sentinel互相溝通來確認某個master是否真的死了
#
## sentinel <option_name> <master-group-name> <option_value>
#### down-after-milliseconds : sentinel會向master發送心跳PING來確認master是否存活,若是master在「必定時間範圍」內不迴應PONG或者是回覆了一個錯誤消息,那麼這個sentinel會主觀地(單方面地)認爲這個master已經不可用了(subjectively down, 也簡稱爲SDOWN)。而這個down-after-milliseconds就是用來指定這個「必定時間範圍」的,單位是毫秒。
#### failover-timeout : 這個選項肯定自動轉移故障超時時間,單位毫秒
#### parallel-syncs : 在發生failover主備切換時,這個選項指定了最多能夠有多少個slave同時對新的master進行同步

sentinel monitor redis_14555_g1_4500 192.168.16.22 4500 2 
sentinel down-after-milliseconds redis_14555_g1_4500 2500
sentinel failover-timeout redis_14555_g1_4500 10000
sentinel parallel-syncs redis_14555_g1_4500 1

sentinel monitor redis_14555_g2_4501 192.168.16.22 4501 2
sentinel down-after-milliseconds redis_14555_g2_4501 2500
sentinel failover-timeout redis_14555_g2_4501 10000
sentinel parallel-syncs redis_14555_g2_4501 1

上面的配置項配置了兩個名字分別爲redis_14555_g1_4500 和redis_14555_g2_4501 的master,配置文件只須要配置master的信息就好啦,不用配置slave的信息,由於slave可以被自動檢測到(master節點會有關於slave的消息)。須要注意的是,配置文件在sentinel運行期間是會被動態修改的,例如當發生主備切換時候,配置文件中的master會被修改成另一個slave。這樣,以後sentinel若是重啓時,就能夠根據這個配置來恢復其以前所監控的redis集羣的狀態。

你們在這裏記一下我給兩個master的命名爲 redis_14555_g1_4500 和 redis_14555_g2_4501  ,是有目的的,爲了sentinel 後面觸發修改twemproxy 的配置文件和重啓有關係

sentinel 的配置信息也能夠經過動態配置 ,如 SENTINEL SET command動態修改

二、在三臺服務器分別啓動 sentinel 服務

#
/usr/local/bin/redis-sentinel /data/nosql/sentinel/sentinel.conf

三、測試sentinel 自動故障轉移(kill掉一個master ,sentinel 會將slave 提高爲master)

在前面redis 配置主從時候,咱們已經檢查過了 主從的信息

## 查看 192.168.16.24:4501 的信息( role:slave )
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4501 info replication
# Replication
role:slave      ## slave
master_host:192.168.16.22
master_port:4501
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:855442
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

## kill 掉 192.168.16.22:4501  master 進程  
[root@vm16-22 ~]# ps -ef |grep 4501 
root     14455 59263  0 23:16 pts/2    00:00:00 grep 4501
root     37694     1  0 Mar04 ?        00:10:58 /usr/local/bin/redis-server 192.168.16.22:4501               
[root@vm16-22 ~]# kill 37694
[root@vm16-22 ~]# ps -ef |grep 4501 
root     14532 59263  0 23:16 pts/2    00:00:00 grep 4501

## 立馬再次查看 192.168.16.24:4501 的信息,角色role 仍是slave ;由於故障轉移須要一點時間
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4501 info replication
# Replication
role:slave   ## slave
master_host:192.168.16.22
master_port:4501
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:857887
master_link_down_since_seconds:20
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

## 稍等幾秒,再次查看 192.168.16.24:4501 的信息,角色role 仍是master;故障轉移成功,提高slave爲 master了
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4501 info replication
# Replication
role:master    ## master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
[root@vm16-22 ~]#

四、查看一臺sentinel 的日誌信息

55580:X 09 Mar 23:17:01.856 # +new-epoch 9
55580:X 09 Mar 23:17:01.856 # +try-failover master redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:01.900 # +vote-for-leader f88ba4336b43abddc5c9fbffbc564b2bc213560c 9
55580:X 09 Mar 23:17:01.979 # 192.168.16.23:26379 voted for f88ba4336b43abddc5c9fbffbc564b2bc213560c 9
55580:X 09 Mar 23:17:01.986 # 192.168.16.24:26379 voted for f88ba4336b43abddc5c9fbffbc564b2bc213560c 9
55580:X 09 Mar 23:17:02.040 # +elected-leader master redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.040 # +failover-state-select-slave master redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.117 # +selected-slave slave 192.168.16.24:4501 192.168.16.24 4501 @ redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.117 * +failover-state-send-slaveof-noone slave 192.168.16.24:4501 192.168.16.24 4501 @ redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.176 * +failover-state-wait-promotion slave 192.168.16.24:4501 192.168.16.24 4501 @ redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.425 # +promoted-slave slave 192.168.16.24:4501 192.168.16.24 4501 @ redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.425 # +failover-state-reconf-slaves master redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.425 # +failover-end master redis_14555_g2_4501 192.168.16.22 4501
55580:X 09 Mar 23:17:02.425 # +switch-master redis_14555_g2_4501 192.168.16.22 4501 192.168.16.24 4501
55580:X 09 Mar 23:17:02.426 * +slave slave 192.168.16.22:4501 192.168.16.22 4501 @ redis_14555_g2_4501 192.168.16.24 4501
55580:X 09 Mar 23:17:04.956 # +sdown slave 192.168.16.22:4501 192.168.16.22 4501 @ redis_14555_g2_4501 192.168.16.24 4501

你們能夠自行查看一下相關說明


實戰四 : twemproxy 配置

由於sentinel 確保了 redis 主從故障轉移,當master 出現故障後,將slave提高爲master 繼續爲客戶端提供緩存服務;可是新的master ip 和端口信息已經發生了改變,因此客戶端須要從新配置文件或者改造程序才能從新鏈接新的master ,這樣有點不方便 。爲了方便客戶端無需改造及redis 達到高可用狀態(故障恢復時間保持在1分鐘內),咱們採用 twemproxy 作redis 前端代理,分片存儲數據,結合sentinel故障轉移時的通知/觸發腳本功能,作一個自動故障轉移且高可用的redis 集羣。也就是本文最開始的架構圖 twemproxy + redis + sentinel + 腳本 實現redis高可用架構(高可用集羣)

redis 主從 和 sentinel 基本都已經配置好了,咱們如今來配置一下 twemproxy

一、在 192.168.16.23 服務器上配置twemproxy ,配置文件爲 /usr/local/twemproxy/conf/redis_14555.yml

內容爲:

redis_14555:
  listen: 192.168.16.23:14555
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  redis: true
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
   - 192.168.16.22:4500:1
   - 192.168.16.22:4501:1

上面配置了兩個redis master 的分片 192.168.16.22:4500 和 192.168.16.22:4501 。

這裏的參數咱們先不講,咱們看看配置的文件名是 redis_14555.yml ,你們有沒有想起來,跟sentinel monitor 監控的 master-group-name 有關係,對了取的就是master-group-name 的前半段(redis_14555_g1_4500); 你們再記住一下,後面還會用到

二、啓動twemproxy

## 啓動
[root@vm16-23 ~]# /usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/redis_14555.yml -p /usr/local/twemproxy/conf/redis_14555.pid -o /usr/local/twemproxy/logs/redis_14555.log -v 11 -d

[root@vm16-23 ~]# ps -ef |grep nutcracker
root      9356     1  0 23:56 ?        00:00:00 /usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/redis_14555.yml -p /usr/local/twemproxy/conf/redis_14555.pid -o /usr/local/twemproxy/logs/redis_14555.log -v 11 -d

啓動相關參數信息說明:

Usage: nutcracker [-?hVdDt] [-v verbosity level] [-o output file]
                  [-c conf file] [-s stats port] [-a stats addr]
                  [-i stats interval] [-p pid file] [-m mbuf size]
Options:
  -h, --help             : this help
  -V, --version          : show version and exit
  -t, --test-conf        : test configuration for syntax errors and exit
  -d, --daemonize        : run as a daemon
  -D, --describe-stats   : print stats description and exit
  -v, --verbose=N        : set logging level (default: 5, min: 0, max: 11)
  -o, --output=S         : set logging file (default: stderr)
  -c, --conf-file=S      : set configuration file (default: conf/nutcracker.yml)
  -s, --stats-port=N     : set stats monitoring port (default: 22222)
  -a, --stats-addr=S     : set stats monitoring ip (default: 0.0.0.0)
  -i, --stats-interval=N : set stats aggregation interval in msec (default: 30000 msec)
  -p, --pid-file=S       : set pid file (default: off)
  -m, --mbuf-size=N      : set size of mbuf chunk in bytes (default: 16384 bytes)

三、測試 twemproxy set/get ,後端分片查看

## 測試set 和 get

## 測試短key - value
[root@vm16-23 ~]# redis-cli -h 192.168.16.23 -p 14555 set huang "dc"
OK
[root@vm16-23 ~]# redis-cli -h 192.168.16.23 -p 14555 get huang
"dc"

## 測試長key - value
[root@vm16-23 ~]# redis-cli -h 192.168.16.23 -p 14555 set huangggggggggggggggggggggggggg "dccccccccccccccccccccccccccccccccccccc"
OK
[root@vm16-23 ~]# redis-cli -h 192.168.16.23 -p 14555 get huangggggggggggggggggggggggggg
"dccccccccccccccccccccccccccccccccccccc"

## 直接經過後端redis 的master get key 查看存儲,會發現已經分片了
[root@vm16-23 ~]# redis-cli -h 192.168.16.22 -p 4500 get huang
"dc"
[root@vm16-23 ~]# redis-cli -h 192.168.16.22 -p 4501 get huang
(nil)

[root@vm16-23 ~]# redis-cli -h 192.168.16.22 -p 4500 get huangggggggggggggggggggggggggg
(nil)
[root@vm16-23 ~]# redis-cli -h 192.168.16.22 -p 4501 get huangggggggggggggggggggggggggg
"dccccccccccccccccccccccccccccccccccccc"

咱們如今將 192.168.16.22:4501 master  直接kill 掉 ,並查看 192.168.16.22:4501 的從服務192.168.16.24:4501是否被提示爲 master

[root@vm16-22 ~]# ps -ef |grep 4501
root     18304     1  0 Mar09 ?        00:00:03 /usr/local/bin/redis-server 192.168.16.22:4501               
root     41826 59263  0 00:07 pts/2    00:00:00 grep 4501
[root@vm16-22 ~]# kill 18304
[root@vm16-22 ~]# ps -ef |grep 4501
root     41871 59263  0 00:07 pts/2    00:00:00 grep 4501


## 查看從服務是否被提高爲新的 master ,以下所示,很明顯已經被提高爲master了
[root@vm16-22 ~]# redis-cli -h 192.168.16.24 -p 4501 info replication
# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

好了,咱們再次經過 twemproxy 獲取 剛剛設置的兩個key 「huang」 和 「huangggggggggggggggggggggggggg"

## 
[root@vm16-23 ~]# redis-cli -h 192.168.16.23 -p 14555 get huang
"dc"
[root@vm16-23 ~]# redis-cli -h 192.168.16.23 -p 14555 get huangggggggggggggggggggggggggg
(error) ERR Connection refused

## 很明顯,剛剛存儲在 4501 上面的key:huangggggggggggggggggggggggggg 已經獲取不到了

爲了讓redis 達到高可用狀態,咱們還須要在 sentinel 發送故障轉移的時候,將新的master ip和端口告知twemproxy ,並修改twemproxy的配置文件和重啓nutcracker服務,下一步見分曉

四、sentinel 配置 client-reconfig-script 腳本

增長腳本 /data/nosql/sentinel/client-reconfig.sh ; 並添加執行權限 chmod +x /data/nosql/sentinel/client-reconfig.sh ; 腳本內容以下:

#!/bin/sh 
###  sentinel 觸發執行此腳本時,會默認傳遞幾個參數過來
###  <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
#
monitor_name="$1"   ##monitor master-group-name
master_old_ip="$4"
master_old_port="$5"
master_new_ip="$6"
master_new_port="$7"
twemproxy_name=$(echo $monitor_name |awk -F'_' '{print $1"_"$2}')   ##注意 
## 本文前面已經提了2次讓你們記住一個地方 master-group-name ,我這邊的命名規則 redis_14555_g1_4500 , 這裏我就是爲了獲取redis_14555 , 由於twemproxy 的配置文件名用的是 redis_14555.yml ;
## 這裏經過獲取  master-group-name 來修改 twemproxy 的配置文件,這裏定的一點規範而已

twemproxy_bin="/usr/local/twemproxy/sbin/nutcracker"
twemproxy_conf="/usr/local/twemproxy/conf/${twemproxy_name}.yml"
twemproxy_pid="/usr/local/twemproxy/conf/${twemproxy_name}.pid"
twemproxy_log="/usr/local/twemproxy/logs/${twemproxy_name}.log"
twemproxy_cmd="${twemproxy_bin} -c ${twemproxy_conf} -p ${twemproxy_pid} -o ${twemproxy_log} -v 11 -d"

## 將新的master 端口和ip 替換掉 twemproxy 配置文件中舊的master 信息
sed -i "s/${master_old_ip}:${master_old_port}/${master_new_ip}:${master_new_port}/" ${twemproxy_conf}

## kill 掉根據redis_14555.yml配置啓動的nutcracker 進程 ,並從新啓動
ps -ef |grep "${twemproxy_cmd}" |grep -v grep |awk '{print $2}'|xargs kill
${twemproxy_cmd}

sleep 1
ps -ef |grep "${twemproxy_cmd}" |grep -v grep

動態修改192.168.16.23:26379 sentinel 的配置,添加 client-reconfig-script 項

[root@vm16-23 sentinel]# redis-cli -h 192.168.16.23 -p 26379 sentinel set redis_14555_g1_4500 client-reconfig-script /data/nosql/sentinel/client-reconfig.sh
OK
[root@vm16-23 sentinel]# redis-cli -h 192.168.16.23 -p 26379 sentinel set redis_14555_g2_4501 client-reconfig-script /data/nosql/sentinel/client-reconfig.sh
OK
[root@vm16-23 sentinel]#

五、再次測試 twemproxy

咱們確認一下 twemproxy的配置文件的 servers 信息:(/usr/local/twemproxy/conf/redis_14555.yml)

[root@vm16-23 sentinel]# cat /usr/local/twemproxy/conf/redis_14555.yml 
redis_14555:
  listen: 192.168.16.23:14555
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  redis: true
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
   - 192.168.16.22:4500:1
   - 192.168.16.22:4501:1

### 肯定servers項的信息爲 192.168.16.22:4500:1 和 192.168.16.22:4501:1

好了,在192.168.16.22服務器上,咱們把 192.168.16.22:4501 master 幹掉,直接kill 掉

[root@vm16-22 sentinel]# ps -ef |grep 4501 |grep -v grep 
root     61109     1  0 00:41 ?        00:00:00 /usr/local/bin/redis-server 192.168.16.22:4501               
[root@vm16-22 sentinel]# kill 61109
[root@vm16-22 sentinel]# ps -ef |grep 4501 |grep -v grep

經過twemproxy 代理192.168.16.23:14555 獲取key 「huang」 和 「huangggggggggggggggggggggggggg"的值

[root@vm16-22 sentinel]# redis-cli -h 192.168.16.23 -p 14555 get huang
"123"
[root@vm16-22 sentinel]# redis-cli -h 192.168.16.23 -p 14555 get huangggggggggggggggggggggggggg
"dccccccccccccccccccccccccccccccccccccc"
[root@vm16-22 sentinel]#

## oh oh  獲取到了

再次查看twemproxy 的配置文件的 servers 信息:(/usr/local/twemproxy/conf/redis_14555.yml)

[root@vm16-23 sentinel]# cat /usr/local/twemproxy/conf/redis_14555.yml
redis_14555:
  listen: 192.168.16.23:14555
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  redis: true
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
   - 192.168.16.22:4500:1
   - 192.168.16.24:4501:1

看到沒有,看到沒有,看到沒有,192.168.16.22:4501 已經被替換爲 192.168.16.24:4501 了。

twemproxy + redis + sentinel + 腳本 實現redis高可用架構(高可用集羣)

twemproxy 有個缺點:若是 Twemproxy 的後端節點數量發生變化,Twemproxy 相同算法的的狀況下,原來的數據必須從新處理分佈,不然會存在找不到key值的狀況

相關文章
相關標籤/搜索