高可用

介绍Pigsty提供的高可用

一、意义

  1. 显著提高系统整体可用性,提高RTO与RPO水平。
  2. 极大提高运维灵活性与可演化性,可以通过主动切换进行滚动升级,灰度停机维护。
  3. 极大提高系统可维护性,自动维护域名,服务,角色,机器,监控等系统间的一致性。显著减少运维工作量,降低管理成本

二、目标

当我们在说高可用时,究竟在说什么?Several nines ?

说到底,对于传统单领导者数据库来说,核心问题是就是故障切换,是领导权力交接的问题。

目标层次

  • L0,手工操作,完全通过DBA人工介入,手工操作完成故障切换(十几分钟到小时级)
  • L1,辅助操作,有一系列手工脚本,完成选主,拓扑切换,流量切换等操作(几分钟)
  • L2,半自动化,自动检测,人工决策,自动操作。(1分钟)
  • L3,全自动化:自动检测,自动决策,自动操作。(10s)

关键指标

  • 允许进行日常Failover与Switchover操作,不允许出现脑裂。
  • 无需客户端介入,提供代理切换机制,基于流复制,不依赖特殊硬件。
  • 域名解析,VIP流量切换,服务发现,监控适配都需要与自动故障切换对接,做到自动化。
  • 支持PG 10~12版本与CentOS 7,不会给云原生改造埋坑。

交付方式

  • 沙盒模型,展示期待的部署架构与状态
  • 调整方案,说明如何将现有环境调整至理想状态。

三、效果

场景演示

集群状况介绍

  • 主库URL:postgres://dbuser_test:dbuser_test@testdb:5555/testdb
  • 从库URL:postgres://dbuser_test:dbuser_test@testdb:5556/testdb

HA的两个核心场景:

  • Switchover演示
  • Failover演示

故障切换的四个核心问题:

  • 故障检测(Lease, TTL,Patroni向DCS获取Leader Key)
  • Fencing(Patroni demote,kill PG进程,或通过Watchdog直接重启)
  • 拓扑调整(通过DCS选主,其他从库从DCS获取新主库信息,修改自身复制源并重启生效)
  • 流量切换(监听选主事件,通知网络层修改解析)

Patroni原理:故障检测

  • 基于DCS判定
  • 心跳包保活
  • Leader Key Lease
  • 秦失其鹿,天下共逐之。

Patroni原理:Fencing

  • 一山不容二虎,成王败寇,血腥的权力交接。

Patroni原理:选主

  • The king is dead, long live the king
  • 先入关者王

流量切换原理

  • 回调事件,或监听DCS变化。

搭建环境

https://github.com/Vonng/pigsty

五、细节,问题,与风险

场景演示

  • Switchover
  • Standby Down
    • Patroni Down
    • Postgres Down
    • Accidentally Promote
  • Primary Down
  • Failover
  • DCS Down
    • DCS Service Down
    • DCS Primary Client Down
    • DCS Standby Client Down
  • Fencing And corner cases
  • Standby Cluster
  • Sync Standby
  • Takeover existing cluster

问题探讨

关键问题:DCS的SLA如何保障?

==在自动切换模式下,如果DCS挂了,当前主库会在retry_timeout 后Demote成从库,导致所有集群不可写==。

作为分布式共识数据库,Consul/Etcd是相当稳健的,但仍必须确保DCS的SLA高于DB的SLA。

解决方法:配置一个足够大的retry_timeout,并通过几种以下方式从管理上解决此问题。

  1. SLA确保DCS一年的不可用时间短于该时长
  2. 运维人员能确保在retry_timeout之内解决DCS Service Down的问题。
  3. DBA能确保在retry_timeout之内将关闭集群的自动切换功能(打开维护模式)。

可以优化的点? 添加绕开DCS的P2P检测,如果主库意识到自己所处的分区仍为Major分区,不触发操作。

关键问题:HA策略,RPO优先或RTO优先?

可用性与一致性谁优先?例如,普通库RTO优先,金融支付类RPO优先。

普通库允许紧急故障切换时丢失极少量数据(阈值可配置,例如最近1M写入)

与钱相关的库不允许丢数据,相应地在故障切换时需要更多更审慎的检查或人工介入。

关键问题:Fencing机制,是否允许关机?

在正常情况下,Patroni会在发生Leader Change时先执行Primary Fencing,通过杀掉PG进程的方式进行。

但在某些极端情况下,比如vm暂停,软件Bug,或者极高负载,有可能没法成功完成这一点。那么就需要通过重启机器的方式一了百了。是否可以接受?在极端环境下会有怎样的表现?

