Redis——主从复制

Redis主从复制原理

在 Redis 复制的基础上,使用和配置主从复制很是简单,能使得从 Redis 服务器(下文称 slave)能精确得复制主 Redis 服务器(下文称 master)的内容。每次当 slave 和 master 之间的链接断开时, slave 会自动重连到 master 上,而且不管这期间 master 发生了什么, slave 都将尝试让自身成为 master 的精确副本。web

这个系统的运行依靠三个主要的机制:redis

  • 当一个 master 实例和一个 slave 实例链接正常时, master 会发送一连串的命令流来保持对 slave 的更新,以便于将自身数据集的改变复制给 slave , :包括客户端的写入、key 的过时或被逐出等等。vim

  • 当 master 和 slave 之间的链接断开以后,由于网络问题、或者是主从意识到链接超时, slave 从新链接上 master 并会尝试进行部分重同步:这意味着它会尝试只获取在断开链接期间内丢失的命令流。服务器

  • 当没法进行部分重同步时, slave 会请求进行全量重同步。这会涉及到一个更复杂的过程,例如 master 须要建立全部数据的快照,将之发送给 slave ,以后在数据集更改时持续发送命令流到 slave 。网络

Redis使用默认的异步复制,其特色是低延迟和高性能,是绝大多数 Redis 用例的天然复制模式。可是,从 Redis 服务器会异步地确认其从主 Redis 服务器周期接收到的数据量。异步

Redis 复制功能是如何工做的

每个 Redis master 都有一个 replication ID :这是一个较大的伪随机字符串,标记了一个给定的数据集。每一个 master 也持有一个偏移量,master 将本身产生的复制流发送给 slave 时,发送多少个字节的数据,自身的偏移量就会增长多少,目的是当有新的操做修改本身的数据集时,它能够以此更新 slave 的状态。复制偏移量即便在没有一个 slave 链接到 master 时,也会自增,因此基本上每一对给定的tcp

Replication ID, offset

都会标识一个 master 数据集的确切版本。svg

当 slave 链接到 master 时,它们使用 PSYNC 命令来发送它们记录的旧的 master replication ID 和它们至今为止处理的偏移量。经过这种方式, master 可以仅发送 slave 所需的增量部分。可是若是 master 的缓冲区中没有足够的命令积压缓冲记录,或者若是 slave 引用了再也不知道的历史记录(replication ID),则会转而进行一个全量重同步:在这种状况下, slave 会获得一个完整的数据集副本,从头开始。性能

下面是一个全量同步的工做细节测试

master 开启一个后台保存进程,以便于生产一个 RDB 文件。同时它开始缓冲全部从客户端接收到的新的写入命令。当后台保存完成时, master 将数据集文件传输给 slave, slave将之保存在磁盘上,而后加载文件到内存。再而后 master 会发送全部缓冲的命令发给 slave。这个过程以指令流的形式完成而且和 Redis 协议自己的格式相同。

以前说过,当主从之间的链接由于一些缘由崩溃以后, slave 可以自动重连。若是 master 收到了多个 slave 要求同步的请求,它会执行一个单独的后台保存,以便于为多个 slave 服务。

正常状况下,一个全量重同步要求在磁盘上建立一个 RDB 文件,而后将它从磁盘加载进内存,而后 slave以此进行数据同步。

若是磁盘性能很低的话,这对 master 是一个压力很大的操做。Redis 2.8.18 是第一个支持无磁盘复制的版本。在此设置中,子进程直接发送 RDB 文件给 slave,无需使用磁盘做为中间储存介质。

实现主从复制

实验环境

两台rhel7.3的虚拟机

安装redis

1 官网下载redis的源码压缩包:redis-5.0.3.tar.gz

2 解压缩:tar zxf redis-5.0.3.tar.gz

3 安装依赖,并进行编译:

yum install -y gcc

[root@server1 ~]# cd redis-5.0.3/
[root@server1 redis-5.0.3]# ls
00-RELEASENOTES  COPYING  Makefile   redis.conf       runtest-sentinel  tests
BUGS             deps     MANIFESTO  runtest          sentinel.conf     utils
CONTRIBUTING     INSTALL  README.md  runtest-cluster  src
[root@server1 redis-5.0.3]# make

4 编译完成后,进入/root/redis-5.0.3/utils,这里有一个redis的安装脚本,进行安装

[root@server1 utils]#  ./install_server.sh

5 开启redis服务,能够看到默认开启6379端口。注意redis是使用脚本开启的,这是由于安装脚本里指定的,咱们也能够修改。

[root@server1 utils]# /etc/init.d/redis_6379 start
[root@server1 utils]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:6379            0.0.0.0:*               LISTEN

6 在server2(172.25.10.2 )上做以上一样的操做。

7 这里咱们将server1这台redis设置为slave,因此须要修改redis配置文件。

vim /etc/redis/6379.conf 
在第287行,写入你的master,代表从172.25.10.2 上复制同步数据
replicaof 172.25.10.2 6379

8 重启server1的redis服务。

/etc/init.d/redis_6379 restart

9 测试,主从复制是否生效。

[root@server1 utils]# redis-cli 
127.0.0.1:6379> info [section]

...
role:slave
master_host:172.25.10.2
master_port:6379
master_link_status:up
...

能够看到在server1上链接redis服务器,进行info查看时,显示了相关的master信息

在server2,设置kv字符串值
[root@server2 ~]# redis-cli 
127.0.0.1:6379> set name mac
OK
127.0.0.1:6379> get name
"mac"
127.0.0.1:6379> 
在server1查看是否同步:
[root@server1 utils]# redis-cli 
127.0.0.1:6379> get name
"mac"

注意:主从复制是经过rdb复制的,至于复制频率,能够在redis的配置文件中设置。