redis高可用叢集介紹
一、redis的高可用管理工具sentinel介紹
sentinel是一個管理redis例項的工具,它可以實現對redis的監控、通知、自動故障轉移。sentinel不斷的檢測redis例項是否可以正常工作,通過API向其他程式報告redis的狀態,
如果redis master不能工作,則會自動啟動故障轉移程序,將其中的一個slave提升(通過選舉)為master,其他的slave重新設定新的master伺服器。而故障的master再次啟動後會被sentinel自動降級為slave伺服器加入到叢集中。
redis主從的特點:
1、redis使用非同步複製,從伺服器會以每秒一次的頻率向主伺服器報告複製流的處理進度
2、一個主伺服器可以有多個從伺服器,從伺服器也可以有自己的從伺服器(級聯複製)
3、複製功能不會阻塞主伺服器,即使一個或多個從伺服器正在進行初次同步,主伺服器也可以繼續處理命令請求
4、複製功能可以用於資料冗餘,也可以通過讓多個從伺服器處理只讀命令請求來提升擴充套件性
5、Redis從節點預設為只讀,無須手動配置
redis的主從叢集可以實現分擔壓力的效果,但是無法做到高可用,如果master宕掉,服務就不可用了,所以使用redis的sentinel可以實現HA的功能:
sentinel作用如下:
1、監控:sentinel會不斷的檢查你的主伺服器和從伺服器是否執行正常
2、當被監控的某個redis伺服器出現問題時,sentinel可以通過API向管理員或者其他應用程式傳送通知
3、自動故障轉移:當一個主伺服器不能正常工作時,sentinel會開始一次自動故障轉移操作,他會將其中一個從伺服器升級為新的主伺服器,並將其他從伺服器改為複製新的主伺服器;當客戶端試圖連線失效的主伺服器時,叢集也會向客戶端返回新主伺服器的地址,使得叢集可以使用新主伺服器代替失效伺服器。
二、部署說明
redis-server 192.168.248.131
redis-slave 192.168.248.132
redis-slave 192.168.248.133
先進行的主從的配置
安裝redis
redis可以根據自己的需求去redist官網去下載https://redis.io/download
tar –zxvf redis-3.0.7.tar.gz
cd redis-3.0.7
make
mkdir –pv /data/redis
之後將redis的命令檔案拷貝到/usr/local/sbin下面去
cd /usr/local/src/redis-3.0.7/src
cp redis-benchmark redis-check-aof redis-check-dump redis-cliredis-server redis-sentinel /usr/local/sbin
redis-server的redis.conf配置檔案
cat > /etc/redis/redis.conf <<EOF
maxmemory 256mb
daemonize yes
pidfile"/data/redis/redis-6379.pid"
port 6379
bind 0.0.0.0
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel notice
logfile "/data/redis/redis.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dumpredis-6379.rdb"
dir "/data/redis"
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
# repl-ping-slave-period 10
# repl-timeout 60
repl-disable-tcp-nodelay no
# repl-backlog-size 1mb
# repl-backlog-ttl 3600
slave-priority 100
# min-slaves-to-write 3
# min-slaves-max-lag 10
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
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
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb60
client-output-buffer-limit pubsub 32mb 8mb60
hz 10
aof-rewrite-incremental-fsync yes
EOF
slave的redis.conf
cat >/etc/redis/redis.conf <<EOF
slaveof 192.168.248.131 6379
maxmemory 256mb
daemonize yes
pidfile"/data/redis/redis-6379.pid"
port 6379
bind 0.0.0.0
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel notice
logfile "/data/redis/redis.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename "dumpredis-6379.rdb"
dir "/data/redis"
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
# repl-ping-slave-period 10
# repl-timeout 60
repl-disable-tcp-nodelay no
# repl-backlog-size 1mb
# repl-backlog-ttl 3600
slave-priority 100
# min-slaves-to-write 3
# min-slaves-max-lag 10
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
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
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb60
client-output-buffer-limit pubsub 32mb 8mb60
hz 10
aof-rewrite-incremental-fsync yes
EOF
在slave的配置檔案中需要指明的是slaveof masterip port
之後就組成了redis的叢集,但是這樣同樣會存在問題,如果我們的master出現問題之後,slave就會找不到master同步資料,另外client端也會發生找不到master從而不能寫的請求被拒絕的情況。
所以下面為redis新增sentinel新增哨兵,哨兵的作用就是當redis的master發生改變的時候,會在其餘的slave中重新選舉一個新的master,如果原來的master的redis服務恢復之後,他不會重新的搶回master的角色,而是會被降級為slave。
redis-sentinel.conf
cat>/etc/redis/sentinel.conf <<EOF
dir /tmp
sentinel monitor mymaster 192.168.248.131 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
EOF
三個節點的sentinel.conf配置檔案是一樣的。
之後啟動redis-server和redis-sentinel服務
redis-server /etc/redis/redis.conf &
redis-sentinel /etc/redis/sentinel.conf &
表示兩個服務全部從在後臺啟動。
redis配置檔案解析
maxmemory 256mb
redis可以使用的最大的記憶體大小,redis訪問速度非常快的原因是他把資料全部的載入到記憶體中去,然後在持久化到磁碟中。但是如果記憶體滿了的話,那麼redis就會清除一些key,這些key是設定了超時時間的key,雖然超時時間還沒有到,但是仍然有可能被刪除。如果刪除了這些key之後,仍然沒有辦法多餘空間的話,那麼redis就會返回錯誤給連線的客戶端。
daemonize yes
是不是以守護程序的方式執行,如果此處是yes的話,在啟動redis的時候,我們就不需要使用&,讓服務去後臺執行。
pidfile"/data/redis/redis-6379.pid"
redis的pid檔案所在的位置
port 6379
redis監聽的埠
bind 0.0.0.0
監聽的地址,如果為了保證安全的話在此處可以進行限制為自己需要的內網地址
tcp-backlog 511
為了避免redis客戶端連線的慢,需要調節的redis客戶端的最大的數量,這個值會預設的設定為/proc/sys/net/core/somaxconn下面的數量,所以如果想要修改的話,記住兩處都要修改
timeout 0
客戶端連線的超時時間,如果是0的話表示的話,不超時,不管這個連線
tcp-keepalive 0
是不是啟用長連線,0表示不啟用
loglevel notice
日誌的級別,日誌級別有四種debug notice info warning
logfile "/data/redis/redis.log"
日誌檔案的位置
databases 16
啟用的資料庫
save 900 1
save 300 10
save 60 10000
在相應的時間內有多少個key發生了變化,就將資料持久化到磁碟中去
stop-writes-on-bgsave-error yes
當後臺儲存失敗,持久化失敗的是,是不是停止進行寫操作
rdbcompression yes
資料是否壓縮
rdbchecksum yes
是否對資料進行校驗
dbfilename "dumpredis-6379.rdb"
持久化資料的名稱
dir "/data/redis"
資料的儲存路徑
slave-serve-stale-data yes
當slave和master數去聯絡或者是在進行資料複製的時候,是不是仍然提供給客戶端服務
slave-read-only yes
slave是不是隻是隻讀的
repl-diskless-sync no
複製集同步策略:磁碟或者socket
新slave連線或者老slave重新連線時候不能只接收不同,得做一個全同步。需要一個新的RDB檔案dump出來,然後從master傳到slave。可以有兩種情況:
1)基於硬碟(disk-backed):master建立一個新程序dump RDB,完事兒之後由父程序(即主程序)增量傳給slaves。
2)基於socket(diskless):master建立一個新程序直接dumpRDB到slave的socket,不經過主程序,不經過硬碟。
基於硬碟的話,RDB檔案建立後,一旦建立完畢,可以同時服務更多的slave。基於socket的話,新slave來了後,得排隊(如果超出了repl-diskless-sync-delay還沒來),完事兒一個再進行下一個。
當用diskless的時候,master等待一個repl-diskless-sync-delay的秒數,如果沒slave來的話,就直接傳,後來的得排隊等了。否則就可以一起傳。
disk較慢,並且網路較快的時候,可以用diskless。(預設用disk-based)
repl-diskless-sync-delay 5
同步延遲時間
# repl-ping-slave-period 10
# repl-timeout 60
repl-disable-tcp-nodelay no
# repl-backlog-size 1mb
# repl-backlog-ttl 3600
slave-priority 100
slave的優先順序(和競選master有關係)
# min-slaves-to-write 3
# min-slaves-max-lag 10
appendonly no
redis非同步的dump資料到disk,如果是斷電了那麼就會有比部分資料丟失,aof則提供了更好的方式,保證瞭如果發生錯誤那麼丟失的僅僅是上一秒的資料或者是上一次寫操作的資料。當aof檔案過大的話就會重新再生成另外的一個aof檔案
appendfilename "appendonly.aof"
aof檔案的名稱
appendfsync everysec
檔案的同步的方式,有單重 no always everysec ,第一種的話由作業系統自己決定,這樣子會跟快,第二種的話是每次寫操作更新速度慢但是最安全,第三種是每秒進行一次 兩種的折中辦法
no-appendfsync-on-rewrite no
當fsync為always或者everysec,當一個bgsave或者AOF rewrite執行緒正在耗費大量I/0,redis可能會在fsync上阻塞很久。發生之後就無法fix,即使是另一個執行緒跑fsync,也會阻塞我們同步的write方法。
如下方法可以解決這個問題:當bgsave()或bgrewriteaof()在跑,主程序的fsync()就無法呼叫。也就是當子程序在save,那段時光相當於redis是appendaof no的。也就是有可能會丟失最多30s的log。
所以如果你有lag問題,把下邊改成yes,否則就用no。yes意思是暫停aof,拒絕主程序的這次fsync。no是redis是排隊的,不會被prevent了,但主程序是阻塞的。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
自動重寫AOF
當AOF檔案大小到一定比例,就自動隱式呼叫BGREWRITEAOF
過程:redis記住最後一次rewrite時aof檔案大小(重啟後沒rewrite的話,就是啟動時AOF檔案的大小),如果現在AOF大小和上次的比例達到特定值就重寫。也要指定最小AOF大小,防止到2倍:1M的時候也重寫。
aof-load-truncated yes
aof檔案在尾部是不完整的,那redis重啟的時候load進記憶體的時候就會出現問題,如果aof-load-truncated 為yes的時候就會盡量多的將資料load進記憶體中,如果是no的話就必須手動的修復資料,利用redis-check-aof就行資料的修復
lua-time-limit 5000
lua時間時間為毫秒
slowlog-log-slower-than 10000
慢日誌的時間為微秒
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
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
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb60
client-output-buffer-limit pubsub 32mb 8mb60
hz 10
aof-rewrite-incremental-fsync yes
當child程序在rewrite AOF檔案,如果這個選項是yes,那麼這個file每32MB會寫fsync()。這個是保證增量寫硬碟而防止寫硬碟時I/O突增
當redis-server啟動之後可以使用redis-cli info來檢視redis的資訊
redis-sentinel介紹
redis-sentinel實現的是對redis服務進行監控,是想一下加入我們的redis叢集中有三臺機器,mater角色實現的是write以及read的功能。並且slave一般都是read-only的。當master出現意外的情況下,這時候客戶端的write請求就會被拒絕掉,這個顯然是不合理的。所以需要有新的slave重新升級為master。
master的sentinel.conf檔案內容
cat >/etc/redis/sentinel.conf<<EOF
port 26379
dir /tmp
sentinel monitor mymaster 192.168.248.131 6379 2
sentinel down-after-milliseconds mymaster30000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
EOF
redis-sentinel配置詳解
port 26379 監聽的埠
dir /tmp 存放的目錄
sentinel monitor mymaster 192.168.1.2416379 2
監聽的master的名稱(隨意起名字)地址埠號 後面的是2表示的是在叢集中至少有兩個slave同時判斷master失效,master才算失效(object_down)
sentinel down-after-milliseconds mymaster30000
經過多長時間之後如果還不能和master聯絡上之後,就認定master已經down掉,預設的時間是30s
sentinel parallel-syncs mymaster 1
指定在故障轉移的過程中,多少個slave和新的master進行資料的同步如果在,這個數值越小,所需的同步時間越長(一共有n個slave,每次只進行一個的同步當時需要的時間會比較長)當客戶端執行slaveof並進行同步時,會中斷和客戶端的請求,所以如果後面的數字越大,那麼會給客戶端的訪問帶來一定的問題
sentinel failover-timeout mymaster180000
故障切換的過程中slave和新的master同步的超時時間,如果在超時時間內沒有完成,則認為失敗。預設時間為3minutes
note:在進行redis的故障轉移過程中,redis配置檔案會被rewrite為新的slaveof,也就是redis的配置檔案會被重寫
在此redis 主從加上sentinel就已經搭建好了。現在還存在一個問題,如果程式中寫死了寫快取的地址,就是192.168.248.254,但是當masterdown掉之後新的master的地址可能是發生變化的,所以此時我們需要keepalived來實現地址的漂移。
redis-server + redis-sentinel + keepalived
安裝之前先解決掉依賴
yum –y install openssl-devel
tar –zxvf keepalived-1.2.20.tar.gz
cd keepalived-1.2.20
./configure –prefix=/usr/local/keepalived
make
make install
mkdir /etc/keepalived
cd /usr/local/keepalived
cp etc/keepalived/keepalived.conf/etc/keepalived
cp rc.d/init.d/keepalived /etc/init.d
cp sysconfig/keepalived /etc/sysconfig/
cp sbin/keepalived /usr/sbin/
預設keepalived的日誌會存放到/var/log/message中,在此處可以進行自定義
修改/etc/sysconfig/keepalived
KEEPALIVED_OPTIONS="-D -d -S 0"
修改/etc/rsyslog.conf 追加下面的配置
local0.* /var/log/keepalived.log
cat>/etc/keepalived/keepalived.conf<< EOF
! Configuration File for keepalived
global_defs {
notification_email {
}
notification_email_from [email protected]
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id LVS_DEVEL
vrrp_skip_check_adv_addr
vrrp_strict chk_redis {
script "redis-cli info | grep role:master &>/dev/null2>&1"
weight -10
interval 1
timeout 2
rise 1
fall 2
}
}
vrrp_instance VI_1 {
state BACKUP
interface eth1
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.248.254
}
tack_script {
chk_redis
}
}
EOF
其餘的slave節點的配置是相同的,但是需要注意的是通訊的介面是不是都是eth0。
至此,我們就配置好了,當keepalived或者是redis出現問題的時候,就會自動的進行IP地址的漂移。
二、redis+keepalived+twemproxy實現redis高可用
twemproxy是Twitter推出的redis叢集的解決方案
twemproxy特點:
1、 對外暴露一個訪問節點
2、 請求分片
3、 分片要合理(分片均勻,相同的請求分配到同樣的redis節點)
對於和sentinel不同的是,sentinel組成是redis的主從叢集,也就是說當master節點出現問題之後,會有一個新的原來的slave成為master節點,然後slave在向master同步資料。所有的主從節點的資料是一致的。但是twemproxy實現的是一個代理的作用,只對外暴露一個節點地址,client端通過這個地址來進行訪問,代理節點將client的請求分發到後面的redis節點。如果一個節點出現問題,這個節點上面的資料會受到影響。
下面簡單的介紹實現方法
首先下載twemproxy
git clone https://github.com/twitter/twemproxy.git
之後執行autoreconf,這時候有可能會包autoconf的版本比較低,需要更高版本的autoconf,這時候需要去下載更高版本的autoconf,http://ftp.gnu.org/gnu/autoconf/,可以到這個站點去下載,安裝之後
CFLAGS="-ggdb3 -O0" autoreconf -fvi && ./configure --prefix=/usr/local/twemproxy --enable-debug=log
進行安裝,如果報錯的話解決掉相應的依賴即可。
make && makeinstall
安裝好之後
cd /usr/local/twemproxy
mkdir conf
此時編輯配置檔案,不過同樣可以從原來下載的原始碼包將配置檔案的樣例複製過來,檔案為原來twemproxy的conf目錄下,名字叫做nutcracker.yml,複製到安裝目錄的conf目錄下,過來進行如下的編輯
redis:
listen: 0.0.0.0:6379
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
timeout: 400
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 192.168.248.135:6380:1
- 192.168.248.136:6380:1
建立好之後就可以啟動了
/usr/local/twemproxy/sbin/nutcracker-d -c /usr/local/twemproxy/nutcracker.yml
在此處,我們想叢集中添加了兩個redis,並且監聽的埠號為6380,權重全部為1,後面權重代表的是前端對後面兩個分配任務的額度。
為了實現高可用下面搭建keepalived
! Configuration File for keepalived
global_defs {
notification_email {
}
#notification_email_from [email protected]
# smtp_server 192.168.200.1
# smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_script chk_nutcracker {
script "killall -0 nutcracker"
interval 2
weight -4
}
vrrp_instance VI_85 {
state BACKUP
interface eth1
virtual_router_id 85
priority 100
virtual_ro
advert_int 1
authentication {
auth_type PASS
auth_pass 8888
}
virtual_ipaddress {
192.168.248.254
}
track_script {
chk_haproxy
}
}
vrrp_instance VI_86 {
state MASTER
interface eth1
virtual_router_id 86
priority 101
virtual_ro
advert_int 1
authentication {
auth_type PASS
auth_pass 5555
}
virtual_ipaddress {
192.168.248.253
}
track_script {
chk_nutcracker
}
}
兩臺主機分別互相做主從,另外一臺主機做相對應的配置就行。當然如果我們想對keepalived的log進行設定的話,只需要設定/etc/sysconfig/keepalived和/etc/rsyslog.conf就可以了。設定好了之後我們就可以使用VIP來進行redis的處理了。