用 docker 学习 redis 主从复制
本篇创建两个 docker 容器模拟两台 redis 机器,修改 redis 配置文件实现主从复制关系,通过查看日志了解建立主从的过程,最后介绍配置文件中复制相关的参数。
准备两个redis容器(一主一从)
1/Dockerfile
FROM centos:latest
RUN groupadd -r redis \
&& useradd -r -g redis redis
RUN yum -y update \
&& yum -y install epel-release \
&& yum -y install redis \
&& yum -y install net-tools
EXPOSE 6379
2/创建镜像
docker build -t redis:n1 .
[root@VM-0-8-centos docker]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
redis n1 1c45d8f479c4 5 minutes ago 570MB
centos latest 5d0da3dc9764 3 months ago 231MB
3/自定义网络
docker network create --subnet=172.10.0.0/16 mynetwork
[root@VM-0-8-centos docker]# docker network ls
NETWORK ID NAME DRIVER SCOPE
a97e473101f2 bridge bridge local
0cbd477b0468 host host local
60d857da579f mynetwork bridge local
8d749f5fca60 none null local
4/创建两个容器
docker run -itd --name redis-master --net mynetwork --ip 172.10.0.2 - p 6380:6379 redis:n1
docker run -itd --name redis-slave --net mynetwork --ip 172.10.0.3 -p 6381:6379 redis:n1
[root@VM-0-8-centos docker]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d4fce2508b76 redis:n1 "/bin/bash" 5 seconds ago Up 2 seconds 0.0.0.0:6381->6379/tcp redis-slave
a591743386ac redis:n1 "/bin/bash" 21 hours ago Up 21 hours 0.0.0.0:6380->6379/tcp redis-master
配置主从
1/进入主节点容器
docker exec -it redis-master bash
vi /etc/redis.conf
搜索 :/bind
:/requirepass
#bind 127.0.0.1
#yyp复制一行,修改为
bind 0.0.0.0
# requirepass foobared
requirepass mypassword
2/进入从节点容器
docker exec -it redis-slave bash
vi /etc/redis.conf
搜索 :/bind
:/repli
bind 0.0.0.0
# replicaof <masterip> <masterport>
#yyp复制一行,修改为
replicaof 172.10.0.2 6379
# masterauth <master-password>
masterauth mypassword
3/启动主从节点
redis-server /etc/redis.conf &
4/向主节点添加数据
[root@a591743386ac /]# redis-cli
127.0.0.1:6379> auth mypassword
OK
127.0.0.1:6379> set name xiaoming EX 3600
OK
127.0.0.1:6379> get name
"xiaoming"
5/从节点读取数据
[root@d4fce2508b76 /]# redis-cli
127.0.0.1:6379> get name
"xiaoming"
复制信息和复制过程
1/主节点查看复制信息(后补充内容,因此主从信息和上面的不同)
127.0.0.1:6379> info replication
# Replication
role:master
//从节点信息
connected_slaves:2
slave0:ip=172.10.0.2,port=6379,state=online,offset=770,lag=1
slave1:ip=172.10.0.4,port=6379,state=online,offset=770,lag=0
//Replication ID (当机器重启时会发生变化)
master_replid:34510d2665ac8d64e959da933005060a20f4f472
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:784//主节点的复制偏移量
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576//主节点的复制缓冲区大小
repl_backlog_first_byte_offset:1
repl_backlog_histlen:784
2/主节点查看建立主从关系的日志 /var/log/redis/redis.log
//172.10.0.2从节点请求复制
* Replica 172.10.0.2:6379 asks for synchronization
//部分复制请求没有被接收,原因:Replication ID没有匹配(这一般是主节点重启造成的)
* Partial resynchronization not accepted: Replication ID mismatch (Replica asked for '4697404d30eb268af88598711d067ef13bdf6ca4', my replication IDs are '494993f6f9e6f052410e9a3d028cc3227a858d8c' and '0000000000000000000000000000000000000000')
//启动BGSAVE程序(backgroud save)将当前数据快照保存到目标:磁盘
* Starting BGSAVE for SYNC with target: disk
//快照保存中,执行程序的pid为55
* Background saving started by pid 55
//已经保存到磁盘
* DB saved on disk
//此过程消耗的内存
* RDB: 0 MB of memory used by copy-on-write
//成功结束保存
* Background saving terminated with success
//同步成功
* Synchronization with replica 172.10.0.2:6379 succeeded
由上方信息可以看出,172.10.0.2:6379 请求复制,收到一个部分复制的请求发现 Replication ID
不匹配,然后开了一个 BGSAVE
(background save) 程序,将当前数据快照 Background
保存到磁盘,然后将 rdb
发送给 172.10.0.2:6379 (注意:此期间新写入的数据保存至复制缓冲区,因本示例并没有新写入,所以没有体现)
3/从节点建立主从的日志
//连接MASTER主节点
* Connecting to MASTER 172.10.0.5:6379
* MASTER <-> REPLICA sync started
* Non blocking connect for SYNC fired the event.
* Master replied to PING, replication can continue...
//尝试部分复制请求
* Trying a partial resynchronization (request 4697404d30eb268af88598711d067ef13bdf6ca4:1).
//从主节点全量复制(显然部分复制没有成功)
* Full resync from master: 34510d2665ac8d64e959da933005060a20f4f472:0
//丢弃先前缓存的主节点状态。
* Discarding previously cached master state.
//接收了175bytes的数据
* MASTER <-> REPLICA sync: receiving 175 bytes from master
//清除老数据(相当于 flushall)
* MASTER <-> REPLICA sync: Flushing old data
//将DB加载到内存(传输的是快照rdb文件)
* MASTER <-> REPLICA sync: Loading DB in memory
//成功结束
* MASTER <-> REPLICA sync: Finished with success
从节点的日志大概意思是,尝试部分复制 partial resynchronization
,发现主节点是新的节点,然后进行全量复制 Full resync
, 丢弃以前缓存的主状态,接收信息,清空老数据,加载到内存,复制完成。
redis.conf ---REPLICATION---
下的配置参数:
slave-serve-stale-data
stale 陈旧的
指定slave与master连接中断时的动作。默认为yes,表明slave会继续应答来自client的请求,但这些数据可能已经过期(因为连接中断导致无法从master同步)。若配置为no,则slave除正常应答”INFO”和”SLAVEOF”命令外,其余来自客户端的请求命令均会得到”SYNC with master in progress”的应答,直到该slave与master的连接重建成功或该slave被提升为master。
slave-read-only
指定slave是否只读,默认为yes。若配置为no,这表示slave是可写的,但写的内容在主从同步完成后会被删掉。
repl-disable-tcp-nodelay
指定向slave同步数据时,是否禁用socket的NO_DELAY选项,默认 yes。若配置为yes,则禁用NO_DELAY,则TCP协议栈会合并小包统一发送,这样可以减少主从节点间的包数量并节省带宽,但会增加数据同步到slave的时间。若配置为no,表明启用NO_DELAY,则TCP协议栈不会延迟小包的发送时机,这样数据同步的延时会减少,但需要更大的带宽。通常情况下,应该配置为no以降低同步延时,但在主从节点间网络负载已经很高的情况下,可以配置为yes。
slave-priority
指定slave的优先级,默认 100。在不只1个slave存在的部署环境下,当master宕机时,Redis Sentinel会将priority值最小的slave提升为master。需要注意的是,若该配置项为0,则对应的slave永远不会被Redis Sentinel自动提升为master。
本作品采用《CC 协议》,转载必须注明作者和本文链接