版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zx711166/article/details/82971705
什么是主从复制
单机有什么问题?
单机存在机器故障、容量瓶颈、QPS(每秒查询率)瓶颈的问题。
主从复制的作用
- 数据副本
- 扩展读性能;
一对一的主从结构
一对多的主从结构(主从备份、读写分离)
简单示例
主节点 set 数据后,从节点可以 get 到主节点中写入的数据。
总结
- 一个 master 可以有多个 salve。
- 一个 salve 只能有一个 master。
- 数据流向是单向的,master 到 slave。
主从复制的配置 — 介绍
两种实现方式
- slaveof命令
- 配置
命令实现
实现复制
- client客户端执行 slaveof 命令;
- 从节点向客户端返回消息(异步过程);
- 从节点从主节点复制数据。
从节点通过slave of切换新的主节点
通过slaveof命令还可以实现切主操作,所谓切主是指把当前从节点对主节点的复制切换到另一个主节点。
执行slaveof{newMasterIp} {newMasterPort}命令即可,
例如把6380节点从原来的复制6379节点变为复 制6381节点,如图6-3所示
- 断开与旧主节点复制关系;
- 与新主节点建立复制关系;
- 删除从节点当前所有数据;
- 对新主节点进行复制操作。
取消复制
- client客户端执行 slaveof no one 命令;
- 从节点与主节点断开连接(之前从主节点复制的数据不会被清除,之后主节点新写入的数据不会同步到从节点);
- 从节点向客户端返回消息(同步过程);
- 从节点晋升为主节点。
修改配置
# 当前节点称为某一个主节点的从节点
slaveof ip port
# 设置该从节点只读
slave-read-only yes
比较
方式 | 命令 | 配置 |
---|---|---|
优点 | 无需重启 | 统一配置 |
缺点 | 不便于管理 | 需要重启 |
主从复制的配置 — 验证
- 创建一个配置文件目录,存放Redis启动配置文件
[root@localhost config]# ll
total 88
-rw-r--r-- 1 carlosfu staff 41K 10 7 22:56 redis.log
- 创建6379服务(主节点)的配置文件
[root@localhost config]# cp redis.conf redis-6379.conf
[root@localhost config]# vim redis-6379.conf
...
# daemonize表示以守护线程方式启动Redis,默认是no
daemonize yes
...
# pidfile表示进程PID文件
pidfile /var/run/redis-6379.pid
...
# port表示服务端口号
port 6379
...
# logfile表示日志文件
logfile "6379.log"
...
# save表示配置RDB自动save条件,实际生产不会使用
#save 900 1
#save 300 10
#save 60 10000
...
# dbfilename表示设置RDB文件名,防止单机多节点是RDB文件产生混乱
dbfilename dump-6379.rdb
...
# dir表示dbfilename文件的工作目录
dir /opt/soft/redis/redis/data/
...
wq!
- 创建6380服务(从节点)的配置文件
[root@localhost config]# cp redis-6379.conf redis-6380.conf
[root@localhost config]# vim redis-6380.conf
...
# daemonize表示以守护线程方式启动Redis,默认是no
daemonize yes
...
# pidfile表示进程PID文件
pidfile /var/run/redis-6380.pid
...
# port表示服务端口号
port 6380
...
# logfile表示日志文件
logfile "6380.log"
...
# save表示配置RDB自动save条件,实际生产不会使用
#save 900 1
#save 300 10
#save 60 10000
...
# dbfilename表示设置RDB文件名,防止单机多节点是RDB文件产生混乱
dbfilename dump-6380.rdb
...
# dir表示dbfilename文件的工作目录
dir /opt/soft/redis/redis/data/
...
# slaveof <masterip> <masterport>表示对从节点配置主节点信息
slaveof 127.0.01 6379
...
wq!
- 查看配置文件
[root@localhost config]# ll
-rw-r--r-- 1 carlosfu staff 41K 10 7 22:59 redis-6379.log
-rw-r--r-- 1 carlosfu staff 41K 10 7 23:01 redis-6380.log
-rw-r--r-- 1 carlosfu staff 41K 10 7 22:56 redis.log
- 启动6379的服务(主节点)、验证服务是否正常、查看节点信息
[root@localhost config]# redis-server redis-6379.conf
[root@localhost config]# ps -ef | grep redis-server
501 77051 1 0 11:01 下午 ?? 0:00.01 redis-server *:6379
501 77057 76575 0 11:01 下午 ttys001 0:00.00 grep --color=auto --exclude-dir-.bar --exclude-dir-CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn redis-server
# 连接客户端
[root@localhost config]# redis-cli
# 查看节点信息
127.0.0.1:6379> info replication
# Replication
role:master #节点角色
connected_slaves:0 #连接从节点个数
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> exit
- 启动6380的服务(从节点)、验证服务是否正常、查看节点信息
# 启动6380的服务
[root@localhost config]# redis-cli -p 6380
Could not connect to Redis at 127.0.0.1:6379: Connection refused not connected> exit
[root@localhost config]# redis-server redis-6380.conf
[root@localhost config]# ll
total 264
-rw-r--r-- 1 carlosfu staff 0B 10 30 23:01 6379.log
-rw-r--r-- 1 carlosfu staff 0B 10 30 23:02 6380.log
-rw-r--r-- 1 carlosfu staff 41K 10 30 22:59 redis-6379.log
-rw-r--r-- 1 carlosfu staff 41K 10 30 23:01 redis-6380.log
-rw-r--r-- 1 carlosfu staff 41K 10 30 22:56 redis.log
# 查看服务是否启动成功
[root@localhost config]# ps -ef | grep redis-server | grep 6380
501 77080 1 0 11:02 下午 ?? 0:00.01 redis-server *:6380
# 查看节点信息
[root@localhost config]# redis-cli -p 6380 info replication
# Replication
role:slave #节点角色
master_hosts:127.0.0.1 #主节点ip
master_port:6379 #主节点端口
master_link_status:up #与主节点连接状态,up为正常
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:43
slave_priority:100
slave_read_only:1
connected_slaves:0 #连接从节点个数
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
- 数据同步
# 主节点写入数据
[root@localhost config]# redis-cli
127.0.0.1:6379> set hello world
OK
127.0.0.1:6379> exit
#从节点查看数据
[root@localhost config]# redis-cli -p 6380
127.0.0.1:6380> get hello
"world"
# 从节点设置了只读,set将会报错
127.0.0.1:6380> set hello java
(error) READONLY you con`t write against a read only slave.
127.0.0.1:6379> exit
- 查看6379日志(主节点)
[root@localhost config]# cd ../data
[root@localhost data]# ll
total 32
-rw-r--r-- 1 carlosfu staff 1.9K 10 30 23:02 6379.log
-rw-r--r-- 1 carlosfu staff 2.1K 10 30 23:02 6380.log
-rw-r--r-- 1 carlosfu staff 18B 10 30 23:02 dump-6379.rdb
-rw-r--r-- 1 carlosfu staff 18B 10 30 23:02 dump-6380.rdb
[root@localhost data]# cat 6379.log
...
# 连接从节点
77051:M 30 Oct 23:02:31.398 * Slave 127.0.0.1:6380 asks for synchronization
# 全量复制请求
77051:M 30 Oct 23:02:31.398 * Full resync requested by slave 127.0.0.1:6380
# 准备通过 bgsave 创建一个 RDB 以便于进行同步
77051:M 30 Oct 23:02:31.398 * Starting BGSAVE for SYNC with target: disk
# 执行 bgsave 创建 RDB
77051:M 30 Oct 23:02:31.398 * Backgrounp saving started by pid 77083
# DB 落盘到硬盘中
77083:M 30 Oct 23:02:31.398 * DB saved on disk
# bgsave 生成 RDB 文件成功
77051:M 30 Oct 23:02:31.417 * Backgrounp saving terminated with success
# 从节点同步成功
77051:M 30 Oct 23:02:31.417 * Synchronization with slave 127.0.0.1:6379 succeeded
...
- 查看6380日志(从节点)
[root@localhost data]# cat 6380.log
...
# 连接主节点
77080:S 30 Oct 23:02:31.396 * Connecting to MASTER 127.0.0.1:6379
# 主从复制已经开始
77080:S 30 Oct 23:02:31.397 * MASTER < - > SLAVE sync started
# 用于同步触发事件的非阻塞连接
77080:S 30 Oct 23:02:31.396 * Non blocking connect for SYNC fired the event
# 主节点ping恢复,复制继续
77080:S 30 Oct 23:02:31.396 * Master replied to PING, replication can continue...
# 部分重新同步不可能(没有缓存的主控)
77080:S 30 Oct 23:02:31.396 * Partial resynchronization not possible (no cached master)
# 从主机完全恢复(345dda992e5064bc80e01f96ea90f729b722b2ea是Redis节点的run_id)
77080:S 30 Oct 23:02:31.399 * Full resync from master: 345dda992e5064bc80e01f96ea90f729b722b2ea:1
# 从主机接收18字节(18字节是RDB文件)
77080:S 30 Oct 23:02:31.417 * MASTER < - > SLAVE sync: receiving 18 bytes from master
# 刷新旧数据
77080:S 30 Oct 23:02:31.417 * MASTER < - > SLAVE sync: Flushing old data
# 加载数据到内存中
77080:S 30 Oct 23:02:31.417 * MASTER < - > SLAVE sync: Loading DB in memory
# 成功完成复制
77080:S 30 Oct 23:02:31.417 * MASTER < - > SLAVE sync: Finished with success
# 查看服务信息
[root@localhost data]# redis-cli info
# Server
...
run_id:345dda992e5064bc80e01f96ea90f729b722b2ea
...
- 取消复制:从节点取消复制后变为主节点,重新连接复制,从节点的数据将会被清除
# 取消6380的复制
[root@localhost data]# redis-cli -p 6380
127.0.0.1:6380> slaveof no one
OK
127.0.0.1:6380> info replication
# Replication
role:master #节点角色
connected_slaves:0 #连接从节点个数
master_repl_offset:549
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6380> exit
# 在6379里写入数据
[root@localhost data]# redis-cli -p
127.0.0.1:6379> info replication
# Replication
role:master #节点角色
connected_slaves:0 #连接从节点个数
master_repl_offset:577
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:576
127.0.0.1:6379> mset a b c d f g h
OK
127.0.0.1:6379> dbsize
(integer) 5
127.0.0.1:6379> exit
[root@localhost data]# redis-cli -p 6380
127.0.0.1:6380> dbsize
(integer) 1
# 清除数据
127.0.0.1:6380> flushall
OK
# 写入不同的数据
127.0.0.1:6380> set abc6380 hello
OK
# 重新连接6379进行复制
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
# 原来的数据被清除了
127.0.0.1:6380> get abc6380
(nil)
127.0.0.1:6380> exit