Redis主备+哨兵

        虽然Redis有持久化功能保障Redis服务器宕机也能恢复并且只有少量数据损失,但由于所有数据都在一台服务器上,如果服务器出现硬盘故障,那就算有备份也不能避免数据丢失的问题。而且在实际生产环境中,我们不能只使用一台Redis服务器作为缓存服务器,必须要多台服务器, 避免单点故障。
主从复制
        
        复制的作用是把Redis的数据复制多个副本部署在不同的服务器上,如果其中一台服务器出现故障,也能快速迁移到其他服务器上提供服务。主从复制就是我们常见的master/slave模式,主服务器可以进行读写操作,当写操作导致数据发生变化时会自动将数据同步给从服务器。从数据库是只读的,并接收主服务器同步过来的数据。一个主服务器可以有多个从服务器。
配置实现
        为Redis配置master/slave模式是非常容易的, 只要在从服务器的配置文件中加入 slaveof 主服务器地址端口,而master服务器不需要任何改变。
步骤:
1.准备两台服务器server1(主)、server2(从),分别安装Redis;
2.在server2的redis.conf文件中增加slaveof server1-ip 6379,同时将bindip注释掉,允许所有IP访问;
3.启动server2,访问server2的redis客户端,输入"INFO replication”查看主从信息;
4. 通过在master机器上输入命令,比如"set foo bar"、 在slave服务器就能看到该值已经同步过来了;
原理
  • 全量复制
Redis全量复制一般发生在slave初始化阶段,这时slave需要将master上的所有数据都复制一份。具体步骤:
1.从服务器连接主服务器,并发送SYNC命令;
2.主服务器接收到命令后执行BGSAVE生成快照,并记录生成快照期间的写命令;
3.主服务器将生成的快照文件发送给从服务器;
4.从服务器载入快照文件;
5.主服务器将缓存的写命令发送给从服务器;
6.从服务器执行主服务器发送过来的缓存的写命令;
流程图如下:
完成上面几个步骤后就完成了slave服务器数据初始化的所有操作,slave服务器此时可以接收来自用户的读请求。
        master/slave 复制策略是采用乐观复制(最终一致性),也就是说可以容忍短时间内master/slave数据的内容是不一致的,但是两者的数据会最终同步。具体来说,redis的 主从同步过程本身是异步的,意味着master执行完客户端请求的命令后会立即返回结果给客户端,然后异步的方式把命令同步给slave。这一特征保证启用master/slave后master的性能不会受到影响。但另一方面,如果在这个数据不一致的窗口期间,master/slave因为网络问题断开连接,而这个时候,master是无法得知某个命令最终同步给了多少个slave数据库。不过redis提供了一个配置项来限制只有数据至少同步给多少个slave的时候,master才是可写的:
min-slaves-to-write 3    //表示只有当3个或以上的slave连接到master,master才是可写的;
min-slaves-max-lag 10    //表示允许slave最长失去连接的时间,如果10秒还没收到slave的响应,则master认为该slave已断开;
  • 增量 复制
        从redis 2.8开始,就 支持主从复制的断点续传。如果主从复制过程中网络连接断掉了,可以接着上次复制的地方继续复制下去,而不是从头开始复制一份。master node会在内存中创建一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制,但是如果没有找到对应的offset,那么就会执行一次全量同步。
  • 无硬盘复制
        前面说过,Redis复制的工作原理基于RDB方式的持久化实现的,也就是master在后台保存RDB快照,slave接收到rdb文件并载入,但是这种方式会存在一些问题。
