Redis与分布式(主从复制,哨兵模式,集群模式)

Redis与分布式


主从复制

Redis与分布式(主从复制,哨兵模式,集群模式)_第1张图片

基本概念

有多个redis服务器,只有一个主节点(Master),其余均为从节点(Slave),只有主节点可以进行写操作,从节点只能进行读操作.数据的复制是单向的,从节点中的内容是由主节点中复制过来的(直接复制/间接复制).

一个主节点可以有多个从节点(也可以没有),一个从节点只能有一个主节点

作用
  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
  • 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
  • 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
Redis为什么需要主从复制

使用Redis主从复制的原因主要是单台Redis节点存在以下的局限性:

  • Redis虽然读写的速度都很快,单节点的Redis能够支撑**每秒请求数(QPS)**大概在5w左右,如果上千万的用户访问,Redis就承载不了,成为了高并发的瓶颈。

  • 单节点的Redis不能保证高可用,当Redis因为某些原因意外宕机时,会导致缓存不可用

  • CPU的利用率上,单台Redis实例只能利用单个核心,这单个核心在面临海量数据的存取和管理工作时压力会非常大。

主从复制流程
  1. 若启动一个Slave机器进程,则它会向Master机器发送一个“sync command”命令,请求同步连接。

  2. 无论是第一次连接还是重新连接,Master机器都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作),同时Master还会记录修改数据的所有命令并缓存在数据文件中。

  3. 后台进程完成缓存操作之后,Maste机器就会向Slave机器发送数据文件,Slave端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着Master机器就会将修改数据的所有操作一并发送给Slave端机器。若Slave出现故障导致宕机,则恢复正常后会自动重新连接。

  4. Master机器收到Slave端机器的连接后,将其完整的数据文件发送给Slave端机器,如果Mater同时收到多个Slave发来的同步请求,则Master会在后台启动一个进程以保存数据文件,然后将其发送给所有的Slave端机器,确保所有的Slave端机器都正常。

哨兵模式

经过之前的学习,我们发现,实际上最关键的还是主节点,因为一旦主节点出现问题,那么整个主从系统将无法写入,因此,我们得想一个办法,处理一下主节点故障的情况。实际上我们可以参考Spring的服务治理模式,比如Nacos和Eureka,所有的服务都会被实时监控,那么只要出现问题,肯定是可以及时发现的,并且能够采取响应的补救措施,这就是我们即将介绍的哨兵:

Redis与分布式(主从复制,哨兵模式,集群模式)_第2张图片

哨兵 (也是一个Redis服务器)会对所有的节点进行监控,如果发现主节点出现问题,那么会立即让从节点进行投票,选举一个新的主节点出来,这样就不会由于主节点的故障导致整个系统不可写(注意要实现这样的功能最小的系统必须是一主一从,再小的话就没有意义了)

那么怎么启动一个哨兵呢?我们只需要稍微修改一下配置文件(conf文件)即可,修改:

sentinel monitor name ip port number

其他配置都是次要的,我们都采用默认配置.

其中第一个和第二个是固定,第三个是为监控对象名称,随意,后面就是主节点的相关信息,包括IP地址和端口,最后的一个数字的意思是当有number个哨兵判断主节点挂掉后,我们认为主节点真的挂掉了,一般number是要比哨兵数量少的,因为哨兵也可能挂掉.如果number等于哨兵数量,如果哨兵挂掉了一个,那么就永远判断不出主节点是否挂了.

哨兵模式启动后,会自动监控主节点,然后还会显示那些节点是作为从节点存在的。如果主节点挂了,刚开始从节点还会正常报错,不会直接重新进行选举而是继续尝试重连(因为有可能只是网络小卡一下,没必要这么敏感),但是哨兵发现,经过一段时间之后,依然无法连接,那么就会开始进行重新选举,从还运行良好的从节点中选出新的主节点,并且之前的主节点会变成新的主节点的从节点.

那么,这个选举规则是怎样的呢?是在所有的从节点中随机选取还是遵循某种规则呢?

  1. 首先会根据优先级进行选择,可以在配置文件中进行配置,添加replica-priority配置项(默认是100),越小表示优先级越高。

  2. 如果优先级一样,那就选择偏移量最大的

  3. 要是还选不出来,那就选择runid(启动时随机生成的)最小的。

集群模式

如果我们服务器的内存不够用了,但是现在我们的Redis又需要继续存储内容,那么这个时候就可以利用集群来实现扩容。

因为单机的内存容量最大就那么多,已经没办法再继续扩展了,但是现在又需要存储更多的内容,这时我们就可以让N台机器上的Redis来分别存储各个部分的数据(每个Redis可以存储1/N的数据量),这样就实现了容量的横向扩展。同时每台Redis还可以配一个从节点,这样就可以更好地保证数据的安全性。

Redis与分布式(主从复制,哨兵模式,集群模式)_第3张图片

集群的作用
  • 数据分区:数据分区(或称数据分片)是集群最核心的功能。

    • 集群将数据分散到多个节点,一方面突破了Redis单机内存大小的限制,存储容量大大增加;另一方面每个主节点都可以对外提供读服务和写服务,大大提高了集群的响应能力。
    • Redis单机内存大小受限问题,在介绍主从复制时有提及;例如,如果单机内存太大,bgsave和bgrewriteaof的fork操作可能导致主进程阻塞,主从环境下主机切换时可能导致从节点长时间无法提供服务,全量复制阶段主节点的复制缓冲区可能溢出。
  • 高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。

那么问题来,现在用户来了一个写入的请求,数据该写到哪个节点上呢?我们来研究一下集群的机制

首先,一个Redis集群包含16384个插槽,集群中的每个Redis 实例负责维护一部分插槽以及插槽所映射的键值数据,那么这个插槽是什么意思呢?

实际上,插槽就是键的Hash计算后的一个结果,注意这里出现了计算机网络中的CRC循环冗余校验,这里采用CRC16,能得到16个bit位的数据,也就是说算出来之后结果是0-65535之间,再进行取模,得到最终结果:

Redis key的路由计算公式
s l o t = C R C 16 ( k e y ) m o d    16384 slot = CRC16(key)\mod 16384 slot=CRC16(key)mod16384

结果的值是多少,就应该存放到对应维护的Redis下,比如Redis节点1负责0-25565的插槽,而这时客户端插入了一个新的数据a=10,a在Hash计算后结果为666,那么a就应该存放到1号Redis节点中。

你可能感兴趣的:(redis,分布式,数据库,java,微服务,缓存,spring,cloud)