高可用架构-Redis Replication

今天学习下如何基于Redis 复制功能构建高可用架构-主从复制,Redis Replication 支持数据复制和故障切换。Redis复制是允许Redis实例完全复制主实例的过程。默认情况下,复制是一个异步过程。Redis复制在主机端和副本端都是非阻塞的。这意味着当一个或多个副本执行初始同步或部分重新同步时,主机将继续处理查询。同样,在副本端,在复制期间,它可以使用旧版本的数据集处理查询。

Redis Replication为了解决Redis高并发的问题,在数据实时性要求不高的场景下,允许应用程序进行读写分离操作。读取副本可提高读取吞吐量,并在节点故障时防止数据丢失。复制既可以用于可扩展性,以便为只读查询提供多个副本,也可以用于提高数据安全性和高可用性。

除了默认情况下是只读的之外,主副本和副本之间的一个重要区别是副本不会过期/收回密钥,它们等待主副本过期密钥,当主副本过期或收回密钥时,副本会合成一个DEL命令,该命令会传输到所有副本。

redis failover命令 redis info replication_单机Replication

主从复制的核心机制

  • 当主机和副本实例连接良好时,主机通过向副本发送一系列命令来复制主机侧发生的对数据集的影响,从而保持副本的更新,原因包括:客户端写入、密钥过期或被逐出、任何其他更改主数据集的操作。
  • 当主服务器和副本之间的链接断开时,由于网络问题或由于在主服务器或副本中检测到超时,副本将重新连接并尝试继续进行部分重新同步:这意味着它将尝试只获取断开连接期间丢失的部分命令流。
  • 当无法进行部分重新同步时,复制副本将要求进行完全重新同步。这将涉及一个更复杂的过程,在该过程中,主服务器需要创建其所有数据的快照,将其发送到副本,然后在数据集更改时继续发送命令流。

核心配置

启动Redis的主从复制很简单,只需要在从节点的配置中加入

replicaof <redis master IP>

主从复制特点

  • Redis使用异步复制,通过从节点来处理的数据量(读取数据)
  • 主节点可以配置多个从节点
  • 从节点能够接受来自其他从节点的连接。除了将多个从节点连接到同一主节点之外,从节点还可以拥有自己的从节点。自Redis 4.0以来,所有子副本将从主副本接收完全相同的复制流。
  • Redis复制在主节点端是非阻塞的。这意味着当一个或多个副本执行初始同步或部分重新同步时,主节点将继续处理查询。
  • Redis主从复制,在从节点也是非阻塞执行,执行数据同步时,从节点使用旧数据进行数据处理。
  • Redis主从复制既可以用于可扩展性,也可以用于只读查询的多个副本(例如,可以将缓慢的O(N)操作卸载到副本),也可以简单地用于提高数据安全性和高可用性。

单机主从

主从方案

在单机搭建三个节点的主从复制架构,一主两从。节点占用的端口分配为

  • 主节点 - 6379端口
  • 从节点1 - 6380端口
  • 从节点2 - 6381端口
# 创建 replica 目录
mkdir replica

# copy redis.conf 文件至 replica下
cp redis.conf replica/redis_master.conf
cp redis.conf replica/redis_node1.conf
cp redis.conf replica/redis_node2.conf

主节点配置

# vim replica/redis_master.conf
protected-mode no
dbfilename dump_6379.rdb
pidfile /var/run/redis_6379.pid
appendfilename "appendonly_6379.aof"

从节点配置

  • 从节点1Redis 配置
# vim replica/redis_node1.conf
port 6380
protected-mode no
dbfilename dump_6380.rdb
pidfile /var/run/redis_6380.pid
appendfilename "appendonly_6380.aof"
replicaof 127.0.0.1 6379
  • 从节点2Redis 配置
# vim replica/redis_node2.conf
port 6381
protected-mode no
dbfilename dump_6381.rdb
pidfile /var/run/redis_6381.pid
appendfilename "appendonly_6381.aof"
replicaof 127.0.0.1 6379

