
作者介绍

2012 年硕士毕业加入 Qunar,目前在网站运营中心担任 DBA 总监,负责整个Qunar的PostgreSQL、GreenPlum、TimescaleDB 及 Oracle 等数据库产品的运维; Qunar TC (技术委员会)成员;
PostgreSQL 中文社区核心成员,热爱数据库技术,乐于在公司内外分享使用中的各种经验;
中国 PostgreSQL MVP ;
中国 PostgreSQL ACE 。
一、PGHA of Qunar 背景
基础软硬件的升级/试用/日常维护给 DB 可用性指标带来挑战
switchover (计划内)和 failover( 故障转移)切换的操作步骤及注意点较多,人工操作效率低且易出错
由于 failover 的随机性,地铁/半夜/假期.....DBA 需安排值班人员值守
DB Instance Crash 的概率虽很低,但如果没有 HA 守护,RD/QA/老板 心里没底,提供的 DB 服务会认为不靠谱......需要的是N个9的服务!
二、PGHA of Qunar 选型
1、流行的开源PGHA方案概况

(数据截止2021-1-10)
2、流行的开源PGHA功能对比

3、PGHA最终选型
通过对上述诸多参考项对比,在开发语言( Python 在 Qunar 自动化运维体系建设中被广泛应用,而 C 学习和维护成本均较高),活跃度,案例使用量及功能等方面,Patroni 具有明显的优势,最终 Qunar PGDBA 团队选型了 Patroni 。
Patroni 基本架构如下:

主要优点:
支持同步复制
支持设置切换最小数据差异
自动化程度高不易出现脑裂
可用 pg_rewind 修复脑裂 DB 实例
HA对运维体系的冲击:
Patroni 会全面接管 DB Cluster 所有节点的配置文件,对原生 Cluster 有一定侵入性
Patroni 管理的 DB Cluster 日常运维需通过 HA 来实现
总之,HA 在保证可用性指标的同时,也需要我们随之更新已有的运维体系,同时对 HA 本身也需要一定维护成本,这是很正常的 trade off 。
三、PGHA of Qunar 定制
We call Patroni a “template” because it is far from being a one-size-fits-all or plug-and-play replication system.
1、核心组件选型/定制功能
DCS(Distributed Configuration Storage)选型:zk/etcd/consul?
三种 dcs 各有优劣,个人见解,一般技术选型考虑的主要因素是掌控程度(熟悉程度)和公司技术栈。考虑到 Qunar 的主流技术栈是 Java + zk ,故选择已经有专业人士维护的 zk 。
DCS 部署在 DB 集群各节点本机还是选择在所有集群之外集中式部署?
考虑到集中式的统一集群便于维护和所有 DB Cluter 统一使用,故选择集中式 zk 集群。
原生方案在预防集群脑裂方面存在不足之处,如何最大限度防止脑裂?
原生方案在主从切换时防止脑裂的主要方式是使用 watchdog 进行机器重启,但不同 OS ,不同 kernel ,甚至不同硬件机型上的 watchdog 配置和实现存在差异,不一定 100% 可将机器重启,且本身触发 watchdog 关机需要一定时间,不一定 100% 在抢到 Leader key 的从库 promote 为主库之前将机器重启!
所以在 watchdog “自杀”主库所在 Server 不一定成功或及时的情况下,Qunar 定制开发了 OS Console Power Reset(断电重启)功能,从库 promote 为主库之前,首先对原主库所在 Server 强制无条件执行 power reset 进行“他杀”, Console 管理口走的是 DB 应用之外的机房单独的管理网络且 Power Reset 速度较 watchdog 重启机器更快,最为靠谱!
Application 和 DB Cluster层的高可用如何选型?
Pgbouncer/Pgpool/Haproxy/Floating IP/DNS 选择哪一个?基于大多数Qunar 的 DB Cluster 已配有 Virtual ip 的现状,且 Vip 对各种语言开发的 Application兼容性好,决定使用Float Vip的方案,相比使用 Pgbouncer/Pgpool/Haproxy ,架构简单易于维护。
原生方案有Master Failover, 但无Slave Failover!
大多数集群上的应用都做了读写分离,从库也有使用,所以 Master Vip 和 Slave Vip 均需要定制开发 vip 自动漂移相关功能。
Master 和 Slave 之间由于网络抖动导致主从通信异常会出现什么情况?
Slave Vip 发生频繁漂移的情况,会导致过频的杀掉应用连接, 所以 API timeout (默认2s)时间也需要可定制。
原生方案在集群初始化 HA 时,各个节点需强制重启,影响应用
此时,zk 里尚未注册 DB 集群数据,原生方案为保证 DB 实例参数符合 yml 配置文件里的参数要求,各个节点需强制重启,尤其是主库,对应用存在较大影响,需进行定制优化。
最终定制实现: 上线 PGHA 主库不需要重启, 从库如果保证 recovery.conf 的参数符合 yml 文件的设置的参数, 亦不会发生重启。
如果zk本身服务挂掉或网络抖动导致zk无法访问,会出现什么情况???
原生方案在处理 DCS 本身的故障时不完善,为避免脑裂会出现 DB Cluster 无 Master 的情况,需定制开发 zk 故障处理功能!

定制后逻辑: 当zk集群故障或网络抖动导致 zk 和集群 Master 不通时, Master 还会去和 Slave 通信, 在确认 DB 集群各节点通信正常且每个节点都和zk集群无法通信时,DB 集群进入无 HA 模式。等待 zk 恢复正常后集群重新进入 HA 管理。
2、PGHA完整方案

