Redis Cluster Cron调度

news/2025/1/15 20:04:20/

返回目录

说明

  1. clusterCron 每秒执行10次
  2. clusterCron 内置了一个iteration计数器。每一次运行clusterCron,iteration都加1。当 iteration % 10 == 0的时候,就会随机选取一个节点,给它发送PING。而由于clusterCron每秒执行10次,所以实际上每秒才会PING一次随机节点。

过程

++iteration		/* 每次运行clusterCron都加一 */
if 配置的cluster-announce-hostname发生了变化:更新myself的hostname
计算handshakeTimeout = max(cluster-node-timeout, 3000)
statsPfailNodes = 0	 /* 重新计算timeout的node数 */
遍历cluster节点字典中的每个node:对于node的inbound link和outbound link:1. 检查它们的发送buffer能否收缩,从而节省内存2. 如果配置的cluster-link-sendbuf-limit != 0,检查它们的发送buffer(可能经过1的收缩)是否超过了限制,若是则释放掉相应的link3. 更新统计它们对内存的使用量跳过myself跳过处于NOADDR的node  /* 没有地址,没法建立连接 */if node处于PFAIL状态:++statsPfailNodes  /* 计算timeout节点数 */if node处于handshake && (当前时间 - node的创建时间)> handshakeTimeout:删除node	/* 规定时间内没有完成handshake,则认为它是未知的节点 */检查node是否disconnected,若是,则重建连接在连接创建成功之后:	/* 这里是异步执行的 */if node处于MEET状态:		/* 我们需要MEET它 */向它发送MEET消息else:向它发送PING消息清除node的MEET标记/* 每秒随机选取一个节点,给它发PING */
if iteration % 10 == 0:	/* 每秒clusterCron调度10次,每10次发一次PING */从cluster节点字典中随机选取5个node,它们满足以下条件:1. 已连接上(有outbound link)2. pingSent == 0 (没有在等待PONG)3. 不是myself4. 没有处于handshake再从这5个node中,选取pongReceived最小的node	/* 最久没收到PONG的node*/if 这样的node存在:给它发送PING消息/* 检查节点是否timeout,顺便为migrate收集信息 */
orphanedMasters = 0	 /* 统计orphaned master数 */
maxSlaves = 0	/* 统计单个节点拥有的最大slave数 */
thisSlaves = 0	/* 如果myself是master,表示拥有的slave数;如果myself是slave,表示它的master所拥有的slave数 */
遍历cluster节点字典的每个node:跳过myself跳过没有地址(NOADDR)的node跳过处于handshake的node/* 检查node是否为orphaned master,主要是先收集信息 */if myself是slave && node是master && node没有FAIL:okSlaves = node上没有处于FAIL的slave数/* node是orphaned master的条件:1. slots > 02. 当前没有正常运作的slave3. 带有MIGRATE_TO标记:曾经有至少一个slave,或者被它failover的master曾经拥有slave */if okSlaves == 0 && node的slots > 0 && node有MIGRATE_TO标记:++orphanedMastersmaxSlaves = max(okSlaves, maxSlaves)if node是myself的master:thisSlaves = okSlaves/* 如果超过 cluster-node-timeout/2 都没有收到来自node的数据,有可能只是连接出了问题,尝试重连 */pingDelay = 当前时间 - node的pingSentdataDelay = 当前时间 - node的dataReceivedif node的link存在 &&		/* 存在连接的才需要检查 */当前时间 - link的创建时间 > cluser-node-timeout && /* 还没有重连 */node的pingSent > 0 &&	/* 已经对node发出了PING */pingDelay > cluster-node-timeout/2 &&	/* 超时没有收到PONG */dataDelay > cluster-node-timeout/2:	/* 超时没有收到其他数据 */释放掉link,下次会自动重连(参考上面的逻辑)/* 检查是否需要PING一下node,以保证cluster信息的有效性 */if node的link存在 &&node的pingSent == 0 &&	/* 没有在等待PONG *//* 太久没PING,需要PING一下node */当前时间 - node的pongReceived > cluster-node-timeout/2: 给node发送PING消息if 我们是node的master,而它对我们请求了manual failover:给node发送PING消息/* 如果timeout了,就改变node的状态 */if node的pingSent > 0:	/* 正在等待PONG *//* 加载大量数据时,PONG有可能会延时,所以如果能收到数据,也能说明node还活着 */nodeDelay = min(pingDelay, dataDelay)	/* 最近一次收到的数据间隔 */if nodeDelay > cluster-node-timeout &&	/* node真的timeout了 */node没有处于PFAIL或FAIL:把node设置成timeout(PFAIL状态)/* 检查是否可以复制master */
if myself是slave && master有地址了 && 还没开始复制master:更新master的IP和port,开始复制/* 检查manual failover是否已经timeout */
if manual failover已经timeout:重置manual failover的状态if myself是slave:处理 Manual Failover	/* 在Failover章节叙述 */处理 Slave Failover		/* 在Failover章节叙述 *//* 检查我们是否需要migrate到orphaned master */if orphanedMasters > 0 &&	/* 存在orphaned master *//* 我们的master拥有最多冗余的slave,所以我们可以分离出来,成为其中一个orphaned master的slave */maxSlaves >= 2 && thisSlaves == maxSlaves &&cluster-allow-replica-migration:	/* 配置允许我们这么做 *//* Step 1: 检查cluster的状态 */if 我们认为当前cluster处于FAIL:跳过migration/* Step 2: 检查我们的master是否拥有多余的slave */if 我们的master拥有的正常slave数 < cluster-migration-barrier:跳过migration	/* 不能少于配置要求的最少slave数,才能做 *//* Step 3:查找orphaned master */target = null遍历cluster节点字典中的每个node:okSlaves = 0isOrphaned = 1/* 必须是正常工作,没有slave的master,而且带有MIGRATE_TO标记(含义参考上面) */if node是slave || node处于FAIL || node没有MIGRATE_TO标记):isOrphaned = 0	if node是master:okSlaves = node拥有的没有处于FAIL的slave数if okSlaves > 0:isOrphaned = 0if isOrphaned:if target == null &&  /* 只查找第一个符合要求的node */node的slots > 0: /* 没有slots的master不需要slave */target = nodeif node的orphanedTime == 0: /* 跟踪记录开始时间 */设置为当前时间else:重置node的orphanedTime为0if okSlaves == maxSlaves:	/* 我们的master拥有最多的slaves */minID = 从node的slaves中查找出最小的IDif myself的ID < minID:candidate = myself	/* 我们当选了 *//* Step 4: 执行migration */			if target != null &&	/* 找到了orphaned master */candidate == myself &&	/* 我们当选了 *//* 需要保持orphaned一段时间,如果期间发生failover,有可能使得slave和master之间的关系发生变化 */当前时间 - target的orphanedTime > 5000ms: 把target设置为我们的新master/* 结束本轮调度前,保存cluster的变化 */
if cluster信息发生了变化 || 我们认为cluster处于FAIL状态:更新nodes.conf文件	

