Redis开发运维实践高可用和集群架构与实践(一)

11.1 主从复制-sentinel架构

11.1.1 高可用原理

11.1.1.1 发现原理

Sentinel发现分为发现从服务器和发现其他sentinel服务两类:

  • Sentinel实例可以通过询问主实例来获得所有从实例的信息
  • Sentinel进程可以通过发布与订阅来自动发现正在监视相同主实例的其他Sentinel,每个 Sentinel 都订阅了被它监视的所有主服务器和从服务器的 __sentinel__:hello 频道, 查找之前未出现过的 sentinel进程。 当一个 Sentinel 发现一个新的 Sentinel 时,它会将新的 Sentinel 添加到一个列表中,这个列表保存了 Sentinel 已知的,监视同一个主服务器的所有其他Sentinel。

注:文中的横杠要替换为下滑线,markdown不太能显示出来...

11.1.1.2 基本切换原理

在切换中,配置文件是会被动态修改的,例如当发生主备切换时候,配置文件中的master会被修改为另外一个slave。这样,之后sentinel如果重启时,就可以根据这个配置来恢复其之前所监控的redis集群的状态。 在sentinel切换过程中有三大步骤:

  1. 判断是否下线(老主是否真的咽气驾崩) 每个sentinel在监控的时候,每秒对主进行一次ping命令,如果多次ping的响应时间超过了配置文件中的down-after-milliseconds,那么这个哨兵就会认为被监控的实例是SDown状态(Subjectively Down,主观down,SDOWN)。 这个时候此sentinel会判断此master是否真的挂了——即可以设置成ODOWN(Objectively Down,客观down,ODOWN)。设置成ODOWN的条件是除了当前sentinel认为此master SDOWN,还必须有其他sentinel认为此master SDOWN,当认为SDOWN的sentinel的个数等于或超过配置文件中monitor master最后的那个参数quorum后,就sentinel就会认为此master是ODOWN。 被标记为ODOWN的另一个效应是:在一般情况下,每个 Sentinel 进程会以每 10 秒一次的频率向它已知的所有主实例和从实例发送 INFO 命令。 当一个主实例被 Sentinel实例标记为客观下线时, Sentinel 向ODOWN Master的所有从实例发送 INFO 命令的频率会从 10 秒一次改为每秒一次。
  2. 进行投票选举主持切换的sentinel(选举一个长老,由它来钦点新帝王) 当master被认为是ODOWN的时候,可能需要进行failover,但是并不是odown了就可以执行failover,因为可能有多个sentinel都认为master是odown了,这时候就需要选举一个sentiel来执行failover。也就是说切换之前要先选举一个sentinel来主持切换,条件是必须有>=max(quorum, num(sentinels)/2 +1)的sentinel都同意某一个sentinel主持failover,那么这个sentinel就可以主持failover,超过半数这个条件就能限制住此时刻只有一个sentinel来操作。 这个也是通过is-master-down-by-addr消息进行更新每个sentinel的选举的leader。每个sentinel都有一个epoch,这个东西相当于一个时间戳,是递增的值,如果集群正常的话,所有的sentinel的这个值都是一样的。当master出现异常后,每个sentinel后自增这个值,如果一直没有选举出来leader的话,这个值会跟随这time event的轮询,每次加一,在设定的故障迁移超时时间的两倍之后, 重新尝试当选。同时is-master-down-by-addr会把这个值发送到其他的sentinel,其他的sentinel收到这个消息后,会判断自己的epoch和消息中的epoch,如果自己的epoch小于消息中的epoch,那么其他的sentinel就会选举传递消息的这个sentinel。最终会大部分sentinel都同意一个较大的epoch的sentinel主持failover。
  3. 进行切换,并其他实例同步新Master(新帝王登基,其余藩王宣誓效忠新帝王) 这个主持切换的sentinel选出一个从redis实例,并将它升级为Master。首先是要下面的条件按照如下条件筛选备选node: 1) slave节点状态处于S_DOWN,O_DOWN,DISCONNECTED的除外 2) 最近一次ping应答时间不超过5倍ping的间隔(假如ping的间隔为1秒,则最近一次应答延迟不应超过5秒,redis sentinel默认为1秒) 3) info_refresh应答不超过3倍info_refresh的间隔(原理同2,redis sentinel默认为10秒) 4) slave节点与master节点失去联系的时间不能超过( (now - master->s_down_since_time) + (master->down_after_period * 10))。总体意思是说,slave节点与master同步太不及时的(比如新启动的节点),不应该参与被选举。 5) Slave priority不等于0(这个是在配置文件中指定,默认配置为100)。

然后再从备选node中,按照如下顺序选择新的master 1) 较低的slave_priority(这个是在配置文件中指定,默认配置为100) 2) 较大的replication offset(每个slave在与master同步后offset自动增加) 3) 较小的runid(每个redis实例,都会有一个runid,通常是一个40位的随机字符串,在redis启动时设置,重复概率非常小) 4) 如果以上条件都不足以区别出唯一的节点,则会看哪个slave节点处理之前master发送的command多,就选谁。 主持切换的sentinel向被选中的从redis实例发送 SLAVEOF NO ONE 命令,让它转变为Master。然后通过发布与订阅功能,将更新后的配置传播给所有其他 Sentinel,其他 Sentinel 对它们自己的配置进行config-rewrite。随后sentinel向已下线的Master的从服务器发送SLAVEOF命令,让它们去复制新Master。

