用 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 协议》,转载必须注明作者和本文链接
focus
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!