主从复制的定义

主从复制:主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master主服务器以写为主,Slave从服务器以读为主。如下图:

在这里插入图片描述


主从复制的优缺点

两个优势:

  • 读写分离

如果只有一台服务器,读和写操作都在一台服务器上进行,这台服务器的压力就会很大。而使用主从复制可以达到读写分离效果,写操作都在master主服务器进行,写操作进行完成之后,把内容复制到它的从服务器去;读操作都在slave从服务器进行。

  • 容灾快速恢复

如果主服务器中进行写操作之后,复制到了从服务器(从服务器一般有多台),如果第一台从服务器在读的过程中突然挂掉,就会切换到另外一台从服务器进行读操作,此即为容灾快速恢复。

一个缺陷:

主从复制存在的缺点是复制延时:
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。


注意:

“领导多了,员工不知道听谁的。”—因此:主从一般都为一主多从。主服务器只能有一个。


搭建主从复制环境(一主两从)

在一台服务器上,搭建一主两从的模拟环境。(因为是一台服务器,因此要保证三者的端口不同)操作如下:

①为了方便先创建一个myRedis的文件夹
在这里插入图片描述
②复制Redis.conf文件到此文件夹
在这里插入图片描述

③配置一主两从,创建三个配置文件:redis6379.conf、redis6380.conf、redis6381.conf(保证三者端口不同)
在这里插入图片描述

由于redis配置文件redis.conf中有公共配置部分,所以在三个新建的配置文件中只需要引入公共配置(使用include),其他不同的地方(进程号pid、端口号、rdb持久化文件的名称)进行单独配置。
在这里插入图片描述
配置完成后 :wq 保存退出
在这里插入图片描述

⑤启动三台Redis服务器
在这里插入图片描述
注意:如果本机的redis服务器也为6379,就会和此处用于演示的redis6379服务器冲突,可以使用kill命令先关闭原有的reis进程,再开启我们自定义的myredis目录下用于演示的redis6379服务器。


  • redis-server redis6379.conf:根据配置文件启动相应的Redis服务器。 如下图:
    在这里插入图片描述

  • redis-cli -p 端口号:通过端口号连接Redis服务器。 如下图:
    在这里插入图片描述

  • info replication:打印主从复制的相关信息,用来查看运行情况。 如下图:
    注意:此命令需要连上Redis后使用。 如下图:
    在这里插入图片描述

目前虽然启动了三台Redis服务器,但此时并没有主从的效果。想要实现主从,还需要在目标从服务器使用slaveof命令

  • slaveof ip port :使当前服务器临时成为某个实例的从服务器(重启Redis服务器后会失效)

要想设置6379为主机,6380、6381为从机:需要在从机上使用slaveof命令进行配置。(小弟认大哥的过程,小弟要主动)

在这里插入图片描述

一主两从效果搭建完成。如下图:
在这里插入图片描述

搭建好一主二从之后,进行测试。

在主服务器中进行写操作,可以在从服务器中成功读到。如下图:

在这里插入图片描述


特殊情形一:
一主(6379)二从(6380、6381)。如果某一台从服务器(如6380)挂掉(可以使用shutdown命令)了,还会剩一个6381从服务器正常运行。此时在主服务器(6379)中添加数据,如下图:
在这里插入图片描述
正常运行的从服务器(6381)可以读到数据,如下图:
在这里插入图片描述
若此时把挂掉的6380从服务器再次启动起来(redis-server redis6380.conf),连接Redis(redis-cli -p 6380),查看6380Redis服务器状态信息(info replication)会出现什么效果?如下图:
在这里插入图片描述
此时若想让6380Redis服务器继续做6379主服务器的从服务器可以使用slaveof命令,如下图:
在这里插入图片描述
此时查看6380Redis服务器中的key值信息,如下图:
在这里插入图片描述

也就是说,如果主机在从服务器挂掉之后修改了数据,再把挂掉的服务器 **作为主机的从服务器重新启动** ,主机中的最新的数据依然会被复制到从服务器中去。

就好比 “只要小弟(从服务器)做大哥(主服务器)的人,大哥有什么资源都会毫无保留地和小弟分享。”


特殊情形二:
如果6379主服务器挂掉了,如下图:
在这里插入图片描述
查看从服务器(6380、6381)的状态信息(info replication),如下图:
在这里插入图片描述
在这里插入图片描述
查看后发现,从服务器的角色依然为从服务器,并没有“篡位”变为主服务器。
再次对6379主服务器进行启动(redis-server redis6379.conf),连接(redis-cli -p 6379),查看信息(info replication)。如下图:
在这里插入图片描述
在这里插入图片描述

也就是说,即使6379主服务器挂掉了,6380和6381两个服务器的角色依然是从服务器,而且认为主服务器依然为6379。(大哥永远是大哥)

就好比,“即使大哥挂掉了,小弟依然把他当作大哥,并不会上位。


主从复制原理

在这里插入图片描述

  • 从服务器连接到主服务器后会向主服务器发送一个sync命令,告诉主服务器现在可以做数据同步了
  • 主服务器接收到从服务器发送来的消息后,把当前主服务器中的数据先进行持久化(把数据放到rdb文件中去),把rdb文件发送给从服务器,从服务器拿到rdb文件之后进行数据读取,完成复制
  • 每次主服务器进行写操作之后,主动和从服务器进行数据同步

从服务器只在第一次主动请求同步,其他大部分过程都是主服务器发起的。

了解两个概念:

  • 全量复制: 从服务器在接收到数据库文件数据后,将其存盘**并加载到内存中。
  • 增量复制: 主服务器继续将 新的所有收集到的修改命令 依次传给slave,完成同步。

只要是重新连接主服务器,就会自动进行一次完全同步(全量复制)


薪火相传

上一个Slave从服务器可以是下一个slave从服务器的主服务器。Slave从服务器同样可以接收其他slave从服务器(可以是多个)的连接和同步请求,那么该slave从服务器作为了链条中下一个slave从服务器的主服务器,可以有效减轻master的写压力,去中心化降低风险。类似数据结构中的树形结构,等级森严。

这种薪火相传的模式肯定会有一个缺点:如果某一个从服务器挂掉了,它下面的服务器就不能再进行数据同步。


反客为主

当一个主服务器挂掉后,手动把后面的从服务器升级为主服务器,其后面的从服务器不用做任何修改。

效果演示:
①让6379主服务器挂掉(shutdown)
在这里插入图片描述

②查看6381从服务器的状态信息(info replication)
在这里插入图片描述

③手动让6380从服务器“上位”,变为主服务器(slaveof no one)
在这里插入图片描述
④查看6380服务器的状态信息
在这里插入图片描述
slaveof no one:把从机变为主机

此即为反客为主

这种 反客为主模式会有一个缺点:需要手动完成。 如果服务器大半夜挂掉了,还需要我们大半夜爬起来去手动切换,很不方便。

能不能让这个过程自动完成?实现主服务器如果挂掉了,从服务器立马挑起大梁,晋升为主服务器。

此即为接下来要介绍的哨兵模式实现的效果。


哨兵模式

在这里插入图片描述

哨兵模式即为反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。

演示:
调整到一主二从状态进行演示:
在这里插入图片描述

配置哨兵(sentinel):
在这里插入图片描述

  • ①在自定义的/myredis目录下新建sentinel.conf文件,名字绝不能错
    在这里插入图片描述

  • ②写入内容:
    sentinel monitor mymaster 服务器ip 端口号 1:其中mymaster为监控对象起的服务器名称;最后的参数表示至少有多少个哨兵同意迁移的数量。(此处最后参数为1则表示只要有一个哨兵同意就能进行切换)
    在这里插入图片描述

  • ③启动哨兵(redis-sentinel /myredis/sentinel.conf )
    在这里插入图片描述
    最终切换为主机的服务器是从被监视服务器的从服务器中取。

  • ④关闭6379主服务器
    在这里插入图片描述

  • ⑤哨兵监控窗口信息如下:
    在这里插入图片描述

  • ⑥查看6381服务器状态
    在这里插入图片描述
    此时连接的从服务器(connected_slaves)只有一个6380,因为6379还没有重新启动。

  • ⑦查看6380服务器状态
    在这里插入图片描述

  • ⑧重启6379服务器,并查看状态信息
    在这里插入图片描述
    在这里插入图片描述


总结哨兵模式:
在这里插入图片描述

①选择优先级高的从服务器作为主服务器(值越小,优先级越高)

在redis的配置文件中都会有相应的优先级(默认值为100),如下图:在这里插入图片描述

②如果优先级相同,选择偏移量最大的从服务器作为主服务器

即两台从服务器中,和主机的的数据同步程度最高的从服务器,偏移量较大,更适合转化为主服务器。

③如果优先级和偏移量都相同,选择runid最小的从服务器作为主服务器

每个redis实例启动后都会随机生成一个40位的runid。选择runid最小的


JedisSentinelPool连接池

想使用Java代码实现主从操作特点,可以使用JedisSentinelPool连接池。

JedisSentinelPool模板如下:

    private static JedisSentinelPool jedisSentinelPool = null;

    public static Jedis getJedisFromSentinel() {
        if (jedisSentinelPool == null) {
            Set<String> sentinelSet = new HashSet<>();
            sentinelSet.add("47.116.4.200:26379");  //服务器ip:哨兵端口号(默认26379)

            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(10); //最大可用连接数
            jedisPoolConfig.setMaxIdle(5); //最大闲置连接数
            jedisPoolConfig.setMinIdle(5); //最小闲置连接数
            jedisPoolConfig.setBlockWhenExhausted(true); //连接耗尽是否等待
            jedisPoolConfig.setMaxWaitMillis(2000); //等待时间
            jedisPoolConfig.setTestOnBorrow(true); //取连接的时候进行一下测试 ping pong

            jedisSentinelPool = new JedisSentinelPool("mymaster", sentinelSet, jedisPoolConfig, "******");  //如果Redis服务器配置了密码,需要在最后一个参数写入密码
            return jedisSentinelPool.getResource();
        } else {
            return jedisSentinelPool.getResource();
        }
    }

注意:想要使用如上哨兵模式连接池,需要在服务器上配置26379端口的安全组或使用宝塔面板放行26379端口、还要确保哨兵服务器的正常运行状态。否则上述程序无法运行成功。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