Apache Druid 中的 ZooKeeper 集群状态管理:路径协议、领导者选举与 Segment 发布机制
发布时间:2026/9/23 2:11:49 作者:尧图编辑部 阅读量:1,286

数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载Apache Druid 使用 Apache ZooKeeper简称 ZK来管理集群的当前状态current cluster state包括 Coordinator/Overlord 的领导者选举、Historical 节点的 Segment 发布协议以及 Overlord 与 MiddleManager 之间的任务管理。本文基于 docs/design/zookeeper.md 展开并结合仓库源码如 ZkPathsConfig.java、CuratorDruidLeaderSelector.java、Announcer.java深入讲解其底层实现帮助你理解 Druid 各服务节点如何通过 ZK 协同工作、如何配置 ZK 路径以及在版本演进中 ZK 相关能力的迁移方向。ZooKeeper 在 Druid 中的角色定位Druid 的分布式架构由 Coordinator、Overlord、Broker、Historical、MiddleManager/Indexer 等角色组成。在这些节点之间ZooKeeper 承担的核心职责是管理集群的当前状态management of current cluster state具体表现为四类关键操作Coordinator 领导者选举leader electionHistorical 节点的 Segment publishing 协议segment 发布/宣告协议Overlord 领导者选举Overlord 与 MiddleManager 之间的任务管理task management。从源码结构看Druid 在server模块下组织了一整套 Curator 工具集来支撑上述能力CuratorModule.java 负责构建 CuratorFramework 客户端Announcer.java 负责向 ZK 发布/撤销临时节点DiscoveryModule.java 负责服务发现与领导者选择器装配。也就是说Druid 并没有直接使用 ZooKeeper 的原生 API而是统一通过 Apache Curator 这一高层客户端来访问 ZK。支持的 ZooKeeper 版本Apache Druid 支持 ZooKeeper3.5.x 及以上版本。有两个重要的版本演进需要特别注意自Apache Druid 0.22.0起移除了对 ZooKeeper 3.4.x 的支持自Apache Druid 31.0.0起移除了基于 Zookeeper 的 segment 加载ZK-based segment loading支持。第二条演进在源码中同样留有痕迹ZkCoordinator.java 的类注释明确标注了Deprecated并说明 Druid has already migrated to HTTP-based segment loading and will soon migrate to HTTP-based inventory view usingSegmentListerResourceZkPathsConfig.java 中的getLiveSegmentsPath()方法也被标记为Deprecated注释建议改用 HTTP-based segment discovery。这意味着新版 Druid 中 segment 的加载与发现正逐步从 ZK 迁移到 HTTP 通道SegmentListerResource但 ZK 在领导者选举与任务管理中的角色仍然保留。ZooKeeper 路径配置druid.zk.paths 系列参数Druid 在 ZK 上使用的一系列路径均可通过配置自定义核心配置类为 ZkPathsConfig.java。该类通过 JacksonJsonProperty绑定druid.zk.paths.*配置项默认以druid作为 base 根路径配置项默认值基于 basedruid用途druid.zk.paths.basedruid所有 ZK 路径的公共根前缀druid.zk.paths.propertiesPathdruid/properties节点属性properties发布路径druid.zk.paths.announcementsPathdruid/announcements服务节点如 Historical存在性宣告路径druid.zk.paths.liveSegmentsPathdruid/segments已废弃Historical 宣告其正在服务的 segment 列表druid.zk.paths.coordinatorPathdruid/coordinatorCoordinator 领导者选举路径druid.zk.paths.connectorPathdruid/connector连接器相关路径druid.zk.paths.overlordPathdruid/overlordOverlord 领导者选举路径druid.zk.paths.internalDiscoveryPathdruid/internal-discovery内部服务发现路径从 ZkPathsConfig.java 可以看到所有默认路径均由defaultPath(subPath)方法生成即ZKPaths.makePath(getBase(), subPath)等价于把 base 与子路径用/拼接。若某个路径显式配置则优先使用显式值否则回退到默认值。在仓库的示例配置中例如 common.runtime.properties典型的 ZK 配置片段如下druid.hostlocalhost druid.zk.service.hostlocalhost druid.zk.paths.base/druid其中druid.zk.paths.base/druid表示所有 ZK 状态路径都挂在/druid之下。druid.host则是每个进程在 ZK 上宣告自身时所使用的节点标识host:port 形式在下文的 segment 发布协议中会看到它的具体作用。ZooKeeper 连接与客户端参数druid.zk.service 系列除了路径Druid 还通过 CuratorConfig.java 绑定druid.zk.service.*配置项来控制 ZK 连接行为源码中CONFIG_PREFIX druid.zk.service配置项默认值说明druid.zk.service.hostlocalhostZK 集群地址如localhost:2181多实例用逗号分隔druid.zk.service.sessionTimeoutMs30000ZK 会话超时时间毫秒druid.zk.service.connectionTimeoutMs15000连接超时时间毫秒与 Curator 默认值一致druid.zk.service.compresstrue是否对 znode 数据启用压缩druid.zk.service.aclfalse是否启用 ZK ACLdruid.zk.service.user无ACL 用户名与authScheme配合druid.zk.service.pwd空密码通过PasswordProvider提供druid.zk.service.authSchemedigestZK 认证方案druid.zk.service.maxZkRetries29连接 ZK 的最大重试次数较小的值有助于节点在 ZK 连接丢失时快速失败其中compresstrue与 Announcer.java 中的curator.create().compressed().withMode(CreateMode.EPHEMERAL)一一对应——Druid 在创建和更新 znode 时都会走压缩通道以减少 ZK 上的数据体积。Coordinator 领导者选举Leader ElectionDruid 使用 Curator 的LeaderLatchrecipe 在以下路径执行 Coordinator 领导者选举${druid.zk.paths.coordinatorPath}/_COORDINATOR在默认配置下该路径为/druid/coordinator/_COORDINATOR。所有 Coordinator 进程在同一 latch 路径上竞争最终只有一个节点成为 leader其余节点处于 standby 状态。源码层面的实现位于 CuratorDruidLeaderSelector.java关键细节如下构造时会以latchPath创建一个LeaderLatch参与者 ID 为self.getServiceScheme() :// self.getHostAndPortToUse()见 第 77 行即每个节点以自己的scheme://host:port作为参与标识只有调用registerListener()并执行leaderLatch.get().start()后节点才真正参与选举见 第 184-185 行在此之前创建的 latch 仅用于查询当前 leader不会参与竞争当选 leader 时触发isLeader()回调内部递增term任期号并调用监听器的becomeLeader()失去 leadership 时触发notLeader()并调用stopBeingLeader()见 第 87-128 行异常情况下如becomeLeader()失败会调用recreateLeaderLatch()重建 latch并在重新参与选举前随机等待 15 秒ThreadLocalRandom.current().nextInt(1000, 5000)见 第 219 行把机会让给其他等待中的节点避免立即重新抢回 leadership 造成抖动。在 DruidCoordinator.java 中Coordinator 通过注册becomeLeader()/stopBeingLeader()监听器来感知自身是否成为 leader并在成为 leader 后执行协调职责如 segment 加载/卸载计划。当 leader 进程崩溃或与 ZK 会话断开时其临时 znode 消失其余节点会通过 LeaderLatch 快速感知并选举出新的 leader从而保证 Coordinator 的高可用。Segment publishing 协议Historical 节点宣告机制Segment 的 publishing发布/宣告协议依赖两个 ZK 路径announcementsPath与liveSegmentsPath。服务存在性宣告announcementsPath所有 Historical 进程都会在announcementsPath上发布自身的存在性具体做法是创建一个临时ephemeralznode${druid.zk.paths.announcementsPath}/${druid.host}默认路径即/druid/announcements/host:port。由于是临时节点Historical 进程一旦宕机或与 ZK 会话过期该 znode 会自动消失其他进程据此判断该节点是否存活。正在服务的 Segment 宣告liveSegmentsPathHistorical 随后还会在liveSegmentsPath下创建一个永久permanentznode${druid.zk.paths.liveSegmentsPath}/${druid.host}默认路径即/druid/segments/host:port。随着该节点陆续加载 segment它会在自己名下挂载形如以下的临时 znode${druid.zk.paths.liveSegmentsPath}/${druid.host}/_segment_identifier_即/druid/segments/host:port/segment_identifier每个 znode 对应一个正在被该节点服务的 segment。segment 被卸载或节点下线时对应临时节点随之消失。Coordinator 和 Broker 等进程可以 watch监听这些路径从而实时获知哪个进程当前正在服务哪些 segment据此进行负载均衡决策与查询路由。底层实现与故障自愈上述协议在代码中由两套机制配合完成Announcer.java 是宣告的核心组件。announce()在指定路径创建临时节点CreateMode.EPHEMERAL见 第 370 行并利用PathChildrenCache对父路径建立监听该缓存监听器实现了故障自愈逻辑见 第 234-290 行当子节点被意外删除CHILD_REMOVED时会自动重建宣告当发生CONNECTION_LOST时会记录所有待恢复路径当CONNECTION_RECONNECTED时逐一重新创建丢失的宣告。这保证了即使 ZK 连接短暂中断Druid 的宣告信息也能在会话恢复后自动复原而不是永久丢失。另外Announcer在创建宣告时若父路径不存在会先创建父路径creatingParentsIfNeeded()见 第 423 行并在 stop 时尝试清理自己创建的父路径。关于 liveSegmentsPath 的废弃说明需要再次强调随着 Druid 迁移到 HTTP-based segment loadingliveSegmentsPathgetLiveSegmentsPath()已在 ZkPathsConfig.java 中被标记为Deprecated源码注释明确说明 Use HTTP-based segment discovery instead对应的 ZkCoordinator.java 整个类也已废弃。在新版本中segment 的加载与 inventory 视图改由 HTTP 通道SegmentListerResource承担ZkCoordinator.java 中的isSkipSegmentAnnouncementOnZk配置也印证了这一点——当跳过 ZK segment 宣告开启时节点将不再在 ZK 上创建 live segments 路径。Overlord 领导者选举与任务管理与 Coordinator 类似Overlord 也通过 LeaderLatch 在overlordPath上执行领导者选举。虽然 ZkPathsConfig.java 中的getOverlordPath()未提供显式配置入口直接返回默认的druid/overlord但可以在druid.zk.paths.base层面统一调整其前缀。Overlord 与 MiddleManager 之间的任务管理task management同样依赖 ZKOverlord 把任务分发/状态信息通过 ZK 与 MiddleManager 协调MiddleManager 及其管理的 Peon 进程通过 ZK 路径宣告自己的状态并接收任务分配。在较新版本中任务管理相关的交互如任务分派状态也逐步引入了 HTTP 通道但 ZK 仍然承担着重要的协调职责。实际部署中的 ZK 配置建议在真实集群部署时请参照仓库中的 common.runtime.properties 统一配置各节点的 ZK 参数。核心要点如下统一 base 路径druid.zk.paths.base必须在所有节点上保持一致如/druid否则不同节点会各自读写不同的 ZK 子树导致彼此不可见ZK 地址集群化druid.zk.service.host应配置为完整的 ZK ensemble 地址列表逗号分隔例如zk1:2181,zk2:2181,zk3:2181服务标识唯一每个进程的druid.host必须全局唯一host:port因为它是 ZK 上宣告节点的直接标识重复会导致宣告冲突考虑 ACL 与压缩多租户或安全敏感环境可开启druid.zk.service.acltrue并配合user/pwd/authScheme数据量较大时保持compresstrue以降低 ZK 存储与传输开销版本约束确保部署的 ZooKeeper 为 3.5.x 及以上版本且不要依赖 ZK-based segment loading 的旧行为Druid 31.0.0 起已移除。小结ZooKeeper 在 Apache Druid 中承担着集群状态管理的中枢角色Coordinator 与 Overlord 通过 Curator LeaderLatch 在coordinatorPath、overlordPath上完成领导者选举保证管理节点的高可用Historical 通过announcementsPath宣告存在性、通过liveSegmentsPath宣告正在服务的 segment 列表供 Coordinator 与 Broker 实时感知Overlord 与 MiddleManager 则借助 ZK 完成任务的分发与管理。理解这些 ZK 路径协议与配置项druid.zk.paths.*、druid.zk.service.*是排查 Druid 集群协调问题、规划多集群隔离与安全加固的基础。同时也要注意到 Druid 正在将 segment 发现与加载逐步从 ZK 迁移到 HTTP 通道SegmentListerResource部署新版本时应以 HTTP-based segment loading 为准。赞分享数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载相关推荐CVAT 多语言支持配置Django gettext、i18next 与文档站点 i18n 完整指南CVAT 多语言支持配置Django gettext、i18next 与文档站点 i18n 完整指南 CVATComputer Vision Annotat数据库OLAP大数据后端Apache Hadoop分布式协调服务Zookeeper选举与配置管理Apache Hadoop分布式协调服务Zookeeper选举与配置管理 引言分布式系统的大脑——Zookeeper在Hadoop中的关键作用 在分布式大数据分布式文件系统批处理任务调度集群管理网页视频难保存猫抓 cat-catch 浏览器资源嗅探扩展使用指南网页视频难保存猫抓 cat catch 浏览器资源嗅探扩展使用指南 猫抓cat catch是一款免费开源的 浏览器资源嗅探扩展 打开任意网页时它会自动音视频创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考