Redis第三篇——集群

Posted 搬砖小松鼠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis第三篇——集群相关的知识,希望对你有一定的参考价值。

前面两篇已经对Redis的基本数据类型,Redis的过期和持久化策略进行了讲述,但即便拥有了恢复的能力,而在故障恢复的这段时间服务也是完全挂掉不可用,对于一个高可用的系统来说,这是完全不能接受的,因此我们要告别单兵作战时代,看看Redis是如何进行集群作战的

主从复制

Redis主从关系是通过slaveof命令来实现的,调用slaveof命令的服务器为从服务器,命令的参数是主服务器。从服务器通过复制来从主服务器获取数据,复制包含两个过程:同步(sync)和命令传播两个操作:

同步:将从服务器的数据状态更新为主服务器当前所处的状态

命令传播:当主服务器数据被修改时,将修改的命令应用到从服务器

同步

同步分为完全同步和部分同步,完全同步通过sync命令完成,部分同步通过psync来实现

sync

(1)从服务器向主服务器发送sync命令

(2)主服务器执行bgsave命令,生成rdb文件,并使用一个缓冲区开始记录这一期间执行的写命令

(3)主服务将rdb文件发给从服务器,从服务器对数据进行载入

(4)主服务器将期间的命令发给重服务器,从服务器执行这些命令

后面就开始进入命令传播阶段

psync

从服务器有两种情况,一种是新服务器上线初始复制和断线重连,对于初次上线sync可以很好的工作,但是对于断线重连,可能大部分数据都是相同,此时在用RDB文件进行重建效率比较低。而psync命令具有完成重同步部分重同步的功能。

完全重同步的过程和sync一样,部分重同步需要以下三个部分的信息:主服务器和从服务器的复制偏移量,主服务器的复制积压缓冲区、服务器运行ID(run ID)。

复制积压缓冲区是一个FIFO的队列,默认大小为1MB,用于保存最近的命令,当从服务器断线重连之后,可以比较自己的偏移量在缓存区中还有没有,如果没有需要完全重同步,如果从服务器保存的主服务器的run Id和当前主服务器不一致,也需要完全重同步(说明主服务器已经变了)

主从复制虽然完成了主从服务器之间的最终一致性,但没有自动故障转移和恢复的能力

Sentinel

Sentinel(哨兵)是Redis高可用的解决方案,由一个或多个Sentinel实例组成Sentinel系统来监控集群的状态,并自动完成故障转移、选主和恢复的能力。

Sentinel是一种特殊的Redis实例,其上不存储数据,只存储节点状态信息,并与其它Sentinel节点进行通信和数据交换。

Sentinel会与每个主/从服务器建立命令连接和订阅连接。会每10s通过命令连接向主/从服务器发送info命令,来从主服务器获取主服务器和其从服务器的状态,也会从从服务器获取其主服务器的状态信息。

Sentinel会以每2秒依次对从服务器hello频道发送命令信息,监控统一服务器的其它Sentinel因为也订阅了这个服务器的hello频道,所以也会收到该消息(基于这样订阅关系,来更新对监控服务器的认知),同时Sentinel也会对消息来源没有建立的Sentinel建立命令连接,这样所有监控统一服务器的Sentinel之间也能够相互通信了。

主观下线

当一个Sentinel与监控主服务器实例不可达时,就会将该master标记为主观下线

客观下线

向其他Sentinel询问,当从其他Sentinel收到足够数量的下线信息后,会判定服务器为客观下线,并开始故障转移操作

(1)发送命令询问其他Sentinel是否同意下线

(2)其他Sentinel响应

(3)统计下线响应数量,并标记客观下线

选举领头Sentinel

按照先到先得,最新得到半数票的Sentinel单选

故障转移

领头Sentinel对已下线的主服务器开启故障转移

(1)从从服务器选出一个作为主服务器(挑出的服务器执行slave no one)

(2)让已下线的主服务器的所有其他从服务器从属于该服务器

(3)已下线主服务器从属于该服务器

Redis-Cluster

Redis集群是Redis提供的分布式数据库方案,集群通过分片的方式来进行数据共享,并提供复制和故障转移功能。

一个Redis集群由多个节点组成,Redis-Cluster是将数据按照槽来分别分给各个主节点,每个主节点负责一部分的槽,同时保存一份全局其它主节点负责的槽信息来实现请求转发,每个主节点可配置若干从节点来对数据进行复制和故障时选主,Redis集群整个数据库被分为16384(2的14次方)个槽。

重新分片

Redis集群的重分片由redis-trib实现,就是将待迁移的槽中的所有节点都迁移到新节点上的过程。在迁移过程中如果访问的节点被迁移了,会向客户端发送ack错误来指引到新节点进行访问, ACK错误是一次性的,下次对该槽的请求仍然会到原节点(因为可能槽中的其它数据还未迁移),而Move指令是永久的(客户端后续的请求都不会到原节点了)

故障检测

集群各节点之间通过ping,pong消息来相互传播服务器的状态。如果一个集群里面,有半数的节点都认为负责处理槽的主节点疑似下线,那么这个主节点将被标记为已下线

故障转移

(1)故障主节点有一个从节点被选中

(2)被选中节点执行slave no one,成为主节点

(3)将原主节点的指派改为自己

(4)广播pong消息,让其他节点知道该节点已经成为主节点

(5)新的主节点处理请求

选主操作

每个故障主节点的从节点向集群中的其它节点广播获取支持,得到半数以上票的从节点当选

几种消息

meet消息:邀请接受者加入当前集群

ping消息:集群每个节点默认每隔一秒从已知节点随机五个进行ping,判断是否在线

pong消息:对ping的回应。还可以通过pong来广播让其他节点刷新对该节点的认知(如选主过程新的主节点)

fail消息:当主节点判断另外一个节点进入fail状态时会广播节点的fail消息

publish消息:执行pushlish命令

其中meet、ping和pong是使用Gossip协议来实现的(通过流言蜚语的扩散传播)

以上是关于Redis第三篇——集群的主要内容,如果未能解决你的问题,请参考以下文章

redis缓存

redis第三篇~redis的主从

脑裂以及Redis主从同步中的坑

redis 会丢数据吗

高级程序员必须精通的Redis,第三篇之——hash(散列)

ELK总结——第三篇Logstash监控Nginx日志存入redis,实现服务解耦