redis主从
redis主从的运行机制:
-
当一个 master 实例和一个 slave 实例连接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave ,包括客户端的写入、key 的过期或被逐出等等。
-
当 master 和 slave 之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave 重新连接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开连接期间内丢失的命令流。
-
当无法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到 slave 。
-
正常情况下,一个全量重同步要求在磁盘上创建一个 RDB 文件,然后将它从磁盘加载进内存,然后 slave以此进行数据同步。
如果磁盘性能很低的话,这对 master 是一个压力很大的操作。Redis 2.8.18 是第一个支持无磁盘复制的版本。在此设置中,子进程直接发送 RDB 文件给 slave,无需使用磁盘作为中间储存介质。
redis主从复制的特点
- Redis 使用异步复制,slave 和 master 之间异步地确认处理的数据量
- slave 可以接受其他 slave 的连接
- Redis 复制在 master 侧是非阻塞的
- 复制在 slave 侧大部分也是非阻塞的。当 slave 进行初次同步时,它可以使用旧数据集处理查询请求,假设你在 redis.conf 中配置了让 Redis 这样做的话。否则,你可以配置如果复制流断开, Redis slave 会返回一个 error 给客户端。但是,在初次同步之后,旧数据集必须被删除,同时加载新的数据集。 slave 在这个短暂的时间窗口内(如果数据集很大,会持续较长时间),会阻塞到来的连接请求。自 Redis 4.0 开始,可以配置 Redis 使删除旧数据集的操作在另一个不同的线程中进行,但是,加载新数据集的操作依然需要在主线程中进行并且会阻塞 slave 。
- 当 master 关闭持久化时,不能保证数据的安全性,不要这么做
redis的主从配置较为简单,只需要在slave中添加主机配置即可,如下通过3个实例来搭建redis的主从环境
三台redis主机信息:
- **master: ** 172.18.0.9:6379
- **slave1:**172.18.0.10:6379
- **slave2:**172.18.0.11:6379
# 分别在主机slave1与slave2的redis配置文件中添加配置
replicaof 172.18.0.9 6379
masterauth "123456"
使用docker-compose启动redis主从程序
# redis容器
redis-master:
image: gongxulei/redis:5.0
container_name: my-app-redis-master
stdin_open: true
tty: true
privileged: true
restart: always
environment:
TZ: "Asia/Shanghai"
LANG: "C.UTF-8"
ports:
- "6390:6379"
volumes:
- "/Users/gongxulei/docker/redis/master/conf:/usr/local/redis/conf"
- "/Users/gongxulei/docker/redis/master/logs:/usr/local/redis/logs"
- "/Users/gongxulei/docker/redis/master/db:/usr/local/redis/db"
command: ["/root/redis_start.sh"]
networks:
default:
ipv4_address: 172.18.0.9
# redis-slave1容器
redis-slave1:
image: gongxulei/redis:5.0
container_name: my-app-redis-slave1
stdin_open: true
tty: true
privileged: true
restart: always
depends_on:
- redis-master
environment:
TZ: "Asia/Shanghai"
LANG: "C.UTF-8"
links:
- "redis-master"
ports:
- "6391:6379"
volumes:
- "/Users/gongxulei/docker/redis/slave1/conf:/usr/local/redis/conf"
- "/Users/gongxulei/docker/redis/slave1/logs:/usr/local/redis/logs"
- "/Users/gongxulei/docker/redis/slave1/db:/usr/local/redis/db"
command: ["/root/redis_start.sh"]
networks:
default:
ipv4_address: 172.18.0.10
# redis-slave1容器
redis-slave2:
image: gongxulei/redis:5.0
container_name: my-app-redis-slave2
stdin_open: true
tty: true
privileged: true
restart: always
depends_on:
- redis-master
environment:
TZ: "Asia/Shanghai"
LANG: "C.UTF-8"
links:
- "redis-master"
ports:
- "6392:6379"
volumes:
- "/Users/gongxulei/docker/redis/slave2/conf:/usr/local/redis/conf"
- "/Users/gongxulei/docker/redis/slave2/logs:/usr/local/redis/logs"
- "/Users/gongxulei/docker/redis/slave2/db:/usr/local/redis/db"
command: ["/root/redis_start.sh"]
networks:
default:
ipv4_address: 172.18.0.11
查询主从信息:可以看到两台slave主机已处于在线状态
master:0>info replication
"# Replication
role:master
connected_slaves:2
slave0:ip=172.18.0.10,port=6379,state=online,offset=668175,lag=1
slave1:ip=172.18.0.11,port=6379,state=online,offset=668175,lag=1
master_replid:86d7b43cfbbea36962cf5a9e6b580d164031d848
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:668583
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:668583
redis主从并不是一种高可用方案,如果master挂了之后如何自动切换slave为master这种高可用方法需要用到redis Sentinel技术