Redis 之五:Redis 的主从复制

概念

主从复制,是指将一台 Redis 服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

主从复制的作用

主从复制的作用主要包括:

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  4. 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

如何使用主从复制

为了更直观的理解主从复制,在介绍其内部原理之前,先说明我们需要如何操作才能开启主从复制。

1. 建立复制

需要注意,主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。

从节点开启主从复制,有 3 种方式:

(1)配置文件

在从服务器的配置文件中加入:slaveof

(2)启动命令

redis-server启动命令后加入 --slaveof

(3)客户端命令

Redis服务器启动后,直接通过客户端执行命令:slaveof ,则该Redis实例成为从节点。

上述 3 种方式是等效的,下面以客户端命令的方式为例,看一下当执行了slaveof 后,Redis 主节点和从节点的变化。

2. 实例

准备工作:启动两个节点

  1. 复制配置文件

    [root@localhost bin]# ls ### 进入redis 安装目录下可执行目录
    dump.rdb redis-benchmark redis-check-aof redis-check-rdb redis-cli redis.conf redis-sentinel redis-server
    [root@localhost bin]# cp redis.conf redis1.conf ### 复制配置文件作为其中一个从机
    [root@localhost bin]# cp redis.conf redis2.conf ### 复制配置文件作为其中一个从机
    [root@localhost bin]# vi redis1.conf ### 修改redis1.conf端口为 6381
    ##***** :/6379 搜索即可找到

此时之前的 redis 实例端口为6379 ,现在又多一个6381。

接下来分别启动各自服务。

启动6379:

[root@localhost bin]# redis-server redis.conf      ###******* 注意使用各自的配置文件
16624:C 05 Aug 2021 09:11:14.767 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
16624:C 05 Aug 2021 09:11:14.767 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=16624, just started
16624:C 05 Aug 2021 09:11:14.767 # Configuration loaded
[root@localhost bin]# redis-cli -p 6379 
127.0.0.1:6379> info replication              ###******* 查看主从情况 
# Replication
role:master                                     ###******* 默认自己都为master 主节点
connected_slaves:0
master_replid:e2995fc02165a6f45644b6076aa4ae7c75ccf3d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:28
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:28
127.0.0.1:6379> 

再启动6381:

[root@localhost bin]# redis-server redis1.conf                     #***** 使用第二个实例配置文件启动
16641:C 05 Aug 2021 09:12:07.514 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
16641:C 05 Aug 2021 09:12:07.515 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=16641, just started
16641:C 05 Aug 2021 09:12:07.515 # Configuration loaded


[root@localhost bin]# redis-cli -p 6381                            ##**** 使用6381
127.0.0.1:6381> info replication
# Replication
role:master                                                        ##**** 一样显示主节点
connected_slaves:0
master_replid:fdc1b15ab0d76bca91227af2c0ebf8198a7c8541
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381> 

从上面看出,两个Redis节点启动后(分别称为6379节点和6381节点),默认都是主节点。

3. 主从配置

此时在6381节点执行 slaveof 命令,使之变为从节点:

127.0.0.1:6381> slaveof 127.0.0.1 6379            ## 建立主从关系,附属6379
OK

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:0
master_sync_in_progress:0
slave_repl_offset:70
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:e2995fc02165a6f45644b6076aa4ae7c75ccf3d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:29
repl_backlog_histlen:42
127.0.0.1:6381> 

再看 6379 节点:

127.0.0.1:6379> info replication
# Replication
role:master                                            
connected_slaves:1                                    # 所属从节点有一个
slave0:ip=127.0.0.1,port=6381,state=online,offset=196,lag=1
master_replid:e2995fc02165a6f45644b6076aa4ae7c75ccf3d6
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:196
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:196

测试读写操作:

先在从节点查询一个不存在的 key,然后去主节点添加此 key ,会发现会自动同步到各个从节点

127.0.0.1:6381>  get age
(nil)

127.0.0.1:6381> get age        ### 当主节点存入age 后 ,再取值,发现已经自动同步到从机了
"23"
127.0.0.1:6381> set age 24
(error) READONLY You can't write against a read only replica.  
127.0.0.1:6381> 

注意:上面的error提示中,说明从节点是只能读,不能写的。所谓主从复制。读写分离

4. 启动命令方式

redis-server启动命令后加入 --slaveof

上面的方式,使用客户端命令方式来实现的主从的配置。

下面使用启动时指定主从关系。

redis-server myredis/redis1.conf --slaveof 127.0.0.1 6379 启动 Redis 服务时,指定所属的主节点为 6379 端口上的服务

[root@wang ~]# redis-server myredis/redis1.conf --slaveof 127.0.0.1 6379
29087:C 25 Aug 2021 16:04:29.836 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
29087:C 25 Aug 2021 16:04:29.836 # Redis version=6.0.6, bits=64, commit=00000000, modified=0, pid=29087, just started
29087:C 25 Aug 2021 16:04:29.836 # Configuration loaded
[root@wang ~]# 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:2
master_sync_in_progress:0
slave_repl_offset:1007
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:f05b6c77978f163ae77ebed3dcd0bb85790ed197
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1007
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
5. 配置文件方式

可以在启动的配置文件中 redis1.config 中追加下面的一行配置 :

slaveof 127.0.0.1 6379

[root@wang myredis]# echo "slaveof 127.0.0.1 6379" >> redis1.conf 
[root@wang myredis]# tail -5 redis1.conf 
相关推荐
测开小菜鸟4 分钟前
使用python向钉钉群聊发送消息
java·python·钉钉
Ai 编码助手1 小时前
MySQL中distinct与group by之间的性能进行比较
数据库·mysql
P.H. Infinity1 小时前
【RabbitMQ】04-发送者可靠性
java·rabbitmq·java-rabbitmq
生命几十年3万天1 小时前
java的threadlocal为何内存泄漏
java
陈燚_重生之又为程序员1 小时前
基于梧桐数据库的实时数据分析解决方案
数据库·数据挖掘·数据分析
caridle1 小时前
教程:使用 InterBase Express 访问数据库(五):TIBTransaction
java·数据库·express
白云如幻1 小时前
MySQL排序查询
数据库·mysql
萧鼎1 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
^velpro^1 小时前
数据库连接池的创建
java·开发语言·数据库
苹果醋31 小时前
Java8->Java19的初步探索
java·运维·spring boot·mysql·nginx