一、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 < 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 < 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 < 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< 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 keepalived下载的官网地址为http://www.keepalived.org/download.html,可以根据自己的需求来进行下载 安装之前先解决掉依赖 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的处理了。