基于Zookeeper实现调度任务选主及心跳检测
在微服务架构中使用ZooKeeper实现分布式任务调度选主,并确保Follower节点能实时监控Master状态并及时触发重新选举,可以通过以下方案实现:
一、核心设计原理
1. ZooKeeper特性利用
| ZK功能 | 在选主中的应用 |
|---|---|
| 临时节点(EPHEMERAL) | Master创建临时节点,会话断开时节点自动删除(相当于心跳检测) |
| Watcher机制 | Follower监听Master节点变化 |
| 顺序节点(SEQUENTIAL) | 实现公平的选举排序 |
2. 状态监控流程
participant Master
participant Follower1
participant Follower2
participant ZK
Master->>ZK: 创建/master_leader临时节点
Follower1->>ZK: 监听/master_leader节点
Follower2->>ZK: 监听/master_leader节点
Note over Master: 正常工作时定期刷新会话
Master--xZK: 会话超时断开
ZK->>Follower1: 触发NodeDeleted事件
ZK->>Follower2: 触发NodeDeleted事件
Follower1->>ZK: 尝试创建新/master_leader节点
ZK-->>Follower1: 创建成功,成为新Master
Follower2->>ZK: 监听新的/master_leader节点
二、完整实现方案
1. 添加依赖
<!-- Curator客户端(推荐) -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>5.5.0</version>
</dependency>
2. 选主服务实现
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListener;
import org.apache.curator.framework.state.ConnectionState;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class ZkLeaderElection {
private final CuratorFramework zkClient;
private LeaderSelector leaderSelector;
private volatile boolean isLeader = false;
public ZkLeaderElection(CuratorFramework zkClient) {
this.zkClient = zkClient;
}
@PostConstruct
public void init() throws Exception {
leaderSelector = new LeaderSelector(zkClient, "/scheduler/leader",
new LeaderSelectorListener() {
@Override
public void takeLeadership(CuratorFramework client) throws Exception {
// 成为Leader后的逻辑
isLeader = true;
System.out.println("当前节点当选为Leader");
try {
while (true) {
Thread.sleep(1000); // 模拟持续工作
}
} finally {
isLeader = false;
}
}
@Override
public void stateChanged(CuratorFramework client, ConnectionState newState) {
// 连接状态变化处理
if (newState == ConnectionState.LOST) {
isLeader = false;
}
}
});
leaderSelector.autoRequeue(); // 自动重新参与选举
leaderSelector.start();
}
@PreDestroy
public void shutdown() {
if (leaderSelector != null) {
leaderSelector.close();
}
}
public boolean isLeader() {
return isLeader;
}
}
3. 增强型状态监控(生产级)
// 在init()方法中添加以下逻辑
public void init() throws Exception {
// ...原有代码...
// 添加额外的心跳检测
zkClient.getConnectionStateListenable().addListener((client, newState) -> {
if (newState == ConnectionState.RECONNECTED) {
// 重连后强制检查Leader状态
checkLeaderStatus();
}
});
// 启动定时检查任务
Executors.newSingleThreadScheduledExecutor()
.scheduleAtFixedRate(this::checkLeaderStatus, 0, 5, TimeUnit.SECONDS);
}
private void checkLeaderStatus() {
try {
if (zkClient.checkExists().forPath("/scheduler/leader") == null) {
System.out.println("Leader节点不存在,触发重新选举");
}
} catch (Exception e) {
e.printStackTrace();
}
}
三、关键优化点
1. 双Watch机制
// 除了LeaderSelector内置监听,额外添加数据Watch
zkClient.getData().usingWatcher((Watcher) event -> {
if (event.getType() == Watcher.Event.EventType.NodeDeleted) {
System.out.println("Leader节点被删除,立即触发选举");
}
}).forPath("/scheduler/leader");
2. 选举性能优化
| 参数 | 推荐值 | 说明 |
|---|---|---|
| sessionTimeoutMs | 10000-15000ms | 根据网络状况调整 |
| leaderSelector.autoRequeue() | 必须启用 | 保证节点退出后重新参与选举 |
| retryPolicy.baseSleepTimeMs | 1000ms | 首次重试延迟 |
3. 故障转移时间控制
// 在ZK配置中优化
@Bean
public CuratorFramework zkClient() {
return CuratorFrameworkFactory.builder()
.connectString("zk1:2181,zk2:2181,zk3:2181")
.sessionTimeoutMs(15000) // 会话超时
.connectionTimeoutMs(5000) // 连接超时
.retryPolicy(new ExponentialBackoffRetry(1000, 3)) // 重试策略
.build();
}
故障转移时间 = 会话超时时间 + 选举时间(通常可控制在15秒内)
四、生产环境建议
1. 监控指标
| 指标名称 | 采集方式 | 告警阈值 |
|---|---|---|
| ZK选举次数 | ZK的leader_election计数器 |
1小时内>5次 |
| Master存活时间 | 节点数据中的时间戳 | 连续3次<30秒 |
| 节点连接状态 | Curator事件监听 | RECONNECTED状态持续>1分钟 |
2. 部署架构
[微服务实例1] [微服务实例2] [微服务实例3]
| | |
+------------+------------+
|
[ZooKeeper Ensemble]
|
[监控系统(Prometheus + Grafana)]
3. 异常场景处理
- 脑裂防护:启用ZK的
quorum机制(至少3节点) - 网络分区:配合Sidecar代理检测真实网络状态
- 持久化问题:定期备份
/scheduler节点数据
五、与Spring Cloud集成
1. 健康检查端点
@RestController
@RequestMapping("/leader")
public class LeaderController {
@Autowired
private ZkLeaderElection election;
@GetMapping("/status")
public ResponseEntity<String> status() {
return election.isLeader()
? ResponseEntity.ok("MASTER")
: ResponseEntity.ok("FOLLOWER");
}
}
2. 调度任务示例
@Scheduled(fixedRate = 5000)
public void scheduledTask() {
if (zkLeaderElection.isLeader()) {
System.out.println("只有Master执行的任务...");
}
}
六、对比Redisson方案
| 维度 | ZooKeeper方案 | Redisson方案 |
|---|---|---|
| 实时性 | 秒级(依赖ZK会话超时) | 秒级(依赖Redis TTL) |
| 可靠性 | 高(CP系统) | 中(依赖Redis持久化) |
| 运维复杂度 | 较高(需维护ZK集群) | 较低(复用Redis) |
| 适用场景 | 强一致性要求的系统 | 允许短暂脑裂的场景 |
通过以上方案,你的微服务可以实现:
- 秒级故障检测:基于ZK临时节点和Watcher机制
- 自动快速选主:利用Curator的选举算法
- 生产级可靠性:多重监控和防护机制
- 无缝集成Spring生态:与
@Scheduled等组件协同工作
基于Zookeeper实现调度任务选主及心跳检测的更多相关文章
- kazoo python zookeeper 选主
本文讲述基于zookeeper选主与故障切换的方法.我们的例子使用的是python. 使用的库是kazoo,安装方式 pip install kazoo 应用场景: 多个实例部署,但不是" ...
- 简述 zookeeper 基于 Zab 协议实现选主及事务提交
Zab 协议:zookeeper 基于 Paxos 协议的改进协议 zookeeper atomic broadcast 原子广播协议. zookeeper 基于 Zab 协议实现选主及事务提交. 一 ...
- 聊聊Zookeeper应用场景、架构设计、选主机制
Zookeeper作为一个分布式协调系统提供了一项基本服务:分布式锁服务,分布式锁是分布式协调技术实现的核心内容.像配置管理.任务分发.组服务.分布式消息队列.分布式通知/协调等,这些应用实际上都是基 ...
- zookeeper curator选主(Leader)
在分布式系统设计中,选主是一个常见的场景.选主是一个这样的过程,通过选主,主节点被选择出来控制其他节点或者是分配任务. 选主算法要满足的几个特征: 1)各个节点均衡的获得成为主节点的权利,一旦主节点被 ...
- Zookeeper笔记之使用zk实现集群选主
一.需求 在主从结构的集群中,我们假设硬件机器是很脆弱的,随时可能会宕机,当master挂掉之后需要从slave中选出一个节点作为新的master,使用zookeeper可以很简单的实现集群选主功能. ...
- 基于zookeeper+mesos+marathon的docker集群管理平台
参考文档: mesos:http://mesos.apache.org/ mesosphere社区版:https://github.com/mesosphere/open-docs mesospher ...
- 基于zookeeper的activemq的主从集群配置
项目,要用到消息队列,这里采用activemq,相对使用简单点.这里重点是环境部署. 0. 服务器环境 RedHat710.90.7.210.90.7.1010.90.2.102 1. 下载安装zoo ...
- ActiveMQ 基于zookeeper的主从(levelDB Master/Slave)搭建以及Spring-boot下使用
0:说明 ActiveMQ 5.9.0新推出的主从实现,基于zookeeper来选举出一个master,其他节点自动作为slave实时同步消息.因为有实时同步数据的slave的存在,master不用担 ...
- 基于zookeeper实现分布式配置中心(一)
最近在学习zookeeper,发现zk真的是一个优秀的中间件.在分布式环境下,可以高效解决数据管理问题.在学习的过程中,要深入zk的工作原理,并根据其特性做一些简单的分布式环境下数据管理工具.本文首先 ...
- Etcd 使用场景:通过分布式锁思路实现自动选主
分布式锁?选主? 分布式锁可以保证当有多台实例同时竞争一把锁时,只有一个人会成功,其他的都是失败.诸如共享资源修改.幂等.频控等场景都可以通过分布式锁来实现. 还有一种场景,也可以通过分布式锁来实现, ...
随机推荐
- .NET 9 new features-C#13新的锁类型和语义
C# 13 中,引入了新的锁类型和语义,主要用于增强多线程编程中的同步机制. 传统上,C# 使用 lock 关键字与任意的 object 实例配合,实现线程间的互斥访问.然而,这种方式可能存在性能瓶颈 ...
- 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
1 大人,时代变了! 赶快把自有业务的本地AI"模型"训练起来! 1.1 背景 目前AI已经大行其道,chatGPT.DeepSeek等如雨后春笋般涌现出来,笔者做为一个守旧派 ...
- Redis 持久化原理分析和使用建议
作者:来自 vivo 互联网存储团队- Qiu Xu 本文主要介绍了 Redis 提供的三大持久化机制,即 AOF 日志.RDB 快照以及混合持久化机制. 一.Redis 为什么需要进行持久化 Re ...
- stay:将代码翻译为Gif动图,妈妈再也不用担心我调试找不到bug了
本文首发于微信公众号:呼哧好大枫.原作者与本文作者是同一人. 平常在做算法题或者是 debug 的时候很需要一款能够实时地将代码执行逻辑和数据以图形化的形式渲染出来的工具.之前尝试了几款(visual ...
- 史陶比尔Stabli机器人维修小细节
在工业自动化领域,史陶比尔机器人以其卓越的性能和可靠性而著称.然而,即使是尖端的设备,也难免会遇到Stabli机械手故障和问题.对于机器人维护和修理,每一个小细节都显得至关重要. 一.观察 首先,我们 ...
- Arduino语法--数据类型
Arduino与C语言类似,有多种数据类型.数据类型在数据结构中的定义是一个值的集合,以及定义在这个值集上的一组操作,各种数据类型需要在特定的地方使用.一般来说,变量的数据类型决定了如何将代表这些值的 ...
- 探秘Transformer系列之(5)--- 训练&推理
探秘Transformer系列之(5)--- 训练&推理 0x00 概述 Transformer训练的目的是通过对输入源序列和模型输出序列的学习,来拟合真正的目标序列.推理的目的则是仅通过输入 ...
- axios 发送 form-data 请求和 x-www-form-urlencoded请求以及相关问题
问题 not supported { "msg": "Content type 'multipart/form-data;boundary=--------------- ...
- 幻兽帕鲁/Palworld/支持网络联机 v0.1.5.1
游戏介绍 在广阔的世界中收集神奇的生物"帕鲁",派他们进行战斗.建造.做农活,工业生产等,这是一款支持多人游戏模式的全新开放世界生存制作游戏. 注意事项 先启动STEAM客户端,在 ...
- nacos(七): gateway(单体)
这篇文章将从gateway的搭建.自动路由匹配.路由数组.跨域和路由过滤器五个方面对gateway项目展开讨论. 1.gateway的搭建 gateway的项目基本的搭建过程与消费者的搭建过程基本一致 ...