redis 主从master-slave搭建及测试

本文详细介绍了Redis主从复制的配置过程,包括正常读写、主节点闪断及故障恢复等情况。在主节点断开或故障时,slave节点能自动重连,并探讨了slave在不同配置下的读写行为。测试显示,slave需通过特定配置才能写入数据,且在主节点无数据时,slave数据会被清除。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、redis主从的特性

 

  1. redis 使用异步复制。从 redis 2.8 开始,slave 也会周期性的告诉 master 现在的数据量。可能只是个机制,用途应该不大。
  2. 一个 master 可以拥有多个 slave,废话,这也是业界的标配吧。

  3. slave 可以接收来自其他 slave 的连接。意思是不是就是说 slave 在接收其他的slave的连接之后成为 master ?答案是 fou,仍然是slave,并不会升级为master

  4. redis 复制在 master 这一端是非阻塞的,也就是说在和 slave 同步数据的时候,master 仍然可以执行客户端的操作命令而不受其影响。这点都不能保证,要你干嘛?
  5. redis 复制在 slave 这一端也是非阻塞的。在配置文件里面有 slave-serve-stale-data 这一项,如果它为 yes ,slave 在执行同步时,它可以使用老版本的数据来处理查询请求,如果是 no ,slave 将返回一个错误。在完成同步后,slave 需要删除老数据,加载新数据,在这个阶段,slave 会阻止连接进来。
  6. Replication can be used both for scalability, in order to have multiple slaves for read-only queries (for example, heavy SORT operations can be offloaded to slaves), or simply for data redundancy.这句话我也没理解什么意思。

  7. 使用复制可以避免 master 因为需要把全部的数据集写入磁盘而造成的开销,因此可以把 master 中 save 配置项全部注释掉,不让它进行保存,然后配置 slave ,让 slave 保存。虽然有这个特性,但是我们好像一般不这么做。

二、

先打开三个终端,然后起三个实例,分别用三个 client 去连接它们:

zhaoguihuadediannao:src zhaogh$ ./redis-server --port 10000 --daemonize yes

zhaoguihuadediannao:src zhaogh$ 

zhaoguihuadediannao:src zhaogh$ ./redis-cli -p 10000

端口10000的做 master。

slave 01:

zhaoguihuadediannao:src zhaogh$ ./redis-server --port 10001 --daemonize yes

zhaoguihuadediannao:src zhaogh$ 

zhaoguihuadediannao:src zhaogh$ ./redis-cli -p 10001

slave 02:

zhaoguihuadediannao:src zhaogh$ ./redis-server --port 10002 --daemonize yes

zhaoguihuadediannao:src zhaogh$ 

zhaoguihuadediannao:src zhaogh$ ./redis-cli -p 10002

上面只是让它们的实例启动了并用客户端去连接它,并没有设置主从关系。在 slave 01 和 slave 02 上执行下面的命令:

127.0.0.1:10001> slaveof 127.0.0.1 10000

OK

127.0.0.1:10001> 

这样就设置好了主从关系。我们来试试有没有效果。

127.0.0.1:10001> get testkey001

(nil)

127.0.0.1:10001> 

这个时候是没有值的。

master 上执行:

127.0.0.1:10000> set testkey001 testvalue001

OK

127.0.0.1:10000> 

然后看看 slave 上有没有:

127.0.0.1:10001> get testkey001

"testvalue001"

127.0.0.1:10001> 

127.0.0.1:10002> get testkey001

"testvalue001"

127.0.0.1:10002> 

有了,是不是比***点读机还 easy ?已经有了感性的认识,我们来介绍一下它的原理吧。

当你设置了主从关系后,slave 在第一次连接或者重新连接 master 时,slave 都会发送一条同步指令给 master ;

master 接到指令后,开始启动后台保存进程保存数据,接着收集所有的数据修改指令。后台保存完了,master 就把这份数据发送给 slave,slave 先把数据保存到磁盘,然后把它加载到内存中,master 接着就把收集的数据修改指令一行一行的发给 slave,slave 接收到之后重新执行该指令,这样就实现了数据同步。

slave 在与 master 失去联系后,自动的重新连接。如果 master 收到了多个 slave 的同步请求,它会执行单个后台保存来为所有的 slave 服务。

一旦 master 和 slave 在失去联系并重新连接上,总是会重新进行一次完整的同步


三、slave  ---master测试

0. 初始情况下各节点info情况(部分有用信息):

MASTER ->
 'connected_slaves': 1,            #可判断slave存活状况
SLAVE  ->
 'master_host': '127.0.0.1',
 'master_last_io_seconds_ago': 5,
 'master_link_status': 'up',       #可判断master与slave存活状况
 'master_port': 6378

1. 正常读写:

In [32]: r1.set('key', 'value')
Out[32]: True

In [34]: r2.get('key')
Out[34]: 'value'

