一、redis主从概念
1.1 redis主从基础
1.redis主从本身是异步的,从库不会阻塞主库的任何操作
2.redis一个主库可以有多个从库。从库也可以有从库
3.redis通过replication ID 和offset确定同步位置
4.redis从库默认为readonly
5.redis是内存数据库,所有数据都放在内存中,数据量不会像一把关系型数据库一样那么大,所以拉取基线数据较简单
1.2 主从同步原理
从服务器向主服务器发送PSYNC命令(redis2.8以前只有sync,sync会阻塞主库),PSYNC的目的是发送老主库的replication ID和从库最新offset位置
主库接受到psync后会出现2种情况
第一种继续传递数据,主库判断从库给予replication ID为主库replication ID,且从库的offset在主库复制积压缓冲区中,主库直接传递复制积压缓冲区中offset以后的数据给从库
第二种重新初始化并传递数据(resynchronization),主库判断从库给予replication ID不为主库replication ID,或者从库的offset已经不在主库复制积压缓冲区中
主服务器执行BGSAVE命令,生成RDB文件,并在复制挤压缓冲区中记录从bgsave开始的所有写命令
主服务器BGSAVE执行完后,将RDB发送给从服务器,从服务器载入RDB文件,将自己的状态更新至主服务器的BGSAVE时的状态
主服务器将缓冲区的写命令发送给从服务器,从服务器执行写命令,将从服务器更新为主服务器的当前态
1.3 diskless sync
正常来说,resynchronization需要主库将当前态dump到rdb磁盘文件,传递给从库服务器,从库在reload这个rdb文件。如果磁盘效率较低的情况下,rdb文件生成时间可能会非常长,会导致主库性能下降。
redis提供了diskless同步,rdb文件不落地,直接传递给从库reload。
repl-diskless-sync参数控制是否开启diskless同步。
二、搭建1主2从的redis主从架构
2.1 搭建主从步骤
搭建步骤很简单
1.配置conf文件
最重要的是在从库conf中配置replicaof $MASTER_IP $MASTER_PORT
2.启动主从实例
2.2 配置conf文件
主库6390端口:
cat /usr/local/redis-5.0.3/redis6390.conf
bind 127.0.0.1 #监听ip,redis对外服务的ip
port 6390 #指定redis的端口
daemonize yes #允许redis实例后台运行,启动redis时就可以不用加&了
masterauth 123456 #从库连接主库时需要主库requirepass的密码用以登陆。主库可以不需要设置
requirepass 123456 #当前redis实例的密码
appendonly no #是否开启AOF,no表示不开启
logfile "/usr/local/redis-5.0.3/redis6390.log" #日志路径
从库6391端口:
[root@lzl redis-5.0.3]# cat redis6391.conf
bind 127.0.0.1
port 6391
daemonize yes
masterauth 123456
requirepass 123456
appendonly no
logfile "/usr/local/redis-5.0.3/redis6391.log"
replicaof 127.0.0.1 6390 #当前redis实例的主库地址
从库6392端口:
[root@lzl redis-5.0.3]# cat redis6392.conf
bind 127.0.0.1
port 6392
daemonize yes
masterauth 123456
requirepass 123456
appendonly no
logfile "/usr/local/redis-5.0.3/redis6392.log"
replicaof 127.0.0.1 6390
2.3 启动主从实例
redis-server /usr/local/redis-5.0.3/redis6390.conf
redis-server /usr/local/redis-5.0.3/redis6391.conf
redis-server /usr/local/redis-5.0.3/redis6392.conf
2.4 主从复制验证
info replication可以看到redis主从配置信息,延时情况
role可以查看当前实例的角色信息
[root@lzl redis-5.0.3]# redis-cli -h 127.0.0.1 -p 6390 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6390> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6391,state=online,offset=2082,lag=1
slave1:ip=127.0.0.1,port=6392,state=online,offset=2082,lag=0
master_replid:3b1cb211b6b0fff1a9cf150ac427a0d8d804c6cd
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:2082
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:2082
测试同步
#主库set一个新key
127.0.0.1:6390> set lzl 1
OK
127.0.0.1:6390> get lzl
"1"
#备库get该key
127.0.0.1:6391> get lzl
"1" #key已同步到备库
127.0.0.1:6391> set test 1
(error) READONLY You can't write against a read only replica.
2.5 从库只读
replica-read-only
从redis2.6开始,从库默认都是只读的。通过设置replica-read-only控制从库是否只读,动态参数。
127.0.0.1:6391> config set replica-read-only no
OK
127.0.0.1:6391> set lzl 1
OK
参考资料:
https://redis.io/topics/replication
《redis设计与实现》