postgresql数据库有着各种各样的高可用方案,绝大多数,都是基于流复制机制实现的,常见的例如patroni dcs,pacemaker corosync,repmgr,keepalived,pg_auto_failover,pgpool等等,其中使用较多的应该是patroni和repmgr两种,下文针对postgresq的两种高可用方案repmgr和patroni进行部分场景对比。
1.repmgr特点
repmgr是2010年由2ndquadrant推出的一款postgresql故障切换工具,repmgr是一个开源工具套件,用于管理postgresql服务器集群中的复制和故障转移。它扩展了postgressql内建的hot-standby能力,可以监控复制和执行管理任务。
(1)repmgr命令管理 (replication manager)
repmgr是一个命令行工具,日常操作主要通过repmgr进行操作,功能包括集群状态查看、switchover、克隆备库、失效节点重新加入等。
用于执行管理任务的命令行工具,主要有以下方面作用:
- 设置备用服务器
- 将备用服务器升级为主服务器
- 切换主服务器和备用服务器
- 显示流复制状态
- clone恢复备机数据
- 注册节点
(2)repmgrd守护进程 (replication manager daemon)
repmgrd 是一个守护进程,支持故障检测、failover,监控和记录集群信息以及自定义脚本接受集群事件通知event_notification_command,它有一组预定义的事件,并将这些事件的每次发生都存储在 repmgr.events 表中。repmgr 允许将事件通知传递给用户定义的程序或脚本,该程序或脚本可以采取进一步的行动,例如发送电子邮件或触发任何警报。
可以使用repmgrd设置自动故障转移。repmgrd 需要在启动 postgresql 服务器时加载共享库“repmgr”。库名称应配置在 postgresql.conf 文件的shared_preload_libraries里。并且需要在 repmgr.conf 文件中设置 failover=automatic 参数。一旦设置了所有这些参数,repmgrd 守护程序就会开始主动监控集群。如果主节点出现任何故障,它将尝试多次重新连接。当所有连接到主节点的尝试都失败时,repmgrd 将通过选举选择最符合条件的备用节点作为新的主节点。
它主动监视复制集群中的服务器并执行以下任务:
- 监控和记录集群复制性能
- 通过检测主服务器故障并提升最合适的备用服务器来执行故障转移
- 将有关群集中事件的通知提供给用户定义的脚本,该脚本可以执行诸如通过电子邮件发送警报等任务
- repmgrd 根据本地数据库角色不同,其功能也不同:
主库:repmgrd仅监控本地数据库,负责自动恢复、同异步切换
备库:repmgrd监控本地数据库和主数据库,负责自动切换、复制槽删除
(3)相关元数据
表
repmgr.events:用来记录repmgr管理的事件信息
repmgr.nodes:复制群集中每个服务器的连接和状态信息
repmgr.monitoring_history:repmgrd写入的历史备用监视信息
repmgr.voting_term:【5.2新增】主要用来记录投票信息
视图
repmgr.show_nodes:基于表repmgr.nodes,增加了显示上游节点的信息
repmgr.replication_status:启用repmgrd的监视时,显示每个备用数据库的当前监视状态。
repmgr元数据的schema可以存储在现有的数据库或在自己的专用数据库,repmgr元数据的schema不能驻留在不属于repmgr管理的复制集群的数据库服务器上。
——
repmgr本身不支持虚拟ip的功能 ,我们可以借助keepalived来实现虚拟ip的功能。另外在配置文件中,也可以设置promote_command为一个自定义脚本
2.repmgr如何仲裁哪台备机升主
- 每个备机检查到主机数据库故障后会进行重试,重试最后一次后,会去询问其他备用数据库。如果其它备用节点的最后一个复制的lsn或与主节点的最后一次通信的时间比当前节点的最后一个复制的lsn或最后一次通信的时间更近,则该节点不执行任何操作,并等待与主节点的通信恢复。
- 如果所有备机数据库节点都看不到主库,则它们将检查witness见证节点是否可用。如果也无法到达witness见证节点,则备机会假定主服务器端发生网络中断,因此不会继续选择新的主服务器。如果可以到达witness见证节点,则备机节点会假定主服务器已关闭,然后继续选择主节点。之后将升级配置为“首选”主节点的节点。每个备机数据库节点将重新初始化其复制,以跟随新的主数据库。
repmgr怎么选主: 当需要failover时,repmgr选举候选备节点会以以下顺序选举:lsn > priority > node_id。若lsn一样,会根据priority优先级进行比较,该优先级是在配置文件中进行参数配置,将priority设置为0会禁止参与选主。若优先级也一样,会比较节点的node id,小者会优先选举
3.repmgr如何处理脑裂场景(位置参数、witness见证节点)
(1)位置参数
repmgr使用location位置参数处理脑裂场景,其中每个节点应根据其所在的数据中心指定位置参数。在任何网络分裂的情况下,repmgr将确保与主节点位于同一位置的节点的提升。如果它在该位置找不到任何节点,它将不会提升任何位置的任何节点。
location='location1' # 定义location
除此之外可以使用witness见证服务器的额外节点处理网络隔离,避免产生脑裂。
(2)见证节点
witness见证节点重要用来处理集群主库和备库之间可能存在网络拥塞、延迟、路由等问题影响,导致主库还在正常工作,而备库无法联系主库的场景。通过设置witness节点可以针对主库与备库之间切换的检查完整性,即辅助备节点进行监控,避免因网络问题导致的脑裂现象。
见证节点主要的工作是帮助备库达到法定的数量。它是一个仅考虑多数票数的节点。该服务器上不需要安装postgresql,因此在复制中没有任何作用。
当备机连不上主机了,就会连接witness见证节点,如果也连接不上见证节点,那判断自己网络故障了,如果能连上见证节点,则认为主机故障,见证节点的作用类似于一个信任的网关。
witness必须配合repmgrd。 remgrd启动后会作为常规服务运行并持续监视集群的运行状况。当达到与主机数据库失去联系的法定人数时,它将启动故障转移。它不仅可以自动升级备用数据库,还可以在多节点群集中重新启动其他备用数据库以跟随新的主数据库。
4.repmgr优缺点
(1)repmgr 优点
- repmgr 提供了帮助设置主节点和备用节点以及配置复制的实用程序。
- 不使用任何额外的端口进行通信。如果想执行切换,那么它才需要配置无密码ssh。
- 通过调用已注册事件的用户脚本来提供通知。
- 在主服务器发生故障时可以执行自动故障转移。
- 对数据库侵入小,维护起来和正常主备流复制基本一致。
- 配置简单。
(2)repmgr 缺点
- repmgr 不会检测备用库是否在恢复配置中使用未知或不存在的节点错误配置。即使节点在未连接到主/级联备用节点的情况下运行,节点也会显示为备用节点。
- 无法从 postgresql 服务关闭的节点检索另一个节点的状态。因此,它不提供分布式控制m6米乐安卓版下载的解决方案。
- 它不能在备机单个节点down掉时,自动把其拉起。
1.patroni特点
patroni起源于 compose 的一个项目governor 的一个分支。它是一个用 python 编写的开源工具套件,用于管理 postgresql 集群的高可用性。patroni 没有构建自己的一致性协议,而是利用了分布式配置存储(dcs) 提供的一致性模型 ,如 zookeeper、etcd、consul 和 kubernetes等。下文主要以etcd作为dcs举例来说明:
etcd可以进行心跳检测(etcd 之间的心态检测)、存储并在各个节点上同步键值信息。etcd最少需要三个节点且为奇数来进行 leader 选举(脑裂发生时 etcd 集群会僵死等待恢复,不会发生都认为自己是主的情况)。
patroni通过一个api接口连接到etcd(或者其他dcs),向其插入键值对记录patroni参数、数据库参数、主备信息以及连接信息,平常通过etcd对其它节点做心跳检测,通过从etcd获取数据对中存储的主备信息来判断各节点的状态对集群进行自动管理
patroni 确保 postgresql ha 集群的端到端设置,包括流复制。它支持创建备用节点的各种方式,并且可以根据您的需要定制模板。 patroni 借助回调可以支持事件通知,回调是由某些操作触发的脚本。它使用户能够通过提供暂停/恢复功能来执行任何维护操作。watchdog支持功能使框架更加健壮。
2.dcs(分布式配置存储) zookeeper vs etcd vs consul
zookeeper
zookeeper带来的主要优势是它的成熟度,健壮性和功能丰富性。 但是,它也有其自身的一系列缺点,其中java和复杂性是主要原因。 zookeeper对java的使用以及相当数量的依赖关系使它比同等竞争产品消耗更多的资源。 除此之外,zookeeper也很复杂。 维护成本比较高。 功能丰富性很高,但是很多复杂的功能可能不会使用到。
etcd
etcd是可通过http访问的键/值存储。 它是分布式的,具有可用于构建服务发现的分层配置系统。 它非常易于部署,设置和使用,可提供可靠的数据持久性,安全性并具有非常好的文档。etcd的简单性比zookeeper更好。 但是,必须先将其与少量第三方工具结合使用,然后才能实现服务发现目标。
consul
consul是一个高度一致的数据存储,它形成了一个动态集群。 具有分层的键/值存储,该键/值存储不仅可以用于存储数据,还可以注册服务,这些服务可以用于各种任务,从发送有关数据更改的通知到根据其输出运行运行状况检查和自定义命令。与zookeeper和etcd不同,consul实现了嵌入式服务发现系统,因此无需构建自己的系统或使用第三方系统。 除其他事项外,该发现还包括对节点和在它们之上运行的服务的运行状况检查。
zookeeper和etcd仅提供原始的k/v存储,并要求应用程序开发人员构建自己的系统来提供服务发现。 另一方面,consul提供了用于服务发现的内置框架。 客户端只需要注册服务并使用dns或http接口执行发现。 其他两个工具需要手工m6米乐安卓版下载的解决方案或使用第三方工具。consul为多个数据中心提供了开箱即用的本机支持,该系统不仅可以在同一集群中的节点之间工作,而且还可以跨数据中心工作。
3.patroni如何仲裁哪台备机升主
patroni监控本地的postgresql状态,并将相关信息写入etcd,每个patroni都能读写etcd上的key,从而获取外地postgresql数据库信息。当etcd的leader节点不可用时,etcd会一致性的选择一个合适的节点作为主节点,新的etcd主节点将获取leader key。
etcd怎么选主:假设etcd有三个节点,三个节点都去创建一个全局的唯一key,谁先创建成功谁就是master主节点。其他节点持续待命继续获取,主节点继续续租key值(key值会过期)。当持有key的节点down机时,或者key值过期被删,其他节点创建key成功,则新master主节点产生,其他节点继续这样待命持续获取key的状态。
- patroni 自动创建主备流复制集群通过 api 接口往 etcd 记录键值来储存主备信息与连接
信息以及配置信息,而etcd 进行心跳检测(etcd 之间的心态检测)与存储键值信息 - patroni 通过连接 etcd 对其它节点做心跳检测,每 loop_wait 秒一次
- patroni 通过连接到 etcd 集群,向其插入键值记录 patroni 参数、数据库参数、主备信息以及连接信息。通过向 etcd 拿取键值中储存的主备信息来判断各节点的状态来切换。各节点会在 data 目录下生成 recovery.done(与 recovery.conf一样,里面的 primary_conninfo 记录是上一次主节点的连接信息),原主节点发生切换时自动改变后缀为 recovery.conf,原备节点会删除掉自身的recovery.conf 文件,再通过 pg_rewind 来快速恢复节点,不需要做bacebackup基础备份。
- 异步流复制时主从之间延时:主从之间 wal 日志延时超过
maximum_lag_on_failover(byte)的大小,主备有可能会重启但不会发生切换。
数据丢失量通过 maximum_lag_on_failover,ttl,loop_wait 三个参数控制。
最坏的情况下的丢失量:maximum_lag_on_failover 字节 最后的 ttl 秒时间内写入的日志量(loop_wait /2 在平均情况下)。 - haproxy keeplived 保持对外的访问 ip 端口不变
4.patroni如何处理脑裂场景(watchdog)
正常停止patroni时,patroni会顺便把本机的pg进程也停掉。然而,当patroni进程自身没法正常工作时,以上的保护措施难以成功。例如patroni进程异常终止或主机临时hang住等。
为了更可靠的防止脑裂,patroni支持经过linux的watchdog监视patroni进程的运行,当patroni进程没法正常往watchdog设备写入心跳时,由watchdog触发linux重启。
使用watchdog防止出现脑裂,如果leader节点异常导致patroni进程无法及时更新watchdog,会在leader key过期的前5秒触发重启。重启如果在5秒之内完成,leader节点有机会再次获得leader锁,否则leader key过期后,由备库通过选举选出新的leader。
patroni会在将postgresql提升为master之前尝试激活watchdog。
如果看atchdog激活失败并且watchdog模式是required那么节点将拒绝成为主节点。
在决定参加leader选举时,patroni还将检查watchdog配置是否允许它成为领导者。
在将postgresql降级后(例如由于手动故障转移),patroni将再次禁用watchdog。当 patroni处于暂停状态时,watchdog也将被禁用。正常停止patroni服务,也会将watchdog禁用。
5.patroni优缺点
(1)patroni优点
- patroni 支持集群的端到端设置。
- 支持 rest api 和 haproxy 集成。
- 通过某些操作触发的回调脚本支持事件通知。
- 利用 dcs 选取主节点。
- 支持自动failover和按需switchover
- 支持同步复制下备库故障时自动降级为异步复制(功效相似于mysql的半同步,可是更加智能)
- 支持控制指定节点是否参与选主,是否参与负载均衡以及是否能够成为同步备机
- 支持经过pg_rewind自动修复旧主。
- 支持多种方式初始化集群和重建备机,包括pg_basebackup和支持pgbackrest,barman等备份工具的自定义脚本
- 支持自定义外部callback脚本
- 支持rest api
- 支持经过watchdog防止脑裂
- 支持k8s,docker等容器化环境部署
- 支持多种常见dcs存储元数据,包括etcd,zookeeper,consul,kubernetes等
除此之外,patroni在目前支持的 逻辑复制槽的自动failover 这一功能,在postgresql的高可用方案里,是比较方便且独树一帜的。所以,如果可用服务器在至少3台或者有逻辑复制需求的时候,patroni是一款很值得推荐的postgresql高可用工具,但是这个最少节点的限制也是其中一个缺点。
(2)patroni缺点
- patroni 不会检测到在恢复配置中具有未知或不存在节点的备用的错误配置。即使备节点在未连接到主/级联备用节点的情况下运行,该节点也将显示为从节点。
- 用户需要处理 dcs 软件的设置、管理和升级。和原本运维主备流复制环境差异较大。对数据库的侵入较大。
- 需要为组件通信打开多个端口:
- patroni 的 rest api 端口
- dcs 最少 2 个端口
1.备机测试
场景 | repmgr | patroni |
---|---|---|
kill postgresql 进程 | 需要手动干预才能再次启动postgresql 进程。 | patroni 使 postgresql 进程回到运行状态。 |
正常停止 postgresql 进程 | 需要手动干预才能再次启动postgresql 进程。 | patroni 使 postgresql 进程回到运行状态。 |
重启服务器 | 需要手动启动postgresql,并将服务器标记为正在运行。 | patroni会在在重启及服务器后启动,除非配置为在重新启动时不启动。一旦 patroni 启动,它就会启动 postgresql 进程并设置备机配置。 |
正常停止repmgrd或patroni | 备机的不会成为自动故障转移的一个节点,(备机状态无变化) | patroni会停止备机postgresql进程 |
2.主机测试
场景 | repmgr | patroni |
---|---|---|
kill postgresql 进程 | repmgrd在固定的时间间隔内,所有备机都会对主节点连接进行健康检查。当所有重试都失败时,在所有备机上触发选举。作为选举的结果,具有最新收到的 lsn 的备用被提升。失去选举的备用服务器将等待来自新主节点的通知,并在收到通知后跟随它。原主节点需要手动干预才能再次启动 postgresql 进程。 | patroni 使 postgresql 进程回到运行状态。在该节点上运行的 patroni 具有主锁,因此没有触发选举。 |
正常停止 postgresql进程并在健康检查到期前立即将其恢复 | repmgrd在固定的时间间隔内,所有备机都会对主节点连接进行健康检查。当所有重试都失败时,在所有备机上触发选举。然而,新当选的主节点没有通知现有的备机,因为旧的主节点回来了。群集处于不确定状态,需要人工干预。 | patroni 使 postgresql 进程回到运行状态。在该节点上运行的 patroni 具有主锁,因此没有触发选举。 |
重启服务器 | 当所有备机上与主的连接健康检查失败时,remgrd 开始选举。符合条件的备机被提升为新主。当原主回来时,它没有加入集群并被标记为失败。需要运行 repmgr node rejoin 命令将服务器添加回集群。 | 发生故障转移,其中一台备机在获得锁后被选为新的主节点。当patroni在旧主机点上启动时,它会拉起原主的postgresql进程并执行pg_rewind,并、且开始跟随新主节点。 |
正常停止repmgrd或patroni | 主节点不会成为自动故障转移的一部分。postgresql 服务正常运行。启动repmgrd,postgresql进程不自动拉起。 | patroni所在的其中一台备机获得了 dcs 锁并提升自身成为主库。旧主的postgresql被patroni关掉,一旦在旧主机上启动了 patroni,它会将旧主的时间线和 lsn(use_pg_rewind设置为 true)调整到与新主一致并开始跟随新主。 |