TT Bigdata TT Bigdata
首页
GitHub (opens new window)
JaneTTR

JaneTTR

数据酿造智慧,每一滴都是沉淀!
  • Ambari 深度专题

  • Bigtop 方法论

  • 自定义集成

  • Ambari Server 与 Web

  • Ambari Metrics

  • Ambari Plus 思考

    • Ambari Server HA
      • 控制面不能只靠一台机器
      • 一把租约如何守住唯一 Active
        • 整体架构先展开看
        • Lease:数据库中的限时通行证
          • 数据库失联时为什么要主动 Fenced
        • Term:识别新旧 Active 的任期号
        • 五种角色状态,而不是简单的主与备
        • 晋升屏障:拿到租约还不能马上对外服务
        • 写围栏:所有普通请求都必须经过角色判断
        • Agent 为什么还要再选一次
        • 统一入口只认 readiness
        • 浏览器如何度过切换窗口
        • 一次故障切换的完整时间线
        • 架构评审时最值得追问的五件事
        • 接着看什么
      • 从一次启用操作追到主备就绪
      • 把 Ambari Server HA 稳稳地跑起来
  • Redis集成实战

  • 通用代码模板

  • 各组件代码

  • 技术专题
  • Ambari Plus 思考
  • Ambari Server HA
JaneTTR
2026-08-17
目录
整体架构先展开看
Lease:数据库中的限时通行证
数据库失联时为什么要主动 Fenced
Term:识别新旧 Active 的任期号
五种角色状态,而不是简单的主与备
晋升屏障:拿到租约还不能马上对外服务
写围栏:所有普通请求都必须经过角色判断
Agent 为什么还要再选一次
统一入口只认 readiness
浏览器如何度过切换窗口
一次故障切换的完整时间线
架构评审时最值得追问的五件事
接着看什么

一把租约如何守住唯一 Active

这一篇关注什么

Ambari Server HA 的关键不在于“第二台 Server 能启动”,而在于两台进程对同一事实达成一致:谁持有当前任期,谁完成了接管恢复,谁才有资格对外写入。

控制权

Lease 决定当前有效期,Term 区分新旧任期,数据库保存全局一致的判断依据。

服务权

新 Active 先跨过晋升屏障,再以 readiness 告诉入口自己已经可以承接业务。

执行权

REST 写围栏与 Agent 二次校验共同拒绝旧 Term、双 Active 和过期命令。

config:
  target: _self
data:
  - name: 控制权
    desc: Lease 决定当前有效期,Term 区分新旧任期,数据库保存全局一致的判断依据。
    bgColor: '#eefaf4'
    textColor: '#176b4d'
  - name: 服务权
    desc: 新 Active 先跨过晋升屏障,再以 readiness 告诉入口自己已经可以承接业务。
    bgColor: '#eef6ff'
    textColor: '#1f4e79'
  - name: 执行权
    desc: REST 写围栏与 Agent 二次校验共同拒绝旧 Term、双 Active 和过期命令。
    bgColor: '#fff8e8'
    textColor: '#79520b'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果把高可用只画成两个 Server 加一个负载均衡,图会很漂亮,却没有回答最危险的问题:网络分区时,两台 Server 都认为对方失联怎么办?旧 Active 卡顿后重新恢复,怎样阻止它继续下发过期命令?Standby 刚拿到租约,还没恢复完任务状态时,能不能立刻接收写请求?

Ambari Plus 的回答由五部分组成:共享数据库租约、单调递增的 Term、服务端写围栏、晋升屏障,以及 Agent 侧的二次校验。入口层的健康检查和浏览器恢复机制,则让这套后端状态能够被用户正确感知。

# 整体架构先展开看

Ambari Server HA 唯一 Active 控制面拓扑

读图顺序

从上到下依次是访问入口、Active/Standby、共享数据库与 Agent。入口可以探测两台 Server,但只把业务流量交给 readiness 成功的 Active;两台 Server 共享数据库,Agent 保存两个候选并独立校验角色与任期。

这里有三个需要特别注意的事实:

  • 两台 Server 连接的是同一个 Ambari 数据库,租约和任务状态不依赖某一台机器的本地磁盘;
  • 负载均衡不负责选主,它只根据 Server 已经形成的角色与就绪状态转发请求;
  • Agent 不是被动接受任意 Server,它会探测候选节点并校验角色、Term、epoch 与 TLS 身份。

# Lease:数据库中的限时通行证

Lease 可以理解为一张带过期时间的写入通行证。Server 成为 Active 后需要周期性续租;Standby 只能在旧 Lease 失效后尝试获取新 Lease。整个竞争通过共享数据库完成,所以不依赖两台 Server 能否直接互相通信。

当前默认参数如下,部署时可以根据数据库和网络时延评估,但不要为了追求更快切换随意压缩。

参数 当前默认值 含义
Lease TTL 15 秒 租约在没有续租时可保持多久
续租间隔 5 秒 Active 正常情况下更新租约的节奏
协调轮询 2 秒 节点重新判断角色和恢复状态的频率
Agent 重连分散窗口 10 秒 避免大量 Agent 在切换瞬间同时连接新 Active

