Redis分布式集群

Redis分布式集群,第1张

Redis分布式集群 主从同步

增量同步: Redis主节点会将自己存储在Buffer中的 *** 作指令异步同步给从库,从节点收到同步成功指令后会像主节点上报自己同步到文件偏移量。因为Redis主库的Buffer使用的是环形数组数据存储结构,如果Buffer满了会从数组的头部开始覆盖写入,如果主从延迟过大,就会存在Buffer中的写入速度大于同步速度而导致指令丢失的可能。快照同步: 为了解决增量同步主从延迟数据丢失的问题引入了快照同步方式,这个过程较消耗性能。当发现增量同步有丢失数据的风险时,主库会fork一个子进程对主库做一次当前内存快照备份发送给从库。从节点接收到主库的RDB备份后,释放掉当前所有的数据,让回放RDB文件。回放完成后通知主库再进行增量同步。在整个快照过程中主节点的Buffer还在不停的前移,如果复制回放rdb文件的时间比Buffer前移的更慢的话,就会导致在RDB同步的过程中Buffer中未同步的指令又被覆盖则rdb同步失败,这样就会导致主库再次进入快照过程中,将新的Rdb文件同步给从库。这样就陷入一个死循环中,我们在平时设计中要考虑到主从延迟导致的Buffer堆积空间大小,给定一个包含网络延迟导致的Buffer堆积的合理大小,做到不低估,不浪费。无盘复制: 我上面说到过一般为了提升主节点性能我们会将日志文件刷盘的 *** 作交给从库来 *** 作。所谓无盘复制就是主节点通过Socket将快照发生到从节点,主节点一边遍历内存一边发送RDB文件内容,从节点将收到的完整的RDB文件存储到磁盘,再进行回放。同步复制: Redis的主从复制大部分都是异步的,想要保证数据的强一致性,我们可以使用Redis提供的wait指令进行同步复制,假如将wait的等待时间设置为无限等待从库同步完成,那么当网络发生分区或者延迟较高的时候,就出现严重阻塞,影响Redis的可用性。

过期key的的主从同步:需要注意的一点是在中从同步过程中对于过期key处理是不同的。有一条中原则就是:过期key统一由主节点删除。主节点在删除一条key时会显示的向所有从节点发送一条del指令,从节点在自己的内存遇到过期key时只需要向客户端返回过期,不做删除动作,等待主节点同步del来删除。

Redis Sentinel 哨兵模式

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。

这里的哨兵有两个作用

通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。如果某个 redis 实例有故障,那么哨兵负责发送消息作为报警通知给管理员。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

用文字描述一下故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover *** 作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的。

哨兵核心知识:

哨兵至少需要 3 个实例,来保证自己的健壮性。哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。 RedisCluster 集群

在上面解决了集群的健壮性后,那么随之探索的就是数据的存储的性能上,在集群模式下都是通过全量数据冗余来保证数据的一致性与可用性,在空间上造成了巨大的浪费。这一节我们将介绍Redis的分布式集群存储方式RedisCluster,它的单个节点上不在是全量数据,而只含有整个集群的一份数据。这样既改善了存储空间浪费的问题,同时也增横向增加了Redis服务整体的吞吐性。RedisCluster将所有数据存储区域划分为16384(2的14次方)个slots(槽位),每个节点负责一部分槽位,槽位的信息存储于每个节点中。当客户端请求进来时候会拉去一份槽位信息列表缓存在本地,RedisCluster的每个节点会将集群的配置信息持久化到自己的配置文件中,所以需要引入一套可维护的配置文件管理方案,尽量做到自动化。

槽位算法: RedisCluster 默认会根据key使用crc32算法进行hash得到一个整数,然后用这个整数对16384取模定位key所在的槽位。它还运行用户在key字符串里面嵌入tag将key强制写入指定的槽位。迁移: 当有新的节点加入或者断开节点时,就会触发Redis槽位迁移。当一个槽位正在迁移时候在原节点的状态为migrating,在目标节点的状态为importing。原节点的单个key执行dump指令得到序列化内容,再向目标节点发送restore携带序列化内容作为参数的指令,目标节点接收到内容后反序列化复制到内存中,响应给原节点成功。原节点收到成功响应后把当前节点的key删掉就完成了节点数据迁移。这个过程是一个同步的 *** 作,在复制完成之前原节点时处于阻塞状态的,不会进入新的数据,直到原节点的key被删除完成。如果key内容过大就会导致迁移阻塞时间过长,出现卡顿现象,所以再次强调大key的危害。上面说完了在迁移过程中服务端的变化,现在我们来说一下槽位迁移对于客户端的变化:这时候新旧节点会同时存在部分key,客户端访问到旧节点,如果旧节点存在就正常处理返回。如果客户端访问的数据不在旧节点,它会向客户端发生一个重定向指令(-ASK targetNodeAddr),客户端收到重定向后,先去目标节点执行一个不带参数的asking指令,然后在目标节点执行 *** 作。因为在没有完全迁移完槽位目标节点还不归新节点管理,如果只适合直接发生 *** 作指令,目标节点会返回给客户端一个-MOVED重定向指令,让它去原节点执行,这样就出现了重定向循环。不带参的asking指令目的就是打开目标节点选项让它当做自己的槽位的请求来处理。通过上面的过程得知在迁移过程中,平时的一个指令需要三个ttl才能完成。跳转: 当RedisCluster发生槽位变化的数据迁移时,这时候客户端保存的槽位信息就和RedisCluster的槽位信息不一致,当客户端访问到错误的槽位时候,当前槽位会相应给客户端一个可能包含此数据的槽位信息,当客户端访问成功后更新本地槽位信息。容错: RedisCluster为每个主节点设置了若干从节点,主节点故障时,集群会主动提升某个从节点作为主节点,当无主节点时Redis整个不可用。也可以通过 cluster-require-full-coverage参数设置允许部分节点故障,其他节点依然可以对完提供服务。实际在异常无处不在生成环境中突然部分节点变得不可用,间隔一会又突然好了是很常见的时候,为了解决这问题我们也通过设置容忍最大离线时间(cluster-node-timeout)来避免,当超过这个最大超时时间则认为节点不可用。还有一个作为被乘数系数来放大超时时间的参数:cluster-slave-validity-factor,当值为0的时候是不能容忍异常短暂离线,系数越大相对越宽松。RedisCluster作为一个去中心化的中间件,一个节点认为某个节点离线,叫可能离线,当所有或者当大多数节点认为某节点离线才叫真正离线,此时集群会剔除此节点或者触发主从切换。它是用Gossip协议来广播自己的状态以及对整个集群变化的感知。比如一个节点发现某节点离线,它会将这个信息向整个集群广播,其他节点也会受到这个信息,如果收到信息的节点发现目标节点状态正常则不更新这条信息,并发送目标节点正常的消息给整个集群,就这样一个个节点的传播消息。当整个集群半数以上节点都持有某目标节点已离线的的信息时候才认为,某目标节点离线的这一事实,否则不予处理。


文章参考:点这里 哨兵 集群

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5713256.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存