Redis主从

Redis主从

虽然 Redis 可以实现单机的数据持久化,但无论是 RDB 也好或者 AOF 也好,都解决不了单点宕机问题,即一旦 redis 服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失,因此需要使用另外的技术来解决单点问题。

配置reids 主从

主备模式,可以实现 Redis 数据的跨主机备份。

程序端连接到高可用负载的 VIP,然后连接到负载服务器设置的Redis后端server,此模式不需要在程序里面配置 Redis 服务器的真实 IP 地址,当后期 Redis 服务器 IP 地址发生变更只需要更改 redis相应的后端serrver即可,可避免更改程序中的 IP 地址设置,如下图。

命令行

>SLAVEOF 10.9.119.18 6379 # 建立主从

建立主从关系过程

master日志

31270:M 26 Mar 2021 16:03:18.711 * Replica 10.9.119.19:6379 asks for synchronization
31270:M 26 Mar 2021 16:03:18.711 * Partial resynchronization not accepted: Replication ID mismatch (Replica asked for 'a89ed1462c5553a524d32a7138d105f6599b8000', my replication IDs are '040b8dd8be85b03f3e9ead7bf811094e380c91f2' and '0000000000000000000000000000000000000000')
31270:M 26 Mar 2021 16:03:18.711 * Starting BGSAVE for SYNC with target: disk
31270:M 26 Mar 2021 16:03:18.712 * Background saving started by pid 31357
31357:C 26 Mar 2021 16:03:18.743 * DB saved on disk
31357:C 26 Mar 2021 16:03:18.744 * RDB: 0 MB of memory used by copy-on-write
31270:M 26 Mar 2021 16:03:18.839 * Background saving terminated with success
31270:M 26 Mar 2021 16:03:18.839 * Synchronization with replica 10.9.119.19:6379 succeeded

日志简要说明
1、从节点请求同步
2、硬盘启动BGSAVE和SYNC
3、开启一个子进程进行快照
4、将保存好的数据,发送给从节点同步完成

salve日志

27767:S 26 Mar 2021 16:03:18.537 * Before turning into a replica, using my master parameters to synthesize a cached master: I may be able to synchronize with the new master with just a partial transfer.
27767:S 26 Mar 2021 16:03:18.537 * REPLICAOF 10.9.119.18:6379 enabled (user request from 'id=3 addr=10.9.119.19:51468 fd=7 name= age=2 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=45 qbuf-free=32723 obl=0 oll=0 omem=0 events=r cmd=slaveof')
27767:S 26 Mar 2021 16:03:18.785 * Connecting to MASTER 10.9.119.18:6379
27767:S 26 Mar 2021 16:03:18.785 * MASTER <-> REPLICA sync started
27767:S 26 Mar 2021 16:03:18.785 * Non blocking connect for SYNC fired the event.
27767:S 26 Mar 2021 16:03:18.786 * Master replied to PING, replication can continue...
27767:S 26 Mar 2021 16:03:18.786 * Trying a partial resynchronization (request a89ed1462c5553a524d32a7138d105f6599b8000:1).
27767:S 26 Mar 2021 16:03:18.787 * Full resync from master: 040b8dd8be85b03f3e9ead7bf811094e380c91f2:14
27767:S 26 Mar 2021 16:03:18.787 * Discarding previously cached master state.
27767:S 26 Mar 2021 16:03:18.915 * MASTER <-> REPLICA sync: receiving 210 bytes from master
27767:S 26 Mar 2021 16:03:18.915 * MASTER <-> REPLICA sync: Flushing old data
27767:S 26 Mar 2021 16:03:18.915 * MASTER <-> REPLICA sync: Loading DB in memory
27767:S 26 Mar 2021 16:03:18.915 * MASTER <-> REPLICA sync: Finished with success

日志简要说明
1、已启用REPLICAOF
2、连接到master开始同步,非阻塞连接
3、同步一部分,完全同步完成。删除之前的数据
4、刷新旧数据,将DB加载到内存