注意:sentinel failover-timeout这个选项有四个含义,有必要在此翻译一下 1) 对于一个sentinel选出的同一个master进行再次的failover尝试所需要的时间——这个参数值的两倍。 2) 当sentinel发现一个slave错误的复制了一个错的主时sentinel会强迫其复制正确的主的时间。 3) 取消一个已经开始但是还没有引起任何配置改变的failover所需要的时间。 4) 等待所有slave被重新配置为新主的slave而所需要的最大时间。注意即使超过了这个时间sentinel也会最终配置slave去同步最新的master

时间: 2024-11-01 18:28:11

Redis开发运维实践高可用和集群架构与实践(一)的相关文章

Redis开发运维实践高可用和集群架构与实践(四)

11.1.4 高可用和异常测试 11.1.4.1 测试环境介绍 sentinel的消息可以通过sentinel日志(/redis/log/sentinel.log)以及sentinel:hello订阅此频道进行查看. 11.1.4.2 手动切换测试 集群情况,2.128为主 发起主动切换: 查看sentinel日志: 在2.129上看,集群已经切换过来: 11.1.4.3 主实例宕测试 接上,此时master为2.129,找出redis实例的pid,然后kill: 此时查看sentinel日志:

Redis开发运维实践高可用和集群架构与实践(二)

11.1.2 环境搭建 11.1.2.1 部署架构 部署架构上采用三台机器,一个Master接受写请求,两个Slave进行数据同步,三台机器上都部署sentinel(一般为奇数个,因为需要绝大部分进行投票才能failover).(官方示例)具体架构如下图: 注意:如果有条件可以将sentinel多部署几个在客户端所在的应用服务器上,而不是与从节点部署在一起,这样避免整机宕机后sentinel和slave都减少而导致的切换选举sentinel无法超过半数. 11.1.2.2 网络规划 redis高

Redis开发运维实践高可用和集群架构与实践(三)

11.1.3 维护操作 11.1.3.1 完整启动 supervisord -c /redis/conf/redis-supervisord.conf 会自动拉起本机的redis和sentinel 11.1.3.2 启停redis supervisorctl -c /redis/conf/redis-supervisord.conf start redis supervisorctl -c /redis/conf/redis-supervisord.conf stop redis supervi

Redis开发运维实践高可用和集群架构与实践(五)

11.1.5 其他问题 11.1.5.1 只读性 主从复制架构下,默认Slave是只读的,如果写入则会报错: 127.0.0.1:6379> set foo bar (error) READONLY You can't write against a read only slave. 注意这个行为是可以修改的,虽然这样的修改没有意义: 127.0.0.1:6379> CONFIG SET slave-read-only no OK 127.0.0.1:6379> set foo bar

Redis开发运维实践开发者设计规范之典型使用场景参考

4.6 典型使用场景参考 下面是Redis适用的一些场景: 1. 取最新 N 个数据的操作 比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的 5000条评论的ID放在Redis的List集合中,并将超出集合部分从数据库获取. 使用LPUSH latest.comments命令,向 list集合中插入数据 插入完成后再用 LTRIM latest.comments 0 5000 命令使其永远只保存最近5000个 ID 然后我们在客户端获取某一页评论时可以用下面的逻辑 FUNCTION

Redis开发运维实践上线部署规划之内存规划

5.1 内存.CPU规划 一定要设置最大内存maxmemory参数,否则物理内存用爆了就会大量使用Swap,写RDB文件时的速度很慢.注意这个参数指的是info中的used_memory,在一些不利于jmalloc的时候,内存碎片会很大. 多留55%内存是最安全的.重写AOF文件和RDB文件的进程(即使不做持久化,复制到Slave的时候也要写RDB)会fork出一条新进程来,采用了操作系统的Copy-On-Write策略(子进程与父进程共享Page.如果父进程的Page-每页4K有修改,父进程自

Redis开发运维实践上线部署规划之服务器部署位置

5.3 服务器部署位置 尽可能把client和server部署在同一台机器上,比如都部署在app server,或者一个网段中,减少网络延迟对于redis的影响. 如果是同一台机器,又想榨干redis性能可以考虑采用UNIX domain sockets配置方式,配置方式如下 这样的配置方式在没有大量pipeline下会有一定性能提升,具体请参见http://redis.io/topics/benchmarks: 另外,对于混合部署即redis和应用部署在同一台服务器上,那么可能会出现如下的情况

Redis开发运维实践开发者设计规范之延迟考虑

4.5 延迟考虑 1. 尽可能使用批量操作: mget.hmget而不是get和hget,对于set也是如此. lpush向一个list一次性导入多个元素,而不用lset一个个添加 LRANGE 一次取出一个范围的元素,也不用LINDEX一个个取出 2. 尽可能的把redis和APP SERVER部署在一个网段甚至一台机器. 3. 对于数据量较大的集合,不要轻易进行删除操作,这样会阻塞服务器,一般采用重命名+批量删除的策略: 排序集合: # Rename the key newkey = "gc

Redis开发运维实践上线部署规划之网卡rps设置

5.2 网卡RPS设置 RPS就是让网卡使用多核CPU的.传统方法就是网卡多队列(RSS,需要硬件和驱动支持),RPS则是在系统层实现了分发和均衡.如果对redis网络处理能力要求高或者在生产上发现cpu0的,可以在OS层面打开这个内核功能. 设置脚本: #!/bin/bash # Enable RPS (Receive Packet Steering) rfc=32768 cc=$(grep -c processor /proc/cpuinfo) rsfe=$(echo $cc*$rfc |