pg_rewind

走向将来 pg_rewind {.center}

小次郎@飞象翻译  origin By Giuseppe Broccolo (第二象限)

原文连接sql

PostgreSQL 9.5 之后pg_rewind 可让旧的主, 追随提高的备库,并继续跟进.数据库

因为在这期间,提高的备库(此时已经成为primary)拥有了本身的时间线(qιuqιu☄:startupxlog timeline+1)。 在switchover过程,集群不能正常工做的场景中,这时会用到pg_rewind服务器

你经历过"脑裂"的切换过程么?post

若是目标是切换角色的主节点和备节点 你最终获得两个两个独立的主节点, 每个拥有一个独立的时间线, 这时PG dba在HA的状况下,pg_rewind 就能够派得上用场 !翻译

在PostgreSQL 9.5之前,那里是这个问题只有一个解决办法︰rest

从新追随新的主作一次新的基础备份(basebackup),并将他做为一个新的备用节点加入HA集群中去, 通常来讲,这也不是一个问题, 若是你的数据库比较大, 假设你有数百GBs 的数据,这时,这样的操做很容易致使停机时间比较长。postgresql

在时间的数据库还原到之前的点能够建立能够用不一样的方式处理一些复杂性。 对于深刻解释的演变和PostgreSQL的 容错组件, 你能够 Gulcin 关于 PostgreSQL 容错能力的演变系列文章 其中提到了 pg_rewind 使用时间旅行特征中的演变。code

pg_rewind 的工做原理server

pg_rewind 扫描"旧"Master 节点的 PGDATA 目录,在切换到新的时间线的过程当中, 标记出这些时间内更改的数据块, 而后从提高的主(原先为从设备)复制只有这些块。blog

而后,这用于替换所作的更改。

做为一个"抵押品"效应,配置文件也会从提高的Master状态中去复制 (因此DBA必需要当心处理, 可以让这个节点可以融入到HA集群中去) 这样,就不须要对PGDATA作一次彻底同步。

要作到这一点,就要拥有旧主 switchover 前的最后时刻产生的全部WALs。 经过比较数据的状态存在于 PGDATA 的块与登陆 WALs 的变化,找出改变并标记。 一旦肯定更改的数据块,WALs 重演,模仿时间线的 rewind("倒带")。

此外︰

实例必须在初始化时使用 "-k"(或 --data-checksums)参数

启用 wal_log_hints参数

在PostgreSQL 9.5之前,必要的WALs从最后一个检查点开始,而且不能在这个时间线以后,

为了更好地理解它是如何工做的,能够以以下Master节点情景为示列︰

# Set PATH variable
export PATH=/usr/pgsql-9.5/bin:${PATH}

# This is the directory where we will be working on
# Feel free to change it and the rest of the script
# will adapt itself
WORKDIR=/var/lib/pgsql/9.5

# Environment variables for PGDATA and archive directories
MASTER_PGDATA=${WORKDIR}/master
STANDBY1_PGDATA=${WORKDIR}/standby1
ARCHIVE_DIR=${WORKDIR}/archive

# Initialise the cluster
initdb --data-checksums -D ${MASTER_PGDATA}

# Basic configuration of PostgreSQL
cat >> ${MASTER_PGDATA}/postgresql.conf <<EOF
archive_command = 'cp %p ${ARCHIVE_DIR}/%f'
archive_mode = on
wal_level = hot_standby
max_wal_senders = 10
min_wal_size = '32MB'
max_wal_size = '32MB'
hot_standby = on
wal_log_hints = on
EOF

cat >> ${MASTER_PGDATA}/pg_hba.conf <<EOF
# Trust local access for replication
# BE CAREFUL WHEN DOING THIS IN PRODUCTION
local replication replication trust
EOF

# Create the archive directory
mkdir -p ${ARCHIVE_DIR}

# Start the master
pg_ctl -D ${MASTER_PGDATA} -l ${WORKDIR}/master.log start

# Create the replication user
psql -c "CREATE USER replication WITH replication"

(注: 少许的WAL保持在主),而后待机状态︰

# Create the first standby
pg_basebackup -D ${STANDBY1_PGDATA} -R -c fast -U replication -x

cat >> ${STANDBY1_PGDATA}/postgresql.conf <<EOF
port = 5433
EOF

# Start the first standby 启动备库
pg_ctl -D ${STANDBY1_PGDATA} -l ${WORKDIR}/standby1.log start

让咱们在主库插入一些数据。能够看到备机也是从(热)备机状态。

如今提高备机,脱离Master节点,使用命令以下︰

pg_ctl -D ${STANDBY1_PGDATA} promote

如今若是你更新的大师,没有更改将可见从待机状态。 此外,在归档文件 / 目录就能够看到文件 00000002.history, 这代表在备机提高期间,时间线发生了变化。