Redis支持主从复制分为全量同步和增量同步,首次同步是全量同步,主从同步可以让从服务器从主服务器备份数据,而且从服务器还可与有从服务器,即另外一台redis服务器可以从一台从服务器进行数据同步,redis的主从同步是非阻塞的,其收到从服务器的sync(2.8 版本之前是 PSYNC)命令会fork一个子进程在后台执行bgsave命令,并将新写入的数据写入到一个缓冲区里面,bgsave执行完成之后并生成的将RDB文件发送给客户端,客户端将收到后的RDB文件载入自己的内存,然后主redis将缓冲区的内容在全部发送给从redis,之后的同步从服务器会发送一个offset的位置(等同于MySQL的binlog的位置)给主服务器,主服务器检查后位置没有错误将此位置之后的数据包括写在缓冲区的积压数据发送给redis从服务器,从服务器将主服务器发送的挤压数据写入内存,这样一次完整的数据同步,再之后再同步的时候从服务器只要发送当前的offset位置给主服务器,然后主服务器根据响应的位置将之后的数据发送给从服务器保存到其内存即可。

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:

  1. 从服务器连接主服务器,发送SYNC命令
  2. 主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB 快照文件并使用缓冲区记录此后执行的所有写命令
  3. 主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令
  4. 从服务器收到快照文件后丢弃所有旧数据,载入收到的快照
  5. 主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令
  6. 从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令
  7. 后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步

配置到redis.conf

replicaof 10.9.119.18 6379
masterauth 123456 #master如果密码需要设置

节点状态

>info
# Replication
role:slave

slave状态只读无法写入数据

slave切换master

停止 slave 同步

10.9.119.19:6379> SLAVEOF no one
OK
10.9.119.19:6379> info Replication
# Replication
role:master
connected_slaves:0
master_replid:6362a56ec5612e09865c0ee28ed3d661aced4fc0
master_replid2:040b8dd8be85b03f3e9ead7bf811094e380c91f2
master_repl_offset:9338
second_repl_offset:9339
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:15
repl_backlog_histlen:9324

Slave节点再有Slave

Redis 从1看状态

10.9.119.19:6379> info replication
# Replication
role:slave
master_host:10.9.119.18
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3 	# 最近一次与master通信已经过去多少秒。
master_sync_in_progress:0  		# 是否正在与 master 通信。
slave_repl_offset:9643			# 当前同步的偏移量。
slave_priority:100				# slave优先级,master故障后值越小越优先同步。
slave_read_only:1
connected_slaves:1
slave0:ip=10.9.119.20,port=6379,state=online,offset=9643,lag=0   # salve节点
master_replid:040b8dd8be85b03f3e9ead7bf811094e380c91f2
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:9643
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:9339
repl_backlog_histlen:305

主从同步优化

Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从 2.8 版本开始增加了部分复制的功能。

repl-diskless-sync yes #yes为支持 disk,master将RDB文件先保存到磁盘在发送给slave,no为master直接将 RDB 文件发送给 slave,默认即为使用no,Master RDB文件不需要与磁盘交互。

repl-diskless-sync-delay 5 #Master准备好RDB文件后等等待传输时间

repl-ping-slave-period 10 #slave端向server端发送ping的时间区间设置,默认为10秒

repl-timeout 60 #设置超时时间

repl-disable-tcp-nodelay no #是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟(40ms),造成master与slave数据不一致,假如设置成no,则redis master会立即发送同步数据,没有延迟,前者关注性能,后者关注一致性

repl-backlog-size 1mb #master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如 master 每秒最大写入64mb,最大允许 60 秒,那么就要设置为 64mb*60秒=3840mb(3.8G)=repl-backlog-ttl 3600 如果一段时间后没有 slave 连接到 master,则 backlog size 的内存将会被释放。如果值为 0 则表示永远不释放这部份内存。

slave-priority 100 #slave端的优先级设置,值是一个整数,数字越小表示优先级越高。当 master 故障时将会按照优先级来选择 slave端进行恢复,如果值设置为 0,则表示该 slave 永远不会被选择。

#min-slaves-to-write 0 #从库的个数为0, 假设为3,从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器将拒绝执行写命令

#min-slaves-max-lag 10 #设置当一个 master 端的可用 slave 少于 N 个,延迟时间大于 M 秒时,不接收写操作。

Master的重启会导致master_replid发生变化,slave之前的master_replid就和master不一致从而会引发所有 slave 的全量同步。

每天进步一点点
原文地址:https://www.cnblogs.com/Otiger/p/14583489.html