前言: 要理解Redis大规模集群的由来,就必然跨不过理解哨兵和主从复制的由来以及存在的缺陷,不管谁学习这几个知识点都逃不过这个顺序…

redis分片集群多读读写延迟 redis集群读写分离原理_redis集群


 

一、主从复制 + 读写分离

现在的公司项目如果有Redis那么一定是集群的,再差再差也会有三台主从复制的机器来保证Redis的可用性。就算内存有256G也不能全部作为Redis存储内存,单台Redis最大使用内存不应该超过20G主从复制作用】

注:Redis哨兵管理的主从复制最低配置 —— (奇数个)三个哨兵 + 一拖二(至少三个)的主从模式,具体详情见下文分析

  • 数据冗余 —— 相当于从机多了一些数据的热备份数据
  • 故障恢复 —— 主节点宕机可由从节点顶替,并快速故障恢复
  • 负载均衡 —— 读写分离能支持高并发
  • 高可用(一般谈到高可用都是集群) —— 主从复制实现哨兵和集群的基础

主从复制、读写分离 - 配置关注点:

注意:我们只需要关注修改要配置的从节点即可,因为每台Redis默认自己为主节点。

# 主从复制. 设置该数据库为其他数据库的从数据库.
# 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
# 这里永久性的设置主机IP(设置后自己视为奴隶) —— 比如 slaveof 127.0.0.1 6379
# slaveof <masterip> <masterport>
 
# 当master服务设置了密码保护时(用requirepass制定的密码)
# slav服务连接master的密码
#
# masterauth <master-password>
 
 
# 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:
#
# 1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求
#
# 2) 如果slave-serve-stale-data是指为no,出去INFO和SLAVOF命令之外的任何请求都会返回一个
#    错误"SYNC with master in progress"
# [stale/steɪl/ - 陈旧的]
slave-serve-stale-data yes
 
# 从库会按照一个时间间隔向主库发送PINGs.可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒
#
# repl-ping-slave-period 10
# 总结就是上面间隔多少秒发送一次检测存活的pingPong信号,下面就是判定发送这个信号后的返回超时时间 
# repl-timeout 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒
# 一定要确保repl-timeout大于repl-ping-slave-period
# repl-timeout 60

启动服务命令: redis-server redis.conf

配置完后,我们可以通过 —— info replication 命令查看当前Redis的主从配置信息。

举例 从节点 Redis可以看到的信息应该和下面类似:

# 调用命令
127.0.0.1:6380> info replication

# 指明当前角色是从机 
role:slave
# 下面涵盖了主机、从机的各种信息
master_host:127.0.0.1	
master_port:6379
master_link_status:up 
master_last_io_seconds_ago:3 
master_sync_in_progress:0 
slave_repl_offset:14 
slave_priority:100 
slave_read_only:1 
connected_slaves:0
master_replid:a81be8dd257636b2d3e7a9f595e69d73ff03774e master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14 
second_repl_offset:-1 
repl_backlog_active:1 
repl_backlog_size:1048576 
repl_backlog_first_byte_offset:1 
repl_backlog_histlen:14

举例 主节点 Redis可以看到的信息应该和下面类似:

# 调用命令
127.0.0.1:6379> info replication
# 标明当下连接几台从机等从机信息...
connected_slaves:1	
slave0:ip=127.0.0.1,port=6380,state=online,offset=42,lag=1	
master_replid:a81be8dd257636b2d3e7a9f595e69d73ff03774e master_replid2:0000000000000000000000000000000000000000
master_repl_offset:42 
second_repl_offset:-1 
repl_backlog_active:1 
repl_backlog_size:1048576 
repl_backlog_first_byte_offset:1
repl_backlog_histlen:42

至此我们就完成了主从复制的配置,主从配置后具备读写分离机制 —— 只有主能写,从只能读(如果尝试从写会返回错误信息)

二、配置哨兵 —— 管理主从节点

如果仔细思考,能发现主从复制是有问题的。也就是如果主挂了,那么整个Redis就失去了写的操作。这个时候我们就需要有一个机制来解决这种异常现象,那就是配置哨兵来管理集群 —— 哨兵会在主宕机后进行两个操作(为了保证高可用,哨兵也会实现集群,所以这两部操作需也要集群中的哨兵一起做决策,这个我后面有一篇会细讲原理) 1.判定是否真正宕机 2.选举一个从节点做为新的主节点(选举成功后,就算老主节点修复上线,照样无法顶替现存的主节点)

