Redis主从复制
-
主从复制流程
- 从数据库向主数据库发送sync命令。
- 主数据库接收sync命令后,执行BGSAVE命令(保存快照),创建一个RDB文件,在创建RDB文件期间的命令将保存在缓冲区中。
- 当主数据库执行完BGSAVE时,会向从数据库发送RDB文件,而从数据库会接收并载入该文件。
- 主数据库将缓冲区的所有写命令发给从服务器执行。
- 以上处理完之后,之后主数据库每执行一个写命令,都会将被执行的写命令发送给从数据库。
时间 | 主服务器 | 从服务器 |
---|---|---|
T1 | 服务器启动 | 服务器启动 |
T2 | 执行 SET k1 v1 | |
T3 | 执行 SET k2 v2 | |
T4 | 接收到客户端发送的SLAVEOF命令,向主服务器发送SYNC命令 | |
T5 | 接收到从服务器发来的SYNC命令,执行BGSAVE命令,创建包含k1、k2的RDB文件,并使用缓冲区记录接下来执行的所有写命令 | |
T6 | 执行 SET k3 v3,并将此条命令保存在缓冲区中 | |
T7 | 执行 SET k3 v3,并将此条命令保存在缓冲区中 | |
T8 | BGSAVE命令执行完毕,想从服务器发送RDB文件 | |
T9 | 接收并载入主服务器发来的RDB文件,读取到k1、k2 | |
T10 | 向从服务器发送缓冲区中的保存的写命令 SET k3 v3、SET k4 v4 | |
T11 | 接受并执行由主服务器发来的SET命令,读取到k3、k4 | |
T12 | 同步完成,现在主从服务器状态保持一致 | 同步完成,现在主从服务器状态保持一致 |
-
主从复制配置
################################# REPLICATION #################################
masterauth linux #主节点密码
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 #启用tcp-nodelay,以减小延迟,启用则会减小带宽占用
repl-backlog-size 1mb #复制缓冲区大小,仅在至少有一个从节点在线时启用
repl-backlog-ttl 3600 #复制缓冲区保留时间
slave-priority 100 #从节点优先级,数字越大优先级越高
min-slaves-to-write 3 #从节点至少为多少个
min-slaves-max-lag 10 #主从之间的最大延迟
slave-announce-ip 5.5.5.5 #从节点请求发送IP
slave-announce-port 1234 #从节点请求发送端口
启动主从 Redis 服务,在主节点上使用 INFO replication 或者 CLIENT LIST 命令查看从服务器状态
127.0.0.1:6379> INFO replication
# Replication
role:master
connected_slaves:1
slave0:ip=192.168.30.174,port=6379,state=online,offset=239,lag=0
master_repl_offset:239
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:238
# 主节点 从节点
127.0.0.1:6379> KEYS * 127.0.0.1:6379> KEYS *
1) "Linux" 1) "first_hash"
2) "first_key" 2) "OS"
3) "second_list" 3) "count"
4) "first_hash" 4) "second_list"
5) "count" 5) "first_list"
6) "OS" 6) "first_key"
7) "NewOS" 7) "NewOS"
8) "first_list" 8) "Linux"
Redis-Sentinel
Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-slave的高可用方案时,假如master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel本身也是一个独立运行的进程,它能监控多个master-slave集群,发现master宕机后能进行自动切换。
- 不时地监控redis是否按照预期良好地运行
- 如果发现某个redis节点运行出现状况,能够通知另外一个进程(例如它的客户端)
- 能够进行自动切换。当一个master节点不可用时,能够选举出master的多个slave(如果有超过一个slave的话)中的一个来作为新的master,其它的 slave 节点会将它所追随的 master 的地址改为被提升为 master 的 slave 的新地址
当然,sentinel 也面临单点失败的问题,所以 sentinel 支持集群,也支持同时监控多个主从复制集群。
[root@CentOS74 ~]# cat /etc/redis-sentinel.conf | grep ^[^#]
bind 0.0.0.0 #监听IP
port 26379 #监听端口
dir "/tmp" #工作目录
sentinel myid d645331e011f0e4cbc9ac83cce729d615880a630
sentinel monitor mymaster 192.168.30.74 6379 2 #定义集群名称 主节点IP 主节点端口 法定人数
sentinel parallel-syncs mymaster 5 #当从节点当选主节点,一次性允许多少从节点重新指向新主
sentinel auth-pass mymaster linux #主节点密码
sentinel config-epoch mymaster 0
logfile "/var/log/redis/sentinel.log" #日志文件
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 192.168.30.174 6379
sentinel known-slave mymaster 192.168.30.75 6379
sentinel known-sentinel mymaster 192.168.30.75 26379 6a8f5aedcf69da4b8f4c6805f8bf39dfa3f3cf3c
sentinel known-sentinel mymaster 192.168.30.174 26379 d42a162d3c06f7c80a404d7f8058704c4f8fb81c
sentinel current-epoch 0
开启 redis-sentinel 服务,并使用 redis-cli 工具通过 26379 端口连接 sentinel 服务
SENTINEL masters 查看当前 sentinel 监控的主从集群的主节点状态
SENTINEL slaves <MASTER_NAME> 查看指定主节点下的从节点状态
SENTINEL failover <MASTER_NAME> 强制将指定主节点状态改为DOWN
SENTINEL get-master-addr-by-name <MASTER_NAME>
查看日志文件 /var/log/redis/sentinel.log
1222:X 26 Jul 00:25:59.426 # Sentinel ID is d645331e011f0e4cbc9ac83cce729d615880a630 #监控ID
1222:X 26 Jul 00:25:59.426 # +monitor master mymaster 192.168.30.74 6379 quorum 2 #读取配置文件
1222:X 26 Jul 00:25:59.427 * +slave slave 192.168.30.174:6379 192.168.30.174 6379 @ mymaster 192.168.30.74 6379 #检测到一个节点加入到mymaster集群
1222:X 26 Jul 00:25:59.427 * +slave slave 192.168.30.75:6379 192.168.30.75 6379 @ mymaster 192.168.30.74 6379 #又检测到一个节点加入到mymaster集群
1222:X 26 Jul 00:26:20.254 * +sentinel sentinel d42a162d3c06f7c80a404d7f8058704c4f8fb81c 192.168.30.174 26379 @ mymaster 192.168.30.74 6379 #检测到sentinel集群新增了一个成员
1222:X 26 Jul 00:26:30.723 * +sentinel sentinel 6a8f5aedcf69da4b8f4c6805f8bf39dfa3f3cf3c 192.168.30.75 26379 @ mymaster 192.168.30.74 6379 #检测到sentinel集群又新增了一个成员
尝试停止主节点的 redis 服务,模拟主节点故障,并查看 sentinel 日志
1974:X 26 Jul 01:54:55.780 # +sdown master mymaster 192.168.30.74 6379 #主观down
1974:X 26 Jul 01:54:55.847 # +odown master mymaster 192.168.30.74 6379 #quorum 2/2 #客观down
1974:X 26 Jul 01:54:55.847 # +new-epoch 1 #配置更新
1974:X 26 Jul 01:54:55.847 # +try-failover master mymaster 192.168.30.74 6379 尝试选举新的master
1974:X 26 Jul 01:54:55.873 # +vote-for-leader 23efcd5b5d29bcdcfed13a95a11bdcca4e76de56 1 #本节点投票
1974:X 26 Jul 01:54:55.873 # 68b9310ae0ffc1c2cb6458765bdb2b83d02a6fb7 voted for 68b9310ae0ffc1c2cb6458765bdb2b83d02a6fb7 1 #其他节点的投票
1974:X 26 Jul 01:54:55.876 # a04f04ec089a2e65272445c5c19c9d76d94cc12d voted for 68b9310ae0ffc1c2cb6458765bdb2b83d02a6fb7 1
1974:X 26 Jul 01:54:56.530 # +config-update-from sentinel 68b9310ae0ffc1c2cb6458765bdb2b83d02a6fb7 192.168.30.75 26379 @ mymaster 192.168.30.74 6379 #修改down节点的配置文件
1974:X 26 Jul 01:54:56.530 # +switch-master mymaster 192.168.30.74 6379 192.168.30.174 6379 #新master产生
1974:X 26 Jul 01:54:56.531 * +slave slave 192.168.30.75:6379 192.168.30.75 6379 @ mymaster 192.168.30.174 6379 #从节点重新指向新master
1974:X 26 Jul 01:54:56.531 * +slave slave 192.168.30.74:6379 192.168.30.74 6379 @ mymaster 192.168.30.174 6379
再次启动宕机节点,角色已经被降级为从节点
总结 Redis-Sentinel
- sentinel集群通过给定的配置文件发现master,启动时会监控master。通过向master发送info信息获得该服务器下面的所有从服务器。
- sentinel集群通过命令连接向被监视的主从服务器发送hello信息(每秒一次),该信息包括sentinel本身的ip、端口、id等内容,以此来向其他sentinel宣告自己的存在。
- sentinel集群通过订阅连接接收其他sentinel发送的hello信息,以此来发现监视同一个主服务器的其他sentinel;集群之间会互相创建命令连接用于通信,因为已经有主从服务器作为发送和接收hello信息的中介,sentinel之间不会创建订阅连接。
- sentinel集群使用ping命令来检测实例的状态,如果在指定的时间内(down-after-milliseconds)没有回复或则返回错误的回复,那么该实例被判为下线。
- 当failover主备切换被触发后,failover并不会马上进行,还需要sentinel中的大多数sentinel授权后才可以进行failover,即进行failover的sentinel会去获得指定quorum个的sentinel的授权,成功后进入ODOWN状态。如在5个sentinel中配置了2个quorum,等到2个sentinel认为master死了就执行failover。
- sentinel向选为master的slave发送SLAVEOF NO ONE命令,选择slave的条件是sentinel首先会根据slaves的优先级来进行排序,优先级越小排名越靠前。如果优先级相同,则查看复制的下标,哪个从master接收的复制数据多,哪个就靠前。如果优先级和下标都相同,就选择进程ID较小的。
- sentinel被授权后,它将会获得宕掉的master的一份最新配置版本号(config-epoch),当failover执行结束以后,这个版本号将会被用于最新的配置,通过广播形式通知其它sentinel,其它的sentinel则更新对应master的配置。
Redis Cluster
Redis Cluster实现在多个节点之间进行数据共享,即使部分节点失效或者无法进行通讯时,Cluster仍然可以继续处理请求。若每个主节点都有一个从节点支持,在主节点下线或者无法与集群的大多数节点进行通讯的情况下, 从节点提升为主节点,并提供服务,保证Cluster正常运行,Redis Cluster的节点分片是通过哈希槽(hash slot)实现的,每个键都属于这 16384(0~16383) 个哈希槽的其中一个,每个节点负责处理一部分哈希槽。
################################ REDIS CLUSTER ###############################
cluster-enabled yes #启用集群
cluster-config-file redis-cluster.conf #指定集群配置文件
cluster-node-timeout 15000 #声明从节点超时时间
cluster-slave-validity-factor 10 #设置从节点超时因子
cluster-migration-barrier 1 #最小从节点个数,从节点数量小于该值将不会进行故障转移
cluster-require-full-coverage yes #必须将所有slot分配完,集群才能够提供服务
超时因子:在进行故障转移的时候,全部slave都会请求申请为master,但是有些slave可能与master断开连接一段时间了,导致数据过于陈旧,这样的slave不应该被提升为master。该参数就是用来判>断slave节点与master断线的时间是否过长。判断方法是:
比较slave断开连接的时间和(node-timeout * slave-validity-factor) + repl-ping-slave-period,如果节点超时时间为三十秒, 并且slave-validity-factor为10,假设默认的repl-ping-slave-period是10秒,即如果超过310秒slave将不会尝试进行故障转移。可能出现由于某主节点失联却没有从节点能顶上的情况,从而导致集群不能正常工作,在这种情况下,只有等到原来的主节点重新回归到集群,集群才恢复运作。如果设置成0,则无论从节点与主节点失联多久,从节点都会尝试升级成主节点
-
配置Redis Cluster
在配置文件中开启集群功能后,需要为每个节点分配 slot
redis-cli -c -h 节点IP -p 服务端口 -a 节点密码 cluster addslots {起点..终点}
[root@CentOS74 ~]# redis-cli -c -h 192.168.30.74 -p 6379 -a linux cluster addslots {0..5499}
OK
[root@CentOS74 ~]# redis-cli -c -h 192.168.30.174 -p 6379 -a linux cluster addslots {5500..10999}
OK
[root@CentOS74 ~]# redis-cli -c -h 192.168.30.75 -p 6379 -a linux cluster addslots {11000..16383}
OK
登录客户端使用 CLUSTER MEET 确认集群成员之间的关系
CLUSTER MEET ip port
使用 CLUSTER INFO 命令查看集群状态
127.0.0.1:6379> CLUSTER INFO
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:3
cluster_size:3
cluster_current_epoch:2
cluster_my_epoch:1
cluster_stats_messages_sent:1078
cluster_stats_messages_received:1078
随后可以使用 help @CLUSTER 命令查看其它集群组中的命令