10. 高可用特性
10.1 GPDB 高可用概述
GPDB 系统提供了几种可选特性来最大可能支持系统的工作连续性和系统高可用性。
10.1.1 段镜像(segment mirror)概述
Mirror 允许数据库查询在 Primary段 不可用时故障切换到 备份Segment。要配置 Mirror, GPDB系统中必须有足够多的节点才能保证 Mirror 总是位于不同于对应的 Primary段 所在的主机。
只有Mirror 与 Primary 位于不同主机时,才能充分保证有主机不可用时,数据库中可用的段保证数据的完整性。
不过,一定要配置 Mirror 与 Primary 重叠也不是不可以的,只是这样就失去了高可用特征。
Mirror 位于其 Primary 主机之外。在数据库运行时,只有 Primary 是活动的。Primary 的变化通过 文件块同步程序 复制到其 Mirror 的。除非 Primary 出现故障, 否则 Mirror 总是处于非活动状态, 也就是说仅有同步程序在运行。
在 Primary 失效时,文件同步程序会停止, Mirror 会自动唤醒去替代 Primary,使整个系统依然处于活动状态。所有的数据库操作将使用 Mirror。在 Mirror 活动期间,所有对数据库的修改将被记录日志。此时的系统状态为 修改跟踪(Change Tracking)
模式。
当失效的 Segment 被唤醒为在线状态,管理员 需要 使用 恢复程序
将其恢复到 活动状态(或原始状态)
。恢复程序
只同步拷贝 Primary 失效期间 Mirror 发生变化的部分。此时的系统状态为 重新同步(Resynchronizing)状态
。
一旦所有的 Mirror 与它们的 Primary 都处于 同步(synchronized)状态
,系统状态将变为 同步(synchronized)状态
。
10.1.2 主镜像(master mirror)概述
作为可选项,还可以在 Master Instance 主机之外部署一个 Master 镜像。后备 Master(Standby) 在 Master 不可用时作为 热备主机服务。
Standby 与 Master 之间通过 同步程序(gpsyncagent)
保持实时同步,同步程序运行在Standby上并在 Master 和 Standby 之间保持数据同步。 除非 Master 出现故障,否则 Standby 总是处于非活动状态 – 仅有同步程序在运行。
在 Master 失效时,同步程序会停止, Standby 可以被在本机被激活。激活 Standby 时,同步日志被用来恢复 Master 最后一次事务成功提交时的状态。 激活的 Standby 的职能为 GPDB Master,取代之前的 Master,使用相同的端口接受连接。
由于 Master 不含有任何用户数据,仅有系统日志表需要在 Primary 和 Standby 之间被同步。这些表不会被频繁更新,不过,一旦更新,变化会自动复制到 Standby,保证总是与 Primary 之间保持同步。
10.2 故障检测与恢复
故障检测由GPDB服务(postgres)的子进程 ftsprobe
来处理。该故障检测进程监测GP集群,按照可配置的间隔周期扫描所有 Segment实例 和 数据库进程。
每当故障检测进程无法连接到某个 Segment实例,会将该 Segment实例在 GPDB系统 日志中标记为 失效(down)
状态。一旦某个实例失效了,其一直会保持未运行状态,直到管理员执行恢复程序来恢复到其在线为止。
在GPDB系统中的 Mirror 启用时,当 Primary不可用时 系统会自动切换到 Mirror。只要 GPDB系统 中剩下的可用 实例 能够确保全部的数据完整,系统将继续处于可用状态。
要恢复系统中失败的实例, GPDB管理员需手动运行 恢复程序(gprecoverseg)
。 该程序会定位失效的 实例,检查它们是否可用,与当前活动的 实例 比较事务状态以确定掉线期间发生的变化。
如果没有启用 Mirror,在有 实例 不可用时,系统会自动停止服务。在可以继续运行之前,必须手动恢复所有失败的 实例。
10.3 开启 GPDB 的 Mirror
GPDB系统 的 Mirror 既可以在 初始化(gpinitsystem)
时配置,也可以在现有的系统上 重新配置( gpaddmirrors
和 gpinitstandby
)。
本节主要讲述的是对于初始化时没有配置 Mirror 的系统如何添加 Mirror。
10.3.1 启用 Segment Mirror
Segment Mirror 允许在 Primary Segment 不可用时故障切换到备份的 Segment。 要配置Mirror,在 GPDB系统 中必须有足够数量的节点以保证 Mirror Segment 总是位于不同于 Primary Segment 所在的主机。 当然,还可以选择与 Primary Host 完全不同的主机来配置 Mirror Segment。
- 在现有系统添加Segment Mirror(与Primary Segment相同的主机)
- 在所有 Segment 主机上分配用以存储 Mirror 的数据存储区域。这个区域必须与Primary Segment位于不同的文件系统位置。
- 必须确保所有Segment主机之间已经建立了互信,参见gpssh-exkeys命令。
- 运行gpaddmirrors命令启用GPDB系统的Mirror。例如(-p参数加到Primary Segment Instance端口数字之上作为Mirror Instance计算Mirror Instance端口的基础数字):
$ gpaddmirrors -p 10000
- 在现有系统添加Segment Mirror(与Primary Segment不同的主机)
- 确保GPDB软件已经在所有主机上安装。
- 在所有Segment主机上分配用以存储Mirror的数据存储区域。
- 必须确保所有Segment主机之间已经建立了互信,参见gpssh-exkeys命令。
- 创建配置文件,该文件包含所有主机名称,端口,数据目录。可以使用下面的方式来创建参考配置文件:
$ gpaddmirrors -o filename
Mirror配置文件的格式为:
filespaceOrder=
[filespace1_fsname[:filespace2_fsname:...]mirror[content]=content:address:port:mir_replication_port:pri_replication_port:fselocation[:
fselocation:...]
例如: 2个Segment主机,每个Segment主机2个Segment Instance,且没有除了缺省文件系统pg_default之外的其他文件系统:
filespaceOrder=
mirror0=0:sdw1:sdw1-1:52001:53001:54001:/gpdata/mir1/gp0
mirror1=1:sdw1:sdw1-2:52002:53002:54002:/gpdata/mir1/gp1
mirror2=2:sdw2:sdw2-1:52001:53001:54001:/gpdata/mir1/gp2
mirror3=3:sdw2:sdw2-2:52002:53002:54002:/gpdata/mir1/gp3
注意,Mirror配置文件中最重要的配置信息格式为第2行开始的内容:
- content对应Mirror的序号,该序号与Primary的序号匹配
- address对应Mirror所在的主机名,其决定了Mirror位于哪里
- port为Mirror运行时的监听端口,其功能与Primary活动时的端口类似
- mir_replication_port为Mirror的同步程序端口
- pri_replication_port为Primary的同步程序端口
- fselocation为Mirror所在文件系统的数据存储目录
如果手动修改程序生成的配置文件,务必保证同一主机端口不可存在冲突,否则在后面的操作会在一开始即提示失败,失败信息为端口冲突。
生成 mirror_config_file 文件:
[gpadmin@mdw ~]$ gpaddmirrors -o mirror_config_file
20170502:14:27:01:029919 gpaddmirrors:mdw:gpadmin-[INFO]:-Starting gpaddmirrors with args: -o add_mirror_nodes
20170502:14:27:02:029919 gpaddmirrors:mdw:gpadmin-[INFO]:-local Greenplum Version: 'postgres (Greenplum Database) 4.3.12.0 build 1'
20170502:14:27:02:029919 gpaddmirrors:mdw:gpadmin-[INFO]:-master Greenplum Version: 'PostgreSQL 8.2.15 (Greenplum Database 4.3.12.0 build 1) on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.4.2 compiled on Feb 27 2017 20:45:12'
20170502:14:27:02:029919 gpaddmirrors:mdw:gpadmin-[INFO]:-Obtaining Segment details from master...
Enter mirror segment data directory location 1 of 2 >
/tol/data/mi1
Enter mirror segment data directory location 2 of 2 >
/tol/data/mi2
20170502:14:28:09:029919 gpaddmirrors:mdw:gpadmin-[INFO]:-Configuration file output to mirror_config_file successfully.
修改 生成 的 mirror_config_file 文件:
生成的 mirror_config_file 为:
[gpadmin@mdw ~]$ cat mirror_config_file
filespaceOrder=
mirror0=0:sdw02:41000:42000:43000:/tol/data/mi1/gpseg0
mirror1=1:sdw02:41001:42001:43001:/tol/data/mi2/gpseg1
mirror2=2:sdw01:41000:42000:43000:/tol/data/mi1/gpseg2
mirror3=3:sdw01:41001:42001:43001:/tol/data/mi2/gpseg3
- 运行gpaddmirrors命令启用GPDB系统的Mirror(-i参数指定刚刚创建的Mirror配置文件):
$ gpaddmirrors -i mirror_config_file
10.3.2 启用 Master Mirror (Standby)
GPDB系统的 Standby 既可以在初始化 (gpinitsystem)时配置,也可以在现有的系统上配置(gpinitstandby)。假设现有系统初始化时未设置Standby,本节讲述如何为之增加Standby。
- 为已有系统增加 Standby
- 确保Standby主机已经正确的安装配置(gpadmin系统用户已创建, GPDB二进制文件已安装,环境变量已设置,互信已建,数据目录已建)。
- 在当前活动的Master主机上运行gpinitstandby命令已添加GPDB系统的Standby。例如(-s参数指定Standby的主机名):
$ gpinitstandby -s smdw
- 关于切换到Standby,参照”恢复失效的Master”相关章节。
- 检查日志同步程序的状态
如果Standby上的同步程序(gpsyncagent)失败了,这对于系统的用户可能是不明显的。
gp_master_mirroring
日志表是GPDB管理员用以检查Standby目前是否处于同步状态的地方。
注意: gp_master_mirroring
是 GPDB 版本(4.2.x) 中的表,在 版本(4.3.x) 中请使用 pg_stat_replication
。
(4.2.x)例如:
$ psql dbname -c 'SELECT * FROM gp_master_mirroring;'
(4.3.x)例如,此时 standby 节点正处于正常的同步状态:
[gpadmin@mdw ~]$ psql gpdb1 -c 'select * from pg_stat_replication;'
procpid | usesysid | usename | application_name | client_addr | client_port | backend_start | state | sent_location | write_location | flush_location | replay_location |
sync_priority | sync_state
---------+----------+---------+------------------+--------------+-------------+-------------------------------+-----------+---------------+----------------+----------------+-----------------+
---------------+------------
30848 | 10 | gpadmin | walreceiver | 10.20.17.130 | 18383 | 2017-05-02 14:59:25.808864+08 | streaming | 0/C0000B8 | 0/C0000B8 | 0/C0000B8 | 0/C0000B8 |
1 | sync
(1 row)
如果结果表明Standby的状态是”Not Synchronized”,检查detail_state 和 error_message 列以确定错误的原因。
恢复一个已经不同步的Standby:
$ gpinitstandby -s standby_master_hostname -n
10.4 获知 segment 何时失效
如果开启了 Mirror,在 Primary实例 失效时 GPDB 将自动将 失效实例 切换到 Mirror 实例。 只要数据每个部分都有一个实例处于活动状态,通常Segment实例失效对于用户来说不太明显。
如果在失效发生时,一个事务正在进行,该事务会被回滚,然后会在重新配置了 Segment 之后自动重启该事务。
如果由于某个 Segment实例 的失败导致了整个 GPDB系统 变得不可运行(数据完整性被破坏),在尝试连接到数据库时会提示错误。
返回给客户端程序的错误信息可能会给出一些提示。例如:
ERROR: All segment databases are unavailable
10.4.1 启用警告和通知
GPDB管理员可以启用发生如segment失效之类的系统事件时的email或者SNMP警告。查看”启用系统警告和通知”相关章节获取更多信息。
10.4.2 检查失效的 Segment
在启用Mirror情况下,可能会出现Segment失败,这时,系统不会中断服务,而且不会有明确提示。
检查系统状态的一种方法就是使用 gpstate命令
。该命令会列出 GPDB系统 中每个独立组件(Primary Instance、 Mirror Instance、 Master、 Standby)的状态。
- 检查失效的 segment
- 在Master主机,使用-e参数执行gpstate命令。这将显示任何出错状态的 Instance:
$ gpstate -e
-
处于
修改跟踪(Change Tracking)状态
表明对应的Mirror已经失效。如果某个 Instance 不在其初始的角色,意味着其当前的运行状态与系统初始化时的设置不同。这意味着系统处于非平衡状态,一个Segment主机可能会有较多的活动Instance,因此会消耗更高的系统资源。 -
要获得 失效Instance 的详细信息,可查看系统日志表
gp_segment_configuration
。对于失效的Instance 其状态(status)为d(down)
, 正常状态下为u(up)
。
$ psql -c "SELECT * FROM gp_segment_configuration;"
-
对于失效的 Instance,注意其主机、端口、初始角色和数据目录。这些将有助于确定 Instance 所在的主机和位置,有助于诊断故障。
-
查看 Primary Instance 与 Mirror Instance 之间的映射关系,执行命令:
$ gpstate -m
10.4.3 检查日志文件
日志文件对于确定出错的原因可以提供更多的信息。 Master和每个Segment Instance都有自己的日志文件,它位于数据目录下的 pg_log 中。 Master 的日志文件包含着最多的信息,应该总是首先检查Master日志文件。
可以使用 gplogfilter命令
检查GPDB日志文件。要检查 Segment 的日志文件,可以使用 gpssh
在 Segment 主机上运行 gplogfilter命令
。
- 检查日志文件
- 检查 Master 日志文件 WARNING、 ERROR、 FATAL 或 PANIC 级别的日志信息:
$ gplogfilter -t
- 使用 gpssh 检查 Segment Instance 日志文件的 WARNING、 ERROR、 FATAL 或 PANIC级别日志信息:
$ gpssh -f seg_hosts_file -e 'source /usr/local/greenplum-db/greenplum_path.sh;gplogfilter -t /data1/primary/*/pg_log/gpdb*.log' > seglog.out
10.5 恢复失效的 segment
当Master无法连接到Segment Instance,会在GPDB系统日志中将该Instance标记为失效状态。
直到采取措施恢复 失效Instance 到在线状态前,该节点一直保持未运行状态。
恢复失效Instance或者主机的程序依赖于失效的原因和是否启用了Mirror。
Instance 变得不可用有多种因素,例如:
- 主机无法访问(网络出错、硬件故障)。
- Instance未运行(无postgres数据路监听进程)。
- Instance的数据目录损坏或丢失(数据无法访问、文件系统损坏、磁盘故障)。
10.5.1 恢复失效的 segment
若整个 Segment 主机失效,将会导致多个 Instance 失效,该主机上的所有 Primary 和 Mirror 都会被标记为失效并一直为未运行状态。如果GPDB系统没有配置Mirror,在任何Instance失效时,系统都将会自动停止并不可操作。
- 恢复有Mirror的系统
- 第一步是确保从Master主机可以连通该Segment主机。例如:
$ ping failed_seg_host_address
-
找到Master无法连接到Segment主机的故障并排除。例如, Segment主机可需要重启或更换。
-
主机正常启动之后,先确认可以连接,然后从Master主机执行
gprecoverseg命令
恢复失败的Instance。需在从Master主机执行,例如:
$ gprecoverseg
-
恢复进程会试图唤醒失效的 Instance 并确定需要被同步的变化文件。 在此期间不能取消gprecoverseg 进程,需要耐心地等待其结束。在此过程中,数据库将暂时终止写操作。
-
在 gprecoverseg 完成之后, 系统变为
重新同步 (Resynchronizing)状态
,开始拷贝覆盖变化的文件。此进程是后台运行的,期间系统处于可用状态且接受数据库请求。 -
当重新同步进程完成,系统将重新变为
已同步(Synchronized)状态
。运行gpstate命令
确认同步进程的状态:
$ gpstate -m
- 恢复所有 instance 到原有角色
当 Primary Instance 失效时, Mirror Instance 被激活并变为 Primary Instance 。在执行 gprecoverseg
之后,当前作为 Primary Instance 活动的仍然是失败时激活的 Mirror Instance。 Primary Instance 并没有恢复到系统初始化时的角色。这会导致系统处于非平衡状态,一个 Segment 主机可能会有较多的活动 Instance,消耗更高的系统资源。要检查非平衡 Instance,执行:
$ gpstate -e
在恢复失败的 Instance 之后再试图将其恢复到系统平衡状态。要恢复到平衡状态,所有的 Instance 必须启动且完全处于已同步状态。在恢复平衡期间的数据库会话,其正在处理的查询会被取消并回滚。
- 运行gpstate -m命令确保所有的Mirror处于已同步状态。
$ gpstate -m
-
如果任何的 Mirror 处于
重新同步(Resynchronizing)状态
,请等待知道它们完成。 -
使用 -r 参数运行
gprecoverseg命令
恢复Instance到原始角色。 -
在恢复平衡之后,运行
gpstate –e
确认所有Instance已经恢复到原始角色。
$ gpstate -e
- 从双失效恢复
双失效指的是Primary与对应的Mirror一起失效的情况。在出现双失效时, GPDB会停止服务。想要从双失效恢复,执行如下步骤:
- 重启GPDB:
$ gpstop -r
- 在系统重启之后,运行gprecoverseg:
$ gprecoverseg
- 在恢复失败的Instance之后,使用gpstate确认Mirror的状态:
$ gpstate -m
- 如果仍然有Instance处于
修改跟踪(Change Tracking)状态
,运行完全拷贝覆盖的恢复
:
$ gprecoverseg -F
注意: 使用-F参数会将失败的Instance数据完全清除并从配对的Instance完全复制所有数据。出现双失败的情况时上述步骤不确保一定可以恢复回来,如果一致性数据遭到破坏或者事务ID发生紊乱,在尝试恢复之前还需要其他修复工作。
- 恢复无Mirror的系统
- 第一步是确保从Master主机可以连通该Segment主机。例如:
$ ping failed_seg_host_address
-
找到Master无法连接到Segment主机的故障并排除。例如, Segment主机可能需要重启或更换。
-
在主机启动之后,确认可以连通该Segment主机,尝试重启GPDB
$ gpstop -r
- 运行gpstate确认是否所有Segment Instance已经启动:
$ gpstate
注意: 如果Segment Host无法恢复,可能需要重新创建GPDB系统并从备份文件恢复系统数据。当然在重新创建GPDB系统之前还有一些手段用来尝试恢复系统,比如诸多PostgreSQL方面的手段,理论上只要数据未丢失,都是有办法恢复的。
- 当某个Segment主机无法恢复
如果某个主机再也无法运行(比如硬件失败),可能需要恢复到一个备用的硬件资源上。如果启用了Mirror,可以使用gprecoverseg从Mirror拷贝恢复到新的主机上。例如:
$ gprecoverseg -i recover_config_file
这里使用的recover_config_file文件格式为:
filespaceOrder=[filespace1_name[:filespace2_name:...]
failed_host_address:port:fselocation
[recovery_host_address:port:replication_port:fselocation[:fselocation:...]]
例如(如要恢复到一个不同的主机,且没有除了缺省文件系统pg_default之外的其他文件系统):
filespaceOrder=
sdw5-2:50002:/gpdata/gpseg2 sdw9-2:50002:53002:/gpdata/gpseg2
系统日志表gp_segment_configuration and pg_filespace_entry可以帮助确定当前Segment Instance的配置,依此可以作为恢复配置文件的参考。例如,运行下面的查询:
=# SELECT dbid, content, hostname, address, port,
replication_port, fselocation as datadir
FROM gp_segment_configuration, pg_filespace_entry
WHERE dbid=fsedbid
ORDER BY dbid;
新的用于恢复的Segment主机必须已经安装好GPDB软件并与已有的Segment主机进行了相同的配置,包括建立互信等。
10.6 恢复失效的 master
在 Master 失效时,同步程序会停止,Standby 可以被在本机被激活,激活 Standby 时,同步日志被用来恢复 Master 最后一次事务成功提交时的状态。在激活 Standby 时还可以指定一个新的Standby。
10.6.1 激活 Standby
- 首先,系统必须配置有Standby主机。
- 在Standby主机上运行gpactivatestandby命令。例如, -d参数指定要被激活的Standby的数据路径:
$ gpactivatestandby -d /data/master/gpseg-1
- 在激活之后,运行gpstate命令检查状态:
$ gpstate -f
新激活的Master应处于活动(Active)状态,而且如果同时还配置了一个新的Standby主机,应该为被动(Passive)状态(如果没有配置,则为未配置(Not Configured)状态)。
- 在切换之后,在新的Master主机上运行ANALYZE。例如:
$ psql dbname -c 'ANALYZE;'
- 作为可选项,如果在激活Standby时没有指定新的Standby,可以在之后使用 gpinitstandby 命令配置一个新的Standby。在当前活动的Master主机上运行这个命令。例如:
$ gpinitstandby -s new_standby_master_hostname
10.7 恢复 Master 的原有角色
在激活Standby之后,假如Standby的主机与原有的Master主机功能和可靠性等价,可以继续将其作为Primary Master运行
除非在激活Standby的时候已经指定了新的Standby,最好初始化一个新的Standby以确保在有Master Mirror的情况下继续运行。在当前的Master上运行gpinitstandby命令配置一个新的Standby。
作为可选项,也许更愿意将Master与Standby恢复到最原始的主机上。这个过程实质上是将Master与Standby交换角色,这仅应该在必须使用最原始主机运行Master的情况再操作。
10.7.1 恢复Master和Standby到原始主机
- 确保原始主机处于可靠的运行状态。那些导致失败的因素已经被彻底解决。
- 在当前Master上执行如下操作,将Standby初始化到原始主机。例如:
$ gpinitstandby -s original_master_hostname
- 在当前的Master主机(原始角色为Standby)上停止Master进程。例如:
$ gpstop -m
- 在原始Master主机上(当前为Standby)运行gpactivatestandby命令。例如, -d 参数指定要被激活的Standby的数据路径:
$ gpactivatestandby -d $MASTER_DATA_DIRECTORY
- 在激活之后,运行gpstate命令检查状态:
$ gpstate -f
- 原始Master状态应为活动(Active),而Standby状态应为未配置(Not Configured)。一旦原始的Master再次作为GPDB的Master在运行,即可在原始Master主机上初始化一个Standby。
$ gpinitstandby -s original_standby_master_hostname
10.7.2 重新同步Standby
有时可能会出现Master与Standby之间的日志同步程序停止,或者同步时间已经过期。可通过gp_master_mirroring
系统日志表来查看Master与Standby之间的最后更新日期。
$ psql dbname -c 'SELECT * FROM gp_master_mirroring;'
要同步Standby并更新到最新的同步,运行下面的gpinitstandby命令(使用-n参数):
$ gpinitstandby -s standby_master_hostname -n