TTL 不是越短越好

数据库偶发抖动或虚拟机短暂停顿都可能延迟续租。TTL 过短会增加不必要切换;TTL 过长则会拉长故障检测。调整前应先测量数据库高分位延迟、时钟状态和实际故障恢复目标。

# 数据库失联时为什么要主动 Fenced

Active 无法访问数据库时,也无法证明自己的 Lease 仍然有效。此时继续处理写请求会产生脑裂风险,所以节点会进入 FENCED,拒绝普通读写和命令调度。即使本地记录的租约时间看起来还没到,也会使用单调时钟形成一道本地写入截止线,防止系统时钟回拨延长旧权限。

这是一种“宁可短暂不可用,也不允许两个控制者同时生效”的选择。对分布式控制面来说,这是正确性优先的必要代价。

# Term:识别新旧 Active 的任期号

每次成功接管都会形成新的 Term。Term 单调递增,它让服务端、Agent 和运维人员都能判断哪个 Active 更新。

例如:

Server A: Active,  Term 18
Server B: Standby, Term 18

Server A 故障
Server B: Active,  Term 19

Server A 恢复
Server A: Standby, Term 19
1
2
3
4
5
6
7
8

旧 Server A 即使保留着 Term 18 的内存状态,也不能覆盖 Term 19 的新 Active。API 写请求可以携带期望 Term,服务端发现请求过期时会明确拒绝;Agent 也只接受最高有效 Term 对应的 Active 会话。

Term 解决的是“先后关系”,Lease 解决的是“当前有效期”。两者配合,才能在进程暂停、网络分区和节点恢复这些场景里识别陈旧控制者。

# 五种角色状态,而不是简单的主与备

Server 实际运行时需要比 Active/Standby 更细的状态。

状态 典型场景 能否承接普通管理请求
SINGLE_ACTIVE 尚未启用 HA 的单节点模式 可以
STARTING HA 节点刚启动,尚未形成安全角色 不可以
ACTIVE 已持有租约;还要结合 ready 状态判断 仅在完成晋升、Ready 后可以
STANDBY 正常备节点,等待接管 不可以
FENCED 租约、数据库或角色一致性无法确认 不可以

HA 模式下进程启动后先进入 STARTING,而不是乐观地把自己当作 Active。首次建立主备时,Standby 还会在关闭选举的状态下启动,只观察已有 Active;等主节点提交新的 HA epoch、Agent 候选配置完成后,才开启正式选举。

这一步很重要:安装完成和参与选举是两件事。把它们分开,可以避免半配置节点过早取得写权限。

# 晋升屏障:拿到租约还不能马上对外服务

Standby 获取新 Lease 后会进入 Active 恢复阶段。它需要重新建立对集群真实状态的认识,典型动作包括:

  • 重新加载 Cluster、Service、Host 与配置状态;
  • 恢复进行中或等待中的管理任务;
  • 核对仓库和版本状态;
  • 恢复告警定义与调度所需状态;
  • 收敛凭据和安全相关运行信息。

只有这些步骤全部完成,节点才标记为 Ready。入口层的 /readiness 也只有在这个时刻返回成功。

正常晋升路径可以概括为 STARTING → ACTIVE_RECONCILING → ACTIVE_READY。如果启动节点观察到其他有效 Lease,它会进入 STANDBY;如果恢复失败、数据库不可确认或续租丢失,它会进入 FENCED,待看到更新 Term 后再以 Standby 身份收敛。

我更愿意把它理解为一扇“晋升屏障”:角色先变化,能力后开放。这样负载均衡不会把用户送到一个刚接管、但内部状态还没准备好的节点。

# 写围栏:所有普通请求都必须经过角色判断

写围栏位于 REST 请求进入业务逻辑之前。它不只拦截 POST、PUT、DELETE,在 Standby 上连普通业务查询也默认不放行,因为某些看似只读的路径可能依赖 Active 的运行状态,或者让调用方误判节点已经可用。

Standby 只保留少量用于发现和恢复的接口:

接口 作用
/api/v2/control-plane/ha/liveness 证明进程存活,不代表可接收业务
/api/v2/control-plane/ha/readiness 只有当前 Active Ready 时返回成功
/api/v2/control-plane/ha/agent-status 供 Agent 判断角色、Term、epoch 和就绪状态
HA 概览与发现接口 供管理页面展示当前拓扑
已存在 HA 操作的精确读取 接管后继续查看原操作,不重新提交写入

这种默认拒绝模式可以减少遗漏。如果以后新增了一个有副作用的 API,开发者即使忘记单独标注,它也不会自动在 Standby 上获得执行权限。

# Agent 为什么还要再选一次

只保护浏览器入口还不够。Ambari Agent 才是真正执行安装、启停、配置分发和安全变更的节点。如果旧 Active 仍能与 Agent 通信,服务端的 REST 围栏就无法阻止过期命令。