2. 主备正常连接下, 默认slave(不配置slave-read-only on)

向slave写入后发现报错

In [35]: r2.set('key2', 'value')
ReadOnlyError: You can't write against a read only slave

3. Master闪断:

Crash掉主节点:

'master_host': '127.0.0.1',
'master_last_io_seconds_ago': -1,
'master_link_down_since_seconds': 4,
'master_link_status': 'down',
'master_port': 6378

重启主节点后,slave自动从从新建立连接

'master_host': '127.0.0.1',
'master_last_io_seconds_ago': 9,
'master_link_status': 'up',
'master_port': 6378,

4. Crash掉主节点,slave默认(不配置slave-read-only on 情况)

即使master挂掉,slave写入依然报错

SLAVE ->
    'master_host': '127.0.0.1',
    'master_last_io_seconds_ago': -1,
    'master_link_down_since_seconds': 6,
    'master_link_status': 'down',
    'master_port': 6378
    
In [37]: r2.set('key', 'value')
ReadOnlyError: You can't write against a read only slave.

设置slave为readonly,发现报错

zb@ubuntu:~/codes/test$ redis-cli -h 127.0.0.1 -p 6379 set slave-read-only no
(error) READONLY You can't write against a read only slave.

需要关闭slave的slave特性, 将其升级为主节点

zb@ubuntu:~/codes/test$ redis-cli -h 127.0.0.1 -p 6379 slaveof NO ONE
OK
zb@ubuntu:~/codes/test$ redis-cli -h 127.0.0.1 -p 6379 set slave-read-only no
OK

升级为主节点后,继续向slave写入:

In [38]: r2.set('key', 'value')
Out[38]: True

5. 重启master, 如果将slave升级为master, 此时master与slave已经隔离, 都作为主节点存在(注意此时的主节点是没有数据的)

In [41]: r1.get('key')

In [42]: 

6. 拷贝R2的dump数据到R1后重启:

In [43]: r1.get('key')
Out[43]: 'value'

7. 从新将R2设置为R1的slave(slave默认配置):

向slave写入:

In [45]: r2.set('key2', 'value')
ReadOnlyError: You can't write against a read only slave.

8. 如果将slave-read-only 属性写到配置文件中:

可以向slave写入数据,但是不会同步到master

In [50]: r2.set('key2', 'value')
Out[50]: True

9. Crash掉R1,往R2写数据(关掉slave-read-only):

SLAVE ->
    'master_link_status': 'down'

In [75]: r2.set('key2', 'value')
Out[75]: True

重启Master(此时的master无数据):

In [85]: r2.get('key2')

In [86]: r2.get('key3')

可以看到,重启了Master后,slave同步了master状态,由于master没有数据,slave的数据同时被删除

总结(部分测试未写出来):

  • slave 配置为slave-read-only on需要升级为主节点或者写入配置文件中, 而不能在默认slave情况下直接设置
  • master与slave断开后会检测心跳, 从新建立连接.
  • 可以直接copy DUMP文件从新重启master
  • 在Master为空以后,slave同步数据会抹掉全部数据.




使用 Docker 搭建 Redis 主从集群是一种高效且便捷的方式,能够快速构建测试或开发环境。以下是详细的搭建步骤: ### 创建自定义 Docker 网络 为了确保容器之间可以互相通信,首先需要创建一个自定义的 Docker 网络。 ```bash docker network create redis-network ``` ### 启动 Redis 主节点 启动第一个 Redis 容器作为主节点,并将其加入之前创建的网络中。 ```bash docker run -d --name redis-master --network redis-network -p 6379:6379 redis ``` ### 启动 Redis 从节点 接下来,启动两个额外的 Redis 容器作为从节点。同样地,将它们加入到 `redis-network` 中。 ```bash docker run -d --name redis-slave1 --network redis-network -p 6380:6379 redis docker run -d --name redis-slave2 --network redis-network -p 6381:6379 redis ``` ### 配置主从关系 一旦所有容器都运行起来后,需要手动配置从节点以指向主节点[^5]。这可以通过执行以下命令来完成: ```bash docker exec -it redis-slave1 redis-cli replicaof redis-master 6379 docker exec -it redis-slave2 redis-cli replicaof redis-master 6379 ``` 这些命令会使得两个从节点开始复制主节点上的数据。 ### 验证配置 可以通过连接到任一从节点并执行 `INFO replication` 命令来验证主从配置是否成功。如果一切正常,你应该能看到关于主节点的信息以及从节点的状态。 ### 持久化配置(可选) 如果你希望在重启容器后仍然保持主从关系,那么你需要在每个从节点的配置文件中添加相应的 `replicaof` 设置。可以通过挂载自定义的 Redis 配置文件到容器中实现这一点[^4]。 通过以上步骤,就可以利用 Docker 成功搭建一个 Redis 主从集群环境。此设置非常适合用于学习、测试或者小型项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值