—— 哨兵管理的目的是为了自动化解决主从复制可能产生的宕机问题,解决机器停滞风险,解放人工维护成本。

注: 配置好哨兵管理后, 宕掉的主机如果重新复活连接会自动变为新主机的从机
 

哨配置关注点 (sentinel.conf文件)

# 当前哨兵的端口号(哨兵集群可以修改这里的端口号,重点是关注的同一个主机就能实现了)
port 8006

# 当前哨兵的运行模式
daemonize yes

# 当前哨兵的工作目录
dir /tmp

# 当前哨兵的日志文件名
logfile "8006.log"

#  sentinel monitor <master-name> <ip> <redis-port> <quorum>
#  <ip> 哨兵sentinel所要监控的redis主节点的ip
#  <redis-port> 哨兵sentinel所要监控的redis主节点的端口号
#  <master-name>  可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
#  <quorum> 当这些quorum个数的哨兵认为master主节点失联,客观层面认为这个节点是真的失联(宕机)了
sentinel monitor mymaster 127.0.0.1 8002 2

# 设置哨兵sentinel 连接主从的密码,注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 8002

# 判断数据节点和sentinel节点多少(毫秒)数内没有响应哨兵发出的ping,则主观认为该节点失联
#(具体是否真正失联还要根据上面配置的<quorum>个哨兵集体认定来判断)
sentinel down-after-milliseconds mymaster 30000

# 主节点下线后,从节点向新的主节点发起复制的个数限制(指的一次同时允许几个从节点)。
sentinel parallel-syncs mymaster 1

# 故障转移(failover)超时时间(毫秒),默认三分钟
# 若哨兵在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败
sentinel failover-timeout mymaster 180000

# SCRIPTS EXECUTION

#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知 相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。

#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等), 将会去调用这个脚本,这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信 息。调用该脚本时,将传给脚本两个参数,一个是事件的类型,一个是事件的描述。如果sentinel.conf配 置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无 法正常启动成功。
#通知脚本
# 需要shell编程
# sentinel notification-script <master-name> <script-path> 
sentinel notification-script mymaster /var/redis/notify.sh

# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已 经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通 信的
#  这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh # 一般都是由运维来配 置!

启动哨兵命令: redis-sentinel sentinel.conf
 
 

哨兵工作原理


上面已经分析完了主从复制和哨兵管理的配置,接下简要来讲一下哨兵工作的原理,主要是三部分:监控、通知、故障转移。如果想知道更加具体细节的部分,我把在网上看到的一篇图文并茂讲的比较

  1. 监控:
  • 所有的哨兵都会做一个事,那就是 —— 向主节点所有从节点,以及其他哨兵发送消息来获取他们的信息并保存到自身。
  1. 通知:
  • 哨兵与哨兵之间会建立发布订阅模式,来确保哨兵的存活,然后哨兵各自会向主节点发送信号来监控主节点是否存活,如果超过一定时间(我们在配置文件里设定的时间)主节点没有回应,就会主观认为这个主节点挂了。这个时候就会在哨兵之间的内网发布一个sentinel is-master-down-by-address-port消息,然后其他哨兵也会对这个主节点去发送信号,如果超过半数的哨兵同样得不到回应,那么就会客观上认为这个主节点真正挂了,这个时候就会开始故障转移(failOver)机制,从节点中选举出一个主节点。
  1. 通知:
  • 选举只能一个哨兵选啊,不然一起选就乱套了。 所以选主节点之前,哨兵内网还会有一套机制(每台哨兵一票,有专门的机制,反正也是得票过半数定选)选举出一个代表哨兵,作为主节点的选择对象。
  • 代表哨兵去就会去从节点选一台主节点来完成故障转移(大概就是先找到所有还活着的节点,然后从这些节点中选出反应最快的,然后根据节点产生时间等来选择一个相对最优的节点作为主节点)。
     

那么这里说完了哨兵管理主从复制,说到底主从复制其实就是做到了一台Redis的高可用集群,三台机数据都是一样的,同时也相当于做了一个数据备份(实质上只有一台机器的数据) —— 那么仔细思考,如果海量数据量超过了这台机器的容量呢?