关键操作:选主之后

选主之后要记得存盘。手工做一次Checkpoint确保万无一失。

关键问题:流量切换怎样做,2层,4层,7层

  • 2层:VIP漂移
  • 4层:Haproxy分发
  • 7层:DNS域名解析

关键问题:一主一从的特殊场景

  • 2层:VIP漂移
  • 4层:Haproxy分发
  • 7层:DNS域名解析

切换流程细节

主动切换流程

假设集群包括一台主库P,n台从库S,所有从库直接挂载在主库上。

  • 检测:主动切换不需要检测故障
  • 选主:人工从集群中选择复制延迟最低的从库,将其作为候选主库(C)andidate。
  • 拓扑调整
    • 修改主库P配置,使得C成为同步从库,使切换RTO = 0。
    • 重定向其他从库,将其primary_conninfo指向C,作为级连从库,滚动重启生效。
  • 流量切换:需要快速自动化执行以下步骤
    • Fencing P,停止当前主库P,视流量来源决定手段狠辣程度
      • PAUSE Pgbouncer连接池
      • 修改P的HBA文件并Reload
      • 停止Postgres服务。
      • 确认无法写入
    • Promote C:提升候选主库C为新主库
      • 移除standby.signal 或 recovery.conf。执行promote
      • 如果Promote失败,重启P完成回滚。
      • 如果Promote成功,执行以下任务:
      • 自动生成候选主库C的新角色域名:.primary.
      • 调整集群主库域名/VIP解析:primary. ,指向C
      • 调整集群从库域名/VIP解析:standby.,摘除C(一主一从除外)
      • 根据新的角色域名重置监控(修改Consul Node名称并重启)
    • Rewind P:(可选)将旧主库Rewind后作为新从库
      • 运行pg_rewind,如果成功则继续,如果失败则直接重做从库。
      • 修改recovery.conf(12-)|postgresql.auto.conf(12),将其primary_conninfo指向C
      • 自动生成P的新角色域名:< max(standby_sequence) + 1>.standby.
      • 集群从库域名/VIP解析变更:standby.,向S中添加P,承接读流量
      • 根据角色域名重置监控

自动切换流程

自动切换的核心区别在于主库不可用。如果主库可用,那么完全同主动切换一样即可。 自动切换相比之下要多了两个问题,即检测与选主的问题,同时拓扑调整也因为主库不可用而有所区别。

  • 检测 (网络不可达,端口拒绝连接,进程消失,无法写入,多个从库上的WAL Receiver断开)
    • 实现:检测可以使用主动/定时脚本,也可以直接访问pg_exporter,或者由Agent定期向DCS汇报。
    • 触发:主动式检测触发,或监听DCS事件。触发结果可以是调用中控机上的HA脚本进行集中式调整,也可以由Agent进行本机操作。
  • 选主
    • Fencing P:同手动切换,因为自动切换中主库不可用,无法修改同步提交配置,因此存在RPO > 0 的可能性。
    • 遍历所有可达从库,找出LSN最大者,选定为C,最小化RPO。
  • 流量切换:需要快速自动化执行以下步骤
    • Promote C:提升候选主库C为新主库
      • 移除standby.signal 或 recovery.conf。执行promote
      • 自动生成候选主库C的新角色域名:.primary.
      • 调整集群主库域名/VIP解析:primary. ,指向C
      • 调整集群从库域名/VIP解析:standby.,摘除C(一主一从除外)
      • 根据新的角色域名重置监控(修改Consul Node名称并重启)
  • 拓扑调整
    • 重定向其他从库,将其primary_conninfo指向C,作为级连从库,滚动重启生效,并追赶新主库C。
    • 如果使用一主一从,之前C仍然承接读流量,则拓扑调整完成后将C摘除。
  • 修复旧主库P(如果是一主一从配置且读写负载单台C撑不住,则需要立刻进行,否则这一步不紧急)
    • 修复有以下两种方式:Rewind,Remake
    • Rewind P:(可选)将旧主库Rewind后作为新从库(如果只有一主一从则是必选)
      • 运行pg_rewind,如果成功则继续,如果失败则直接重做从库。
      • 修改recovery.conf(12-)|postgresql.auto.conf(12),将其primary_conninfo指向C
      • 自动生成P的新角色域名:< max(standby_sequence) + 1>.standby.
      • 集群从库域名/VIP解析变更:standby.,向S中添加P,承接读流量
      • 根据角色域名重置监控
    • Remake P:
      • 以新角色域名< max(standby_sequence) + 1>.standby.向集群添加新从库。
最后修改 January 1, 0001