开启 HA 后,Agent 配置里会保存 Server 候选列表。Agent 只在建立或重新建立连接时探测候选节点,正常心跳期间不会每次都做全量选举。选择过程遵循这些规则:

  1. HTTPS 证书校验必须开启,避免候选身份被冒充;
  2. 候选必须报告 Active Ready;
  3. 选择最高有效 Term,且 epoch 必须与当前 HA 配置一致;
  4. 如果同一最高 Term 出现多个 Active,Agent 拒绝选择,等待一致性恢复;
  5. 建立会话后,命令还要携带有效的 HA 信封和执行标识,避免旧会话或重复命令生效。

为什么要让 Agent 分散重连

大规模集群里,数百个 Agent 同时探测并连接新 Active 会形成“惊群”。默认 10 秒的随机分散窗口让连接逐步恢复,不会在晋升刚完成时瞬间打满 Server。

# 统一入口只认 readiness

如果前面使用 HAProxy 或已有负载均衡,健康检查必须访问 /readiness,不能只检测端口或 /liveness。

  • /liveness 成功:Java 进程活着,Standby 也应成功;
  • /readiness 成功:节点是最新 Active,并且已完成晋升恢复;
  • TCP 端口可连:只说明有进程监听,无法证明角色安全。

入口摘除失去 Active 资格的节点时,还应关闭这个节点上的旧会话,避免长连接继续停留在过期 Server。代理层只可自动重试明确安全的读取请求,绝不能替用户重试创建任务、修改配置、启停服务等写操作。

# 浏览器如何度过切换窗口

当页面遇到明确的接管信号时,会暂停持续查询和事件流,进入一次集中的 readiness 检查。新 Active 就绪后,页面重新挂载当前视图,并按原操作标识读取持久化结果。

这里有两个边界:

  • 只有明确的 HA 接管响应才进入全局恢复,普通业务返回的 503 仍按业务错误展示;
  • 浏览器只恢复读取,不重放写请求。

这一点看似只是前端体验,实际上与后端的幂等设计同样重要。代理或页面若在切换时盲目重试写操作,再严密的 Server 选主也可能收到一笔新的、合法但重复的请求。

# 一次故障切换的完整时间线

时刻 控制面发生什么 入口与 Agent 应怎样响应
T0:稳定运行 Server A 持有 Lease,Term 为 N;Server B 处于 Standby 入口只转发 A,Agent 会话保持在 A
T1:Active 失联 A 无法续租或主动退出,B 仍等待旧 Lease 失效 入口摘除 A;页面暂停读取,禁止重放写请求
T2:新任期形成 B 获取 Lease,Term 增加到 N+1,进入恢复阶段 B 的 liveness 可用,但 readiness 尚未成功
T3:晋升完成 B 恢复任务、配置与运行状态,进入 Active Ready 入口转发 B;Agent 分散重连并接受最高 Term
T4:旧节点回归 A 读取到 N+1,以 Standby 身份加入 A 的 readiness 保持失败,不重新抢占业务

这条链路同时验证了控制权、服务就绪、入口转发、Agent 重连和旧节点回归。缺少其中任何一段,都只能算局部恢复。

# 架构评审时最值得追问的五件事

  1. 数据库中断时,旧 Active 是继续服务还是立即自我围栏?
  2. 新 Active 获取 Lease 后,要完成哪些恢复动作才会 Ready?
  3. Agent 如何拒绝旧 Term、双 Active 和未经 TLS 验证的候选?
  4. 负载均衡检查的是端口、liveness,还是严格的 readiness?
  5. 页面和调用方在切换时是否可能自动重放写请求?

如果这五个问题都有明确答案,高可用才从一张双节点架构图变成了可验证的控制协议。

# 接着看什么

下一篇沿着一次真实启用流程进入源码:为什么先做 mTLS,再远程安装 Standby;为什么候选切换分成准备和激活两阶段;失败后又怎样从持久化 Operation 继续。

从一次启用操作追到主备就绪

查看规划、安装、安全引导、主节点提交和 Agent 切换的实现分工。

把 Ambari Server HA 稳稳地跑起来

回到页面,用准备清单和验收表完成一次可复现的启用。

config:
  target: _self
data:
  - name: 从一次启用操作追到主备就绪
    desc: 查看规划、安装、安全引导、主节点提交和 Agent 切换的实现分工。
    link: /v/custom/thoughts/ambari-server-ha/implementation/
    bgColor: '#fff8e8'
    textColor: '#79520b'
  - name: 把 Ambari Server HA 稳稳地跑起来
    desc: 回到页面,用准备清单和验收表完成一次可复现的启用。
    link: /v/custom/thoughts/ambari-server-ha/enable/
    bgColor: '#eef6ff'
    textColor: '#1f4e79'
1
2
3
4
5
6
7
8
9
10
11
12
13
#Ambari Server#高可用#Lease#写围栏
控制面不能只靠一台机器
从一次启用操作追到主备就绪

← 控制面不能只靠一台机器 从一次启用操作追到主备就绪→

最近更新
01
当前版本 2026/08
08-29
02
把 Ambari Server HA 稳稳地跑起来
08-17
03
从一次启用操作追到主备就绪
08-17
更多文章>
Theme by Vdoing | Copyright © 2017-2026 JaneTTR | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式