http://www.ppmy.cn/news/1135297.html

相关文章

Stable Diffusion云服务器部署完整版教程

Stable Diffusion云服务器部署完整版教程 2023年07月04日 22:30 3607浏览 18喜欢 22评论 <span class"bili-avatar-icon bili-avatar-right-icon "></span> </div>薯片_AI 粉丝&#xff1a; 1513 文章&#xff1a; 1 设置分组取消关注 已关注 …

(一) 使用 Hugo 搭建个人博客保姆级教程(下篇)

关于博客建站简介,请参考上篇 (一) 使用 Hugo 搭建个人博客保姆级教程(上篇) (一)Hugo 安装 Hugo在多个操作系统下的安装 准备工作 安装golang 安装hugo之前,先安装好golang,推荐安装最新版本。Windows 用户强烈建议使用 Scoop 安装(关于 Scoop 安装及使用可参考 Sc…

(高阶) Redis 7 第18讲 RedLock 分布式锁

🌹 以下分享 RedLock 分布式锁,如有问题请指教。🌹🌹 如你对技术也感兴趣,欢迎交流。🌹🌹🌹 如有对阁下帮助,请👍点赞💖收藏🐱‍🏍分享😀 问题 分布式锁问题从(高阶) Redis 7 第17讲 分布式锁 实战篇_PJ码匠人的博客-CSDN博客 这篇文章来看,…

侯捷 C++ STL标准库和泛型编程 —— 8 适配器

8 适配器 适配器 Adapter 只是一个小变化&#xff0c;比如改个接口&#xff0c;函数名称等等其出现在三个地方&#xff1a;仿函数适配器&#xff0c;迭代器适配器&#xff0c;容器适配器可以使用继承 / 复合的两种方式实现&#xff0c;STL中都用复合 其思想就是将该记的东西记…

JS中的 typeof 针对各种类型的返回值 以及typeof历史遗留问题

JS中的 typeof 针对各种类型的返回值 typeof 运算符返回一个字符串&#xff0c;表示操作数的类型。 下表总结了 typeof 可能的返回值 类型结果Undefined"undefined"Null"object"&#xff08;原因&#xff09;Boolean"boolean"Number"numbe…

第10章 MySQL(一)

10.1 谈谈MySQL的架构 难度:★★ 重点:★ 白话解析 要想彻底的理解MySQL,它的架构一定要先弄清楚,当Java程序员通过JDBC或者Mybatis去执行一条SQL的时候,到底经历了什么。下边先看一幅图: 户端:Java程序员通过JDBC或者Mybatis去拿MySQL的驱动程序,实际上就是拿客户端。…

[Spring] Spring5——IOC 简介(二)

目录 六、工厂 Bean&#xff08;Factory&#xff09; 1、普通 bean 2、工厂 bean 3、示例 七、Bean 的作用域 1、单例和多例 2、如何设置为单实例或多实例 八、Bean 的生命周期 1、生命周期 2、生命周期示例 3、Bean 的后置处理器 4、后置处理器示例 九、XML 的自…

什么是博弈论?

什么是博弈&#xff1f;字面描述中&#xff0c;博弈由两个字构成&#xff1a;博 和 弈。博弈是一种双方&#xff08;多方&#xff09;的对抗&#xff08;比赛&#xff09;&#xff0c;对抗总是在一定的规则下进行&#xff0c;参与者必然会考虑应用相应的策略&#xff08;计谋&a…