如今让咱们"倒带"主人,并使其跟进提高待机状态︰

~$ pg_ctl -D ${MASTER_PGDATA} stop
waiting for server to shut down.... done
server stopped
~$ pg_rewind --target-pgdata=${MASTER_PGDATA} \
    --source-server="port=5433 user=postgres dbname=postgres"

注意:在这里,对于链接到源服务器 — — 提高待机状态 — — 咱们使用 postgres 用户,由于 pg_rewind 须要超级用户的身份检查数据块

若是 max_wal_size 参数不是足够大,以保持所需的 WALs 到 pg_xlog / 备用服务器的目录中,我已经故意作了决定以前,相似于如下的错误能够获得︰

The servers diverged at WAL position 0/3015938 on timeline 1.
could not open file "/var/lib/pgsql/9.5/master/pg_xlog/000000010000000000000002": No such file or directory

could not find previous WAL record at 0/3015938
Failure, exiting

如今,有两种可能的方式来解决这个问题: (小次郎注:经过后面的评论,咱们发现第二个方法不可行,不可行(=@__@=)?)

手动检查缺乏的范围,在归档中,开始从一个列出的错误消息,而后将它们复制到 pg_xlog / 目录的主人

在 recovery.conf 和 PGDATA 的主人,在地方中添加适当的 restore_command,因此 pg_rewind 会自动地寻找失踪 WALs

第二个选项多是最合适的方法。例如,想一想,是否你有沃尔玛档案由酒保︰ 你能基地 restore_command 要使用 get 沃尔玛功能的酒保,由加布里埃这篇有趣的文章所述。这样作的时候,酒保将用做沃尔玛集线器,提供必要的沃尔玛文件,到 pg_rewind。

一旦检索到失踪的范围,你能够再次运行 pg_rewind 命令和如下消息应确保一切正常工做︰

~$ pg_rewind --target-pgdata=${MASTER_PGDATA} \
    --source-server="port=5433 user=postgres dbname=postgres"
servers diverged at WAL position 0/3015938 on timeline 1
rewinding from last common checkpoint at 0/3000140 on timeline 1
Done!

请记住,这个操做只是不多的块复制(这是在修复脑裂(次郎注:those changed during the split-brain),即使您的数据库大小是数以百计的 GBs! 记住,配置文件也会被复制,在"降级"的Master节点数据目录中的recovery.conf也已经被覆盖了.

  • 更改该实例是在哪里在 postgresql.conf 监听的端口 (在咱们的示例中, 将其设置为5432)

  • 为了使降级的主库能够链接到提高的主库上去,须要在主库更改recovery.conf文件中的primary_conninfo

完成此操做后,启动降级的Master节点,它将将开始跟进提高的备机(即新的主),而后将其待机反过来。

你但愿拥有一个一个更复杂的HA集群吗?不用担忧!

第2部分将深刻剖析PostgreSQL 9.5 中的pg_rewind!

评论翻译:

lesovsky: 请注意,pg_rewind 仅适用万一当老主人中止正确,和那里是没有办法倒带若是已经崩溃,SIGKILL'ed 或相似。

Vladimir:

在 recovery.conf 和 PGDATA 的主人,在地方中添加适当的 restore_command,因此 pg_rewind 会自动地寻找失踪 WALs

这真的管用吗?好像是,关于这些pg_rewind 源代码没有说起到这一块呢?

嗨,Vladimir,

 是的,这的确存在误导性: 后来通过尝试,这我意识到它不能以这种方式工做(
 但错误地没有改变了书面的部分 — — 太晚如今!伤心表情 :()。

 不管如何,Barman 的get-wal 特性是真的颇有趣(此处是广告),
 任何状况下,均可以从归档中检索到须要的WALs,而且能够单独使用
 若是给pg_rewind 添加个补丁就nice 了,让其支持从相似"restore_command"的参数中检索归档

不过,谢谢指出问题。

Alexander:

若是主库已经奔溃,还有没有办法rewind,SIGKILL'ed 或相似。

也不是彻底无药可救了,还有一种解决办法:(救死马的方法么?) 1) 从"pg_xlog/archive_status"中删除文件 2) 在单用户模式下启动您的数据库 (postgres -single -D -c archive_mode =-c archive_command = false)。 3) 执行检查点 "checkpoint" 4) 按下 Ctrl + D 离开单用户模式。

瞧,如今你有干净关闭,pg_rewind 应该工做 表情嘚瑟笑 :)

博主回复:

   嗨,Alexander

   谢谢你提供的这个过程。以前没尝试过啊,(小次郎注:你厉害),
   这真的对于任何类型的Master节点故障管用么?不管如何,做为已经突出显示到莱绍夫斯基,
   我在这里考虑的场景是* switchover *,主库正常的关闭,没有考虑到 failover。
本站公众号
   欢迎关注本站公众号,获取更多信息