一、什么是Redis主从复制

主从复制,当用户往Master端写入数据时,通过Redis Sync机制将数据文件发送至Slave,Slave也会执行相同的操作确保数据一致;且实现Redis的主从复制非常简单。

二、Redis主从复制原理

在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。

redis主从复制部署 redis主从复制实现_redis主从复制部署

如果Master和Slave之间的链接出现断连现象,Slave可以自动重连Master,但是在连接成功之后,一次完全同步将被自动执行。

如果Master同时收到多个 slave发来的同步连接命令,只会使用启动一个进程来写数据库镜像,然后发送给所有slave。

三、Redis主从复制特点

1、同一个Master可以拥有多个Slaves。

2、Master下的Slave还可以接受同一架构中其它slave的链接与同步请求,实现数据的级联复制,即Master->Slave->Slave模式;

3、Master以非阻塞的方式同步数据至slave,这将意味着Master会继续处理一个或多个slave的读写请求;

4、Slave端同步数据也可以修改为非阻塞是的方式,当slave在执行新的同步时,它仍可以用旧的数据信息来提供查询;否则,当slave与master失去联系时,slave会返回一个错误给客户端;

5、主从复制具有可扩展性,即多个slave专门提供只读查询与数据的冗余,Master端专门提供写操作;

6、通过配置禁用Master数据持久化机制,将其数据持久化操作交给Slaves完成,避免在Master中要有独立的进程来完成此操作。

四、Redis主从复制实现

1.在本地创建两个目录:RedisMaster、RedisSlave 。 分别存放Master服务和Slave服务。

2.修改Master服务的配置文件redis.conf(推荐使用文本编译器打开,例如:Notepad++

3.修改Slave服务的配置文件redis.conf:


redis主从复制部署 redis主从复制实现_Redis_02

4.开启主从服务, 我们先开启Master服务

redis主从复制部署 redis主从复制实现_主从复制_03

然后我们开启Slave服务:

当我们开启Slave服务时,Master服务的窗口会增加一些信息:

可以看到在Slave服务启动并连接到Master服务之后,它将主动发送一个SYNC命令,用来同步数据。Master先dump出rdb文件,然后将rdb文件全量传输给slave,然后Master把缓存的命令转发给Slave,初次同步完成。

第二次以及以后的同步实现是:Master将变量的快照直接实时依次发送给各个Slave。不管什么原因导致Slave和Master断开重连都会重复以上过程。Redis的主从复制是建立在内存快照的持久化基础上,只要有Slave就一定会有内存快照发生。虽然Redis宣称主从复制无阻塞,但由于Redis使用单线程服务,如果Master快照文件比较大,那么第一次全量传输会耗费比较长时间,且文件传输过程中Master可能无法提供服务,也就是说服务会中断。 

5.下面我们来写个控制台程序来试试读写分离:

using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace String
{
    class Program
    {
        static void Main(string[] args)
        {
            RedisClient Masterclient = new RedisClient("127.0.0.1", 6379);
            RedisClient Slaveclient = new RedisClient("127.0.0.1", 6379);
            Console.WriteLine("Master写入数据");
            string data = Console.ReadLine();
            Masterclient.Set<string>("data", data);
            string readmaster = Slaveclient.Get<string>("data");
            Console.WriteLine("Slave读取数据:"+readmaster);
            Console.ReadKey();
        }
    }
}

View Code

五、Redis主从复制存在的问题

在读《京东云实践:浅谈Redis主从复制》 时,看到一个问题:主从复制在遇到网络不稳定的情况下,Slave和Master断开(包括闪断)会导致Master需要将内存中的数据全部重新生成rdb文件(快照文件),然后传输给Slave。Slave接收完Master传递过来的rdb文件以后会将自身的内存清空,把rdb文件重新加载到内存中。这种方式效率比较低下,尤其是在数据量大的情况下,毕竟网络闪断未必丢数据或者说丢的数据只是少部分,但却要为此付出将整个内存数据都重新传输一次的代价。如果能够将闪断过程的更新数据传递给Slave,那么就不需要将Master内存中的所有数据都传递给Slave了。Redis作者在2.8中已经将这个部分复制的思路实现了。

六、Redis数据恢复

当Redis服务器挂掉以后,重启时将按以下优先级恢复数据到内存:

1.如果只配置了AOF,重启时加载AOF文件恢复数据。

2.如果同时配置了RBD和AOF,启动时只加载AOF文件恢复数据。

3.如果只配置了RDB,启动时将加载dump文件恢复数据。