启动服务

AndydeMacBook-Pro:redis-stable andy$ redis-server replica/redis_master.conf 
AndydeMacBook-Pro:redis-stable andy$ redis-server replica/redis_node1.conf 
AndydeMacBook-Pro:redis-stable andy$ redis-server replica/redis_node2.conf
# 查看进程是否启动
AndydeMacBook-Pro:redis-stable andy$ ps -ef | grep redis
  501 93666     1   0  4:48上午 ??         0:16.63 redis-server 127.0.0.1:6380 
  501 93670     1   0  4:48上午 ??         0:16.77 redis-server 127.0.0.1:6379 
  501 94881     1   0  8:23下午 ??         0:00.04 redis-server 127.0.0.1:6381

验证测试

验证工作分两部分,查看各节点状态是否一致;从主节点添加数据,查看其他节点是否已经进行数据同步

节点状态验证

  • 主节点状态验证
AndydeMacBook-Pro:redis-stable andy$ redis-cli 
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=::1,port=6380,state=online,offset=7512,lag=0
slave1:ip=127.0.0.1,port=6381,state=online,offset=7512,lag=0
master_failover_state:no-failover
master_replid:e63e82a592894ab10f2e2e02b2d3d4160c8a61aa
master_replid2:952696240184bb42a0f7109718c5aa87ee025e00
master_repl_offset:7512
second_repl_offset:157
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:157
repl_backlog_histlen:7356
  • 从节点1状态验证
AndydeMacBook-Pro:redis-stable andy$ redis-cli -p 6380
127.0.0.1:6380> info replication
# Replication
role:slave
master_host:localhost
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:8354
slave_repl_offset:8354
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e63e82a592894ab10f2e2e02b2d3d4160c8a61aa
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:8354
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:216
repl_backlog_histlen:8139
  • 从节点2状态验证
AndydeMacBook-Pro:redis-stable andy$ redis-cli -p 6381
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_read_repl_offset:8424
slave_repl_offset:8424
slave_priority:100
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e63e82a592894ab10f2e2e02b2d3d4160c8a61aa
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:8424
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:7247
repl_backlog_histlen:1178

数据同步验证

  • 登录主节点
AndydeMacBook-Pro:redis-stable andy$ redis-cli
127.0.0.1:6379> set java world
OK
127.0.0.1:6379> get java
"world"
  • 查看从节点1
AndydeMacBook-Pro:~ andy$ redis-cli -p 6380
127.0.0.1:6380> get java
"world"
  • 查看从节点2
AndydeMacBook-Pro:~ andy$ redis-cli -p 6381
127.0.0.1:6381> get java
"world"

同步机制

增量同步

redis failover命令 redis info replication_redis failover命令_02

如上图,当从节点连接到主节点时,自动发送PSYNC命令到主节点,同时携带 副本ID、偏移量。这样,主节点根据副本ID、偏移量就知道从节点上次同步数据的位置,只需要发送所需的增量部分,即数据增量同步。

# 语法
PSYNC replicationid offset

redis failover命令 redis info replication_redis failover命令_03

如上图,可以看到从节点的ID,以及偏移量信息

全库同步

对于新加入的节点,或者在master中找不到副本ID,则会发生完全重新同步:在这种情况下,从节点的复制将从头开始获得完整数据。其内部机制为:

主节点启动后台进程异步生成RDB文件,当后台进程完成Redis服务接收的写入指令后。主节点将RDB文件传输到从节点,从节点将数据保存在磁盘文件,然后将其加载到内存中。需要注意:当Redis数据十分庞大时,整个复制过程将非常缓慢。

同步认证

如果主节点设置了密码,那么从节点在进行数据同步时配置密码,相关的配置也非常的简单。

  1. 通过脚本临时性设置密码 - 临时性: 表示当redis节点重启时 密码设置无效
config set masterauth <password>
  1. 修改配置文件 永久性的设置文件
masterauth <password>