上述方案中红色部分为核心定制功能,实际上 PGHA 已在 Qunar 上线多期, DBA 不停的在进行功能优化迭代。
四、PGHA of Qunar 测试
Patroni的工作流程十分复杂,有兴趣详见官网https://raw.githubusercontent.com/zalando/patroni/master/docs/ha_loop_diagram.png。
但原生方案并没有给出完整测试 case ,且经过 Qunar 的 PGDBA 团队深度定制后,更需要结合 Qunar 运维实践梳理出核心测试 case ,给出预期结论。

每次定制优化迭代开发后均需进行全面回归测试,确保全部测试 case 全部符合预期!
五、PGHA of Qunar 指标
1、系统可用性(稳定性)达到N个9的含义
1年 = 365天 = 8760小时
99 = 8760 * 1% = 8760 * 0.01 = 87.6小时
99.9 = 8760 * 0.1% = 8760 * 0.001 = 8.76小时
99.95 = 8760 * 0.0005 = 4.3800 小时 = 4.3800 * 60 = 262.8 分钟
99.99 = 8760 * 0.0001 = 0.876小时 = 0.876 * 60 = 52.6分钟
99.999 = 8760 * 0.00001 = 0.0876小时 = 0.0876 * 60 = 5.26分钟

一般,服务的可用性(稳定性)的及格指标为99.95%,即每年服务不可用时间为 262.8 分钟, 每个季度为65.52 分钟。
2、主库 Failover 切换时间
主库 DB 实例 down (机器没有 down )
主库机器重启时间:(ttl - safety_margin ) 开始触发watchdog重启+ safety_margin (认为在此时间彻底可以完成重启)+ 从库提升为新主库的时间: loop_wait (patroni轮询zk的时间, 抢leader key)+ OPS管理口重启原主库的时间 (1s内可完成,接口超时时间5s)+ 切换时间(极短的promote时间)+ agent绑master vip时间 3s
主库 DB 实例 down ,切换时间线如下图:

可见切换时间和 ttl, safety_margin,loop_wait 设置的值有关。

主库所在机器 down 导致主库 DB 实例 down
从库提升为新主库的时间:loop_wait (patroni轮询zk的时间, 抢leader key)+ OPS管理口重启原主库的时间 (1s内可完成,接口超时时间5s)+ 切换时间(极短的promote时间)+ agent绑master vip时间 3s

可见切换时间仅和 loop_wait 设置的值有关。

参数需要满足的公式
注意无论哪种情况,各参数设置,需满足如下 2 个公式
ttl - safety_margin > loop_waitttl >= loop_wait * 2 + retry_timeoutttl 默认30s, safety_margin 默认5s, loop_wait 默认5s, retry_timeout 默认10s详见 https://patroni.readthedocs.io/en/latest/SETTINGS.html?highlight=retry_timeout#dynamic-configuration-settings
3、主库 Swithover 切换时间
主库计划内的 Switchover 切换,由于已经明确人为指定切换的动作及哪个节点作为新 Master ,不涉及到重启机器,所以基本上主库的切换时间也就是极短的 promote 从库为新主 + 绑定Vip的时间,即 3 秒多一点。
4、从库 Failover 切换时间
从库计划外的 Failover 切换,不涉及到重启机器,所需时间为:周期性唤醒漂 slave vip 进程的时间 5s + 调用 agent 绑 slave vip 的时间 3s (接口超时时间 5s)
可见从库 Failover 可在 10s 内切换完成,可用性指标更容易达到 5个9 以上。
5、从库 Switchover 切换时间
从库计划内的 Switchover 切换,不涉及到重启机器。由于已经明确人为指定切换的动作,不涉及 promote 从库为新主,仅涉及绑定 Vip 的时间,即 3 秒。
6、指标结论
无论何种情况,DB 集群整体可用性指标均可达到5个9以上!
六、PGHA of Qunar 未来
目前 PGHA 的 Application 和 DB Cluster 层的高可用选型 Virtual IP, 但由于 Virtual IP 的固有缺陷,不能跨网段,所以给未来实现天然跨网段的跨机房部署的 DB 集群的高可用带来挑战!
解决方案:Qpatroni 只负责 DB Cluster 的 HA 切换,从各种客户端/开发语言入手,Application 自己实现正常可用的 DB 连接选择、Master/Slave 属性选择,甚至负载均衡。
1. namespace without hostname/IP
Python
Java
Go
......
同样也是针对不同语言,定制开发各自专有的连接池,屏蔽固定hostname/IP,暴露给应用的是 namespace ,在其后面 DBA 动态维护一个 namespace 与具体 hostname/IP的mapping 关系。
此方案非原生方案,需要公司有较强二次开发能力。
2. Connection URIs format with Specifying Multiple Hosts
psql based on libpq

Python base on Psycopg2(libpq wrapper)

Java base on JDBC

由于Qunar的开发语言技术栈主要是 Java ,所以使用原生的 JDBC 自带的 Failover 方案改造 PGHA 将非常轻松!
七、结语
在广大业务线同学的大力配合下,PGHA 在 Qunar 已上线多期,目前运行非常稳定。
希望公司内广大业务线同学及业界/社区内的同仁多多交流,多提宝贵建议和意见。
DBA 会不停的以匠人精神对 PGHA 进行功能优化迭代,力求走出一条 Qunar 自己的 PGHA 成功建设之路!

END
PostgreSQL中文社区欢迎广大技术人员投稿
投稿邮箱:press@postgres.cn




