为上层应用提供高可靠、低延迟、低(无限接近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插入大量数据。
如图所示,有三台主机,分别标识为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 |
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目录比较重要,因此简化安装如下
# http://download.redis.io/redis-stable.tar.gz wget -c http://download.redis.io/releases/redis-3.0.7.tar.gz tar zxf redis-3.0.7.tar.gz cd redis-3.0.7 make cd \cp redis-3.0.7/src/redis-benchmark /usr/local/sbin/ \cp redis-3.0.7/src/redis-check-aof /usr/local/sbin/ \cp redis-3.0.7/src/redis-check-dump /usr/local/sbin/ \cp redis-3.0.7/src/redis-cli /usr/local/sbin/ \cp redis-3.0.7/src/redis-sentinel /usr/local/sbin/ \cp redis-3.0.7/src/redis-server /usr/local/sbin/ mkdir /etc/redis mkdir -p /data/redis-6379/
(3)安装keepalived
# http://www.keepalived.org/documentation.html wget -c http://www.keepalived.org/software/keepalived-1.2.19.tar.gz tar zxf keepalived-1.2.19.tar.gz cd keepalived-1.2.19 ./configure --prefix=/usr/local/keepalived make make install cp /usr/local/keepalived/sbin/keepalived /usr/sbin/ cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/ cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/ mkdir /etc/keepalived
keepalived的配置文件在后面添加
(4)Redis1上的redis-sentinel配置文件
cat >/etc/redis/sentinel.conf<<eof port 26379 dir /tmp sentinel monitor mymaster 192.168.1.241 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 eof
Redis2和Redis3上的redis-sentinel配置文件与Redis1上的redis-sentinel配置文件内容相同。
(5)Redis1上的redis-server的配置文件
cat > /etc/redis/redis-6379.conf <<eof # maxmemory 268435456 maxmemory 256mb daemonize yes pidfile /data/redis-6379/redis-6379.pid port 6379 bind 0.0.0.0 tcp-backlog 511 timeout 0 tcp-keepalive 0 loglevel notice logfile /data/redis-6379/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-6379 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 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes eof
(6)Redis2与Redis3上的redis-server配置文件
cat > /etc/redis/redis-6379.conf <<eof slaveof 192.168.1.241 6379 # maxmemory 268435456 maxmemory 256mb daemonize yes pidfile /data/redis-6379/redis-6379.pid port 6379 bind 0.0.0.0 tcp-backlog 511 timeout 0 tcp-keepalive 0 loglevel notice logfile /data/redis-6379/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-6379 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 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60 hz 10 aof-rewrite-incremental-fsync yes eof
(7)Redis1上的keepalived配置文件(vim /etc/keepalived/keepalived.conf)
关于keepalived的配置文件
keepalived的配置文件默认是没有的,当然sample&example文件还是有的,通常在PREFIX/etc/sample目录下。
keepalived master和backup(backups)之间不同的是:
1.优先级的不同,master的优先级priority的数字要高一些
2.global_defs段的router_id都不一样,实际中可以用任意名字区分也可以用主机名区分
3.backup的配置文件中还有一个nopreempt字段,意思是设置为非抢占模式,作用是让master优先获取到VIP,并保证VIP是在原先的master上。
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 10 router_id keepalivedha_1 } vrrp_script chk_http_port { script "redis-cli info | grep role:master >/dev/null 2>&1" interval 1 timeout 2 fall 2 rise 1 } vrrp_sync_group VG_1 { group { VI_1 } } vrrp_instance VI_1 { state BACKUP interface eth1 #use_vmac keepalived #vmac_xmit_base mcast_src_ip 192.168.1.241 smtp_alert virtual_router_id 20 priority 100 advert_int 1 authentication { auth_type PASS auth_pass password } virtual_ipaddress { 192.168.1.245 } track_script { chk_http_port } }
(8)Redis2上的keepalived配置文件
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 10 router_id keepalivedha_2 } vrrp_script chk_http_port { script "redis-cli info | grep role:master >/dev/null 2>&1" interval 1 timeout 2 fall 2 rise 1 } vrrp_sync_group VG_1 { group { VI_1 } } vrrp_instance VI_1 { state BACKUP interface eth2 #use_vmac keepalived #vmac_xmit_base mcast_src_ip 192.168.1.242 smtp_alert virtual_router_id 20 priority 99 advert_int 1 authentication { auth_type PASS auth_pass password } virtual_ipaddress { 192.168.1.245 } track_script { chk_http_port } nopreempt }
(9)Redis3上的keepalived配置文件
! Configuration File for keepalived global_defs { notification_email { root@localhost } notification_email_from keepalived@localhost smtp_server 127.0.0.1 smtp_connect_timeout 10 router_id keepalivedha_3 } vrrp_script chk_http_port { script "redis-cli info | grep role:master >/dev/null 2>&1" interval 1 timeout 2 fall 2 rise 1 } vrrp_sync_group VG_1 { group { VI_1 } } vrrp_instance VI_1 { state BACKUP interface eth1 #use_vmac keepalived #vmac_xmit_base mcast_src_ip 192.168.1.243 smtp_alert virtual_router_id 20 priority 98 advert_int 1 authentication { auth_type PASS auth_pass password } virtual_ipaddress { 192.168.1.245 } track_script { chk_http_port } nopreempt }
(10)启动redis-server
redis-server /etc/redis/redis-6379.conf tail /data/redis-6379/redis.log
(11)启动redis-sentinel
redis-sentinel /etc/redis/redis-sentinel.conf tail /data/redis-6379/redis-sentinel.log
(12)启动keepalived
service keepalived start tail /var/log/messages
如果keepalived启动后日志如下图显示则表示启动成功。
测试分两块内容,一是测试键值对的set与get,二是测试自增唯一id的是否可用。
(1)测试Redis键值对的set与get
先不模拟故障,先测试一下redis的set、get和复制情况
再测试一下模拟故障出现时redis的set、get和复制情况
停掉Redis1上的redis-server
Redis1上的VIP已经被移除
查看Redis2上的Redis状态和VIP状态
通过上图的***文字可以看出,VIP已经漂移到新的redis-server master了。
注意:VIP的漂移过程是需要时间的,时间大概需要10*4ms左右,如下图所示:
此时再次测试一下Redis的复制情况
由上图可见,Redis复制情况正常,上层应用依然可以使用Redis缓存服务。
(2)测试自增唯一id(autoincrementing unique identifier)
概念参考:http://redis-cookbook.readthedocs.org/en/latest/z.html
自增唯一id最常见的应用就是作为关系型数据库的主键,因为主键必须确保每个数据项都有唯一id。
它也可以在不支持自增唯一id的数据库中(比如MongoDB)用来替代唯一id(uniqueidentifier,通常是一个哈希值)
它也可以为用户提供更好的URL:比如将/topic/4e491e229f328b0cd900010d修改为/topic/10086。
一个自增唯一id对象最重要的是保证值的唯一性,要做到这一点,自增id的自增incr操作必须是一个原子操作,它应该能在一个原子时间内完成以下两件事:
增加id值,返回当前id值,并且它也没有减法decr和清零reset等操作,因为这些操作破坏了唯一性。
get操作一般只用于内部检查,比如观察值是否溢出,但在一般情况下,自增唯一id对象应该只有一个incr操作。
先测试一下主机健康状态下的自增唯一id
发现各个redis-server中的自增唯一id是好用的。再测试一下某台主机故障状态下的自增唯一id。先根据ip addr找到VIP的主机位置,或者通过redis-cli info查看role找到redis-server master的主机,然后kill redis-server pid,再进行测试。
由此发现redis-server中的自增唯一id仍然是好用的。
如果一台主机宕机,则主机启动后,先启动redis-server、再启动redis-sentinel、最后自动keepalived。
如果多台主机宕机,则按照一台主机宕机的步骤做同样处理。
如果一台主机的中的某台服务停止,则直接启动该服务即可。
Redis Documention http://redis.io/documentation
Redis High Availability http://redis.io/topics/sentinel
Redis Replication http://redis.io/topics/replication
tag:Redis集群,Redis高可用,redis-sentinel,keepalived配置,Redis主从复制
--end--