Redis 多机服务
主从同步(复制)
主从同步是Redis高可用服务的基石,其将主要存储数据的服务器成为主服务器(master),把对主服务器进行复制的服务器成为从服务器(slave)。 并且从节点还可以是其他服务器的主节点,并且拥有属于自己的从节点
通过主从模式来进行读写的分离,主服务器进行写操作,然后将数据同步给从服务器,让从服务器来进行读操作,通过这种模式来分摊主服务器的压力。
Redis的复制功能主要分为同步(sync)与命令传播(command propagate) 两个操作
同步
同步操作用于将从服务器的数据库状态更新至主服务器当前的数据库状态。
在从服务器对主服务器进行复制之前,需要先将从服务器的数据库状态更新至主服务器的服务器状态
命令传播
命令传播操作用于在主服务器的数据库状态发生变化(执行写命令),导致主从服务器的数据库状态不一致时,让主从服务器的数据库重新回到一致状态。 当客户端对主服务器进行写操作后,此时主从服务器的数据库状态就会不一致。
为了能够再次让主从服务器的数据库状态恢复一致,此时主服务器会将同一命令发送给从服务器,当从服务器执行完改命令时,数据库状态再次恢复一致。
优缺点
优点
- 性能方面:可以实现读写的分离,由主服务器来进行写操作,并将写的结果同步至从服务器,由从服务器来进行读操作,这样就能将压力分摊到各个服务器上
- 高可用:当主服务器宕机之后,可以通过故障转移机制将从节点提升为主节点,快速的进行服务器的宕机恢复。
- 防止数据丢失:当主服务器的磁盘损坏或者数据丢失后,因为从服务器还保留相关的数据,不至于导致数据全部丢失
缺点
- 由于主从同步需要人工管理,主节点崩溃后需要人工进行从节点的提升才能恢复Redis的正常使用
从上面可以看到,主从同步并没有一个自动的管理机制,当出现主服务器宕机的情况,需要人工干预来进行恢复,但是如果主从服务器数量庞大,又或是因为高并发导致的大量崩溃,这时需要的时间和难度都是非常大的,于是Redis中又引入了哨兵模式(Sentinel) 来作为解决方案,将管理由人工转向哨兵,使得Redis具有自动容灾恢复的能力
哨兵
哨兵是Redis高可用性的解决方案,通过一个或者多个哨兵组成的哨兵系统,可以监控任意多个主服务器以及它们的从服务器。当某个被监视的主服务器进入下线状态时,哨兵就会自动将下线主服务器的某个从服务器升级为新的主服务器,然后由新的主服务器继续处理命令请求
总结下来就是哨兵模式可以用来监控主从同步服务器节点,并在主从服务器出现问题的时候实现自动容灾恢复
下线判断与选举
由于一个主服务器可能会同时被多个哨兵进行同时进行监控,所以当一个哨兵主观的将其判定为下线时,为了确保这个主服务器真的下线了,它会向同样监视这一主服务器的其他哨兵进行询问,看看它们是否也认为该服务器下线了,当积累到一定数量的下线判断时,此时就会客观认为主服务器下线,开始进行故障转移。
但是故障转移只能由一个哨兵来进行,所以此时所有监控该服务器的哨兵会进行协商,选举出一个领头哨兵来进行故障转移。
每一个哨兵都会向其他哨兵发送一个带有自己运行ID的命令,如果接收到该命令的哨兵还没有进行投票,就会将该ID设置为它的头领ID,并返回一个确认恢复。通过这种方法每一个哨兵都可以直到有多少个人为其投票,并选出一个票数最高的作为头领哨兵
故障转移
故障转移分为以下三个步骤
- 在已下线主服务器的从服务器中挑选一个出来作为新的主服务器
- 在已下线主服务器的从服务器改为复制新的主服务器
- 将已下线主服务器设置为新的主服务器的从服务器,当这个旧的主服务器重新上线时,他就会成为新的主服务器的从服务器
集群
集群(Cluster)是Redis多机运行中最完美的方案 ,它的出现甚至可以让我们抛弃掉主从同步和哨兵来实现Redis多机的运行。
集群是无代理模式去中心化的运行模式,客户端发送的绝大多数命令会直接交给相关节点执行,大部分情况下请求命令不需要转发,或者仅仅只需要转发一次就能完成请求和响应。所以集群中的单个节点的性能与单机Redis服务器的性能非常接近,并且通过水平拓展能够使得性能进行翻倍,所以集群的性能非常的高 由于主从同步只能有一个主节点,而集群可以拥有无数个主从节点,有着更强大的平行拓展能力。 所以在理论情况下,如果水平拓展一倍的主节点,相当于请求处理的性能也提高了一倍,也就是说通过平行拓展N倍的主从节点,就会比单机服务来说性能提升了N倍。
握手
每个节点其实就是运行在集群模式下的Redis服务器,而这些节点在一开始时都是互相独立的,它们都处于一个只包含自己的集群中,要组建一个真正可以工作的集群,我们就必须要将各个独立的节点通过握手的方式连接起来。
分片
集群通过分片的方式来保存数据库中的键值对。 集群的整个数据库被分为个16384个槽,并且将一个或者多个槽指派给某个节点,让这个节点来负责管理这个槽中的数据以及相关命令,通过这种方法就能很好的进行压力的分摊。
节点之间会互相转递指派槽的信息 对于发送来的命令,会通过其所在的槽来分配至对应的节点,如果分配错误,也会通过转向操作来转交给至正确的节点