1.当master禁用RDB时,如果执行了复制初始化操作,Redis依然会生成RDB快照,当master下次启动时执行该RDB文件的恢复,但是因为复制发生的时间点不确定,所以恢复的数据可能是任何时间点的,就会造成数据出现问题;
2.当硬盘性能比较慢的情况下(网络硬盘),那初始化复制过程会对性能产生影响;
因此Redis2.8.18以后的版本引入了无硬盘复制选项,可以不需要通过RDB文件去同步,直接发送数据,通过以下配置来开启该功能:
repl-diskless-sync yes
master在内存中直接创建RDB,然后发送给slave,不会在本地落地磁盘了。
说明:
    当需要在一台服务器上搭建伪集群时,可以将配置文件复制多个副本,每个副本为每个节点的配置文件,然后通过指定配置文件的方式启动服务端(配置文件内设置已守护进程方式运行)。例如Mac通过HomeBrew方式安装的Redis,安装后会自动配置环境变量(可以直接通过redis-server命令启动服务端)。可以找到安装Redis时创建的plist文件,通过plist文件可以看到redis.conf配置文件的位置,将该文件复制多份到指定位置,并修改各个节点的配置文件,然后通过redis-server ${redis.conf}命令启动各个节点。
哨兵机制
        在典型的一主多从的master/slave模式系统中, slave在整个体系中起到了数据冗余备份和读写分离的作用。当master遇到异常中断后,需要从slave中选举一个新的master继续对外提供服务。比如在zk中通过leader选举、kafka中可以基于zk的节点实现master选举。所以在redis中也需要一种机制去实现master的决策,redis并没有提供自动master选举功能,而是需要借助一个哨兵来进行监控。 哨兵的作用就是监控Redis系统的运行状况,它的功能包括两个:
1. 监控master和slave是否正常运行;
2. master出现故障时自动将slave数据库升级为master;
哨兵是一个独立的进程,使用哨兵后的架构图:
        为了解决master选举问题,又引出了一个单点问题,也就是哨兵的可用性如何解决,在一个一主多从的Redis系统中,可以使用多个哨兵进行监控任务以保证系统足够稳定。此时 哨兵不仅会监控master和slave,同时还会互相监控;这种方式称为哨兵集群,哨兵集群需要解决故障发现和master决策的协商机制问题。
sentinel之间相互感知
        sentinel节点之间会因为共同监视同一个master从而产生关联,一个新加入的sentinel节点需要和其他监视相同master节点的sentinel相互感知。
感知过程:
1. 需要相互感知的sentinel都向他们共同监视的master节点订阅channel:sentinel:hello。
2. 新加入的sentinel节点向这个channel发布一条消息,包含自己本身的信息,这样订阅了这个channel的sentinel就可以发现这个新的sentinel。
3. 新加入得sentinel和其他sentinel节点建立长连接。
sentinel感知原理图:
master的故障发现
        sentinel节点会 定期向master节点发送心跳包来判断存活状态,一旦master节点没有正确响应,sentinel会把master设置为“主观不可用状态”,然后它会把“主观不可用”发送给其他所有的sentinel节点去确认,当确认的sentinel节点数大于 quorum时,则会认为master是“客观不可用”,接着就开始进入选举新的master流程;但是这里又会遇到一个问题,就是sentinel中,本身是一个集群,如果多个节点同时发现master节点达到客观不可用状态,那谁来决策选择哪个节点作为maste呢?这个时候就需要从sentinel集群中选择一个leader来做决策。而这里用到了一致性算法Raft算法,它和Paxos算法类似,都是分布式一致性算法。但是它比Paxos算法要更容易理解; Raft和Paxos算法一样,也是基于投票算法,只要保证过半数节点通过提议即可;(Raft算法流程动画演示地址: http://thesecretlivesofdata.com/raft/)
配置实现
通过在这个配置的基础上增加哨兵机制。在其中任意一台服务器或多台服务器上创建一个sentinel.conf文件,文件内容:
port <port>
//当前Sentinel服务运行的端口;
logfile <logfile-full-path>
//日志文件位置
daemonize yes
//添加为后台运行 
dir <dir>
//Sentinel服务运行时使用的临时文件夹;
sentinel monitor <master-name> <ip> <port> <quorum>
//指定redis的master节点名称(自定义)、地址、端口、客观认定数量;quorum表示需要几个哨兵节点确认才可将master的状态从“主观不可用”变为“客观不可用”;
sentinel auth-pass <master-name> <password>
//设置连接master和slave时的密码,注意的是sentinel不能分别为master和slave设置不同的密码,因此master和slave的密码应该设置相同,如果没有密码可以不设置该配置项;
sentinel down-after-milliseconds <master-name> <time>
//Sentinel认为Redis实例已经失效所需的毫秒数;
sentinel failover-timeout <master-name> <time>
//表示如果在该时间(ms)后,master仍没活过来,则启动failover,从剩下的slave中选一个升级为master;
两种方式启动哨兵
redis-sentinel sentinel.conf
redis-server /path/to/sentinel.conf --sentinel
哨兵监控一个系统时, 只需要配置监控master即可,哨兵会自动发现所有slave;这时候,我们把master关闭,等待指定时间后(默认是30秒),会自动进行切换,会输出如下消息:
coderX@macbook-pro:~$ redis-sentinel s1.conf
9127:X 22 Aug 23:27:50.999 # You requested maxclients of 10000 requiring at least 10032 max file descriptors.
9127:X 22 Aug 23:27:50.999 # Server can't set maximum open files to 10032 because of OS error: Operation not permitted.
9127:X 22 Aug 23:27:50.999 # Current maximum open files is 4096. maxclients has been reduced to 4064 to compensate for low ulimit. If you need higher maxclients increase 'ulimit -n'.
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 3.2.1 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
(    '      ,       .-`  | `,    )     Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'|     Port: 26379
|    `-._   `._    /     _.-'    |     PID: 9127
  `-._    `-._  `-./  _.-'    _.-'                                   
|`-._`-._    `-.__.-'    _.-'_.-'|                                  
|    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
|`-._`-._    `-.__.-'    _.-'_.-'|                                  
|    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               
9127:X 22 Aug 23:27:51.000 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
9127:X 22 Aug 23:27:51.003 # Sentinel ID is 26f43074868559a81927040f04d8afd6be4d7d2b
9127:X 22 Aug 23:27:51.003 # +monitor master mymaster 192.168.92.136 6379 quorum 1
9127:X 22 Aug 23:27:51.004 * +slave slave 192.168.98.136:6380 192.168.92.136 6380 @ mymaster 192.168.98.136 6379
9127:X 22 Aug 23:27:51.005 * +slave slave 192.168.98.136:6381 192.168.92.136 6381 @ mymaster 192.168.98.136 6379
9127:X 22 Aug 23:27:59.017 * +sentinel sentinel 73d21ad0584a4ce628c9aa5cc0653eda169b9080 192.168.98.136 26380 @ mymaster 192.168.98.136 6379
9127:X 22 Aug 23:28:18.366 # +new-epoch 1
9127:X 22 Aug 23:28:18.367 # +vote-for-leader 73d21ad0584a4ce628c9aa5cc0653eda169b9080 1
9127:X 22 Aug 23:28:18.417 # +sdown master mymaster 192.168.98.136 6379
9127:X 22 Aug 23:28:18.417 # +odown master mymaster 192.168.98.136 6379 #quorum 1/1
9127:X 22 Aug 23:28:18.417 # Next failover delay: I will not start a failover before Mon Aug 22 23:30:58 2016
9127:X 22 Aug 23:28:19.465 # +config-update-from sentinel 73d21ad0584a4ce628c9aa5cc0653eda169b9080 192.168.98.136 26380 @ mymaster 192.168.98.136 6379
9127:X 22 Aug 23:28:19.465 # +switch-master mymaster 192.168.92.136 6379 192.168.92.136 6381
9127:X 22 Aug 23:28:19.465 * +slave slave 192.168.92.136:6380 192.168.98.136 6380 @ mymaster 192.168.98.136 6381
9127:X 22 Aug 23:28:19.465 * +slave slave 192.168.92.136:6379 192.168.98.136 6379 @ mymaster 192.168.98.136 6381
说明:
+sdown表示哨兵主观认为master已经停止服务了;
+odown表示哨兵客观认为master停止服务了。接着哨兵开始进行故障恢复,挑选一个slave升级为master;
+try-failover表示哨兵开始进行故障恢复;
+failover-end 表示哨兵完成故障恢复;
+slave表示列出新的master和slave服务器,我们仍然可以看到已经停掉的master,哨兵并没有清除已停止的服务的实例,这是因为已经停止的服务器有可能会在某个时间进行恢复,恢复以后会以slave角色加入到整个集群中;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值