有多个redis服务器,只有一个主节点(Master),其余均为从节点(Slave),只有主节点可以进行写操作,从节点只能进行读操作.数据的复制是单向的,从节点中的内容是由主节点中复制过来的(直接复制/间接复制).
一个主节点可以有多个从节点(也可以没有),一个从节点只能有一个主节点
使用Redis主从复制的原因主要是单台Redis节点存在以下的局限性:
Redis虽然读写的速度都很快,单节点的Redis能够支撑**每秒请求数(QPS)**大概在5w左右,如果上千万的用户访问,Redis就承载不了,成为了高并发的瓶颈。
单节点的Redis不能保证高可用,当Redis因为某些原因意外宕机时,会导致缓存不可用
CPU的利用率上,单台Redis实例只能利用单个核心,这单个核心在面临海量数据的存取和管理工作时压力会非常大。
若启动一个Slave机器进程,则它会向Master机器发送一个“sync command”命令,请求同步连接。
无论是第一次连接还是重新连接,Master机器都会启动一个后台进程,将数据快照保存到数据文件中(执行rdb操作),同时Master还会记录修改数据的所有命令并缓存在数据文件中。
后台进程完成缓存操作之后,Maste机器就会向Slave机器发送数据文件,Slave端机器将数据文件保存到硬盘上,然后将其加载到内存中,接着Master机器就会将修改数据的所有操作一并发送给Slave端机器。若Slave出现故障导致宕机,则恢复正常后会自动重新连接。
Master机器收到Slave端机器的连接后,将其完整的数据文件发送给Slave端机器,如果Mater同时收到多个Slave发来的同步请求,则Master会在后台启动一个进程以保存数据文件,然后将其发送给所有的Slave端机器,确保所有的Slave端机器都正常。
经过之前的学习,我们发现,实际上最关键的还是主节点,因为一旦主节点出现问题,那么整个主从系统将无法写入,因此,我们得想一个办法,处理一下主节点故障的情况。实际上我们可以参考Spring的服务治理模式,比如Nacos和Eureka,所有的服务都会被实时监控,那么只要出现问题,肯定是可以及时发现的,并且能够采取响应的补救措施,这就是我们即将介绍的哨兵:
哨兵 (也是一个Redis服务器)会对所有的节点进行监控,如果发现主节点出现问题,那么会立即让从节点进行投票,选举一个新的主节点出来,这样就不会由于主节点的故障导致整个系统不可写(注意要实现这样的功能最小的系统必须是一主一从,再小的话就没有意义了)
那么怎么启动一个哨兵呢?我们只需要稍微修改一下配置文件(conf文件)即可,修改:
sentinel monitor name ip port number
其他配置都是次要的,我们都采用默认配置.
其中第一个和第二个是固定,第三个是为监控对象名称,随意,后面就是主节点的相关信息,包括IP地址和端口,最后的一个数字的意思是当有number个哨兵判断主节点挂掉后,我们认为主节点真的挂掉了,一般number是要比哨兵数量少的,因为哨兵也可能挂掉.如果number等于哨兵数量,如果哨兵挂掉了一个,那么就永远判断不出主节点是否挂了.
哨兵模式启动后,会自动监控主节点,然后还会显示那些节点是作为从节点存在的。如果主节点挂了,刚开始从节点还会正常报错,不会直接重新进行选举而是继续尝试重连(因为有可能只是网络小卡一下,没必要这么敏感),但是哨兵发现,经过一段时间之后,依然无法连接,那么就会开始进行重新选举,从还运行良好的从节点中选出新的主节点,并且之前的主节点会变成新的主节点的从节点.
那么,这个选举规则是怎样的呢?是在所有的从节点中随机选取还是遵循某种规则呢?
首先会根据优先级进行选择,可以在配置文件中进行配置,添加replica-priority配置项(默认是100),越小表示优先级越高。
如果优先级一样,那就选择偏移量最大的
要是还选不出来,那就选择runid(启动时随机生成的)最小的。
如果我们服务器的内存不够用了,但是现在我们的Redis又需要继续存储内容,那么这个时候就可以利用集群来实现扩容。
因为单机的内存容量最大就那么多,已经没办法再继续扩展了,但是现在又需要存储更多的内容,这时我们就可以让N台机器上的Redis来分别存储各个部分的数据(每个Redis可以存储1/N的数据量),这样就实现了容量的横向扩展。同时每台Redis还可以配一个从节点,这样就可以更好地保证数据的安全性。
数据分区:数据分区(或称数据分片)是集群最核心的功能。
高可用:集群支持主从复制和主节点的自动故障转移(与哨兵类似);当任一节点发生故障时,集群仍然可以对外提供服务。
那么问题来,现在用户来了一个写入的请求,数据该写到哪个节点上呢?我们来研究一下集群的机制:
首先,一个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节点中。