天天看点

PostgreSQL 最佳实践 - 块级增量备份(ZFS篇)方案与实战

在实际的生产环境中, 当数据库越来越多, 越来越大.

备份可能会成为比较大的问题, 传统的逻辑备份对于大的数据库不适用(因为备份和还原可能是比较耗时的, 而且也不能回到任意时间点, 还会造成数据库膨胀(长时间repeatable read隔离级别), 好处是可以跨平台恢复, 可选恢复表等).

而基于xlog的增量备份, 虽然备份可以在线进行,同时支持恢复到任意时间点,但是恢复需要apply从基础备份到恢复目标之间所有产生的xlog,如果基础备份做得不频繁,那么恢复时可能需要apply的xlog文件数很多,导致恢复时间长。

如果频繁的执行全量基础备份可以解决恢复时间长的问题,又会带来一系列问题,占用跟多的空间、占用更多的备份带宽、消耗数据库读资源、备份时间长等问题。

这些问题随着数据库变大而放大。

有什么好的解决方案么?

为了解决增量备份的问题,我们可能马上会想到类似oracle的增量备份,只需要上次备份以来的变更或新增的数据块。

postgresql目前也支持这种备份方式,我会在下一篇文档中介绍。

除了数据库本身支持的块级别增量备份,我们还可以使用文件系统的快照来支持块级增量备份,例如zfs或者btrfs。

zfs在这里主要用到它的压缩, 去重和snapshot功能.

使用zfs可以减少存储空间, 加快恢复速度.

可以放在crontab定时执行, 例如2小时1次.

最近在写一个集中式的postgresql基于块的增量备份的case,刚好完美的解决了大实例的备份难题.

集中备份主机环境

PostgreSQL 最佳实践 - 块级增量备份(ZFS篇)方案与实战

归档主机配置(本例归档主机和备机主机使用同一台主机)

配置zfs, 开启压缩, 同时注意写性能至少要和网卡带宽相当, 否则容易造成瓶颈.

一旦造成瓶颈, 可能导致主库xlog堵塞膨胀(因为归档完成的xlog才可以重用或被删除).

考虑到写居多, 所以考虑加一个性能好的ilog设备. l2arc没必要加.

zpool使用raidz1+ilog+spare的模式.

raidz1盘的数量9=2^3+1, 实际上本例使用的盘数11(当然你可以多vdev strip的模式例如12块盘分4组vdev raidz1 3+3+3+3, 可用容量为8块盘).

1个ilog因为这个设备底层使用了raid1 的模式, 所以没有再次mirror. 如果底层是jbod模式的话, 建议用mirror防止ilog数据损坏. 1块hot spare.

扇区大小选择4kb.

配置zpool 根 zfs默认选项, 后面创建的zfs可以继承这些选项.

创建归档目录, 日志目录, pghome目录等.

配置postgresql归档, 例如rsync服务端, nfs, ftp 等, 如果使用nfs注意固定一下nfs端口.

本文以nfs为例介绍归档配置.

配置nfs端口固定

配置nfs目录, 每个pg集群一个目录, 存放该集群的归档文件.

开启nfs服务, or service nfs reload.

( (注意如果主节点有流复制的ha的话, 主备都需要配置) )

配置nfs挂载, 数据库启动用户的权限, 如果有必要的话, 可以配置nfs超时.

推荐以下配置

另一种是配置在启动脚本里面

主节点集群配置归档命令(如果以前没有开启归档的话, 需要重启数据库开启归档) (注意如果主节点有流复制的ha的话, 主备都需要配置)

首先要配置sudo, 因为nfs挂载过来权限后面需要调整, 所以最好使用sudo以免归档和还原失败.

配置归档和还原命令 :

主备同时配归档没有问题(因为原版的postgresql备节点不会触发归档), 除非你像这样改了pg代码.

<a href="http://blog.163.com/digoal@126/blog/static/163877040201452004721783/">http://blog.163.com/digoal@126/blog/static/163877040201452004721783/</a>

配置zfs(同归档存储节点的配置)

考虑到写居多, 所以需要加一个ilog设备. l2arc没必要加.

zpool使用raidz1+ilog+spare的模式, 盘的数量11+1+1, 1个ilog因为这个设备底层使用了raid1 的模式, 所以没有再次mirror.如果底层是jbod模式的话, 建议用mirror防止ilog数据损坏.

设置zpool默认zfs的属性, 以便创建后面的zfs继承这些属性(同上). 主要修改压缩和文件访问时间.

因为是集中式的流复制场景, 所以存储的io可能会比较大, 前面我们考虑了使用ilog来提高写性能, 同时我们还需要考虑数据压缩, 节约存储空间, 我们这里选择lz4压缩算法, 速度和压缩比比较均衡.

去重(dedup)暂时不开, 因为需要消耗大量的内存, 具体耗多少内存, 可以使用zdb -s zp1来评估.

创建数据库集群对应的zfs, 一个数据库集群对应一个zfs, 方便我们做zfs snapshot.

命名的话, 最好结合ip和数据库的业务名称.

配置网卡绑定(可选), 当带宽不够时可选.

参考

<a href="http://blog.163.com/digoal@126/blog/static/163877040201451823232145/">http://blog.163.com/digoal@126/blog/static/163877040201451823232145/</a>

如果所有主数据库节点产生xlog的速率超过了网卡速率, 那么建议多网卡绑定来解决网络带宽的问题.

(这样的话所有的主节点pg_hba.conf的配置都指向这个虚拟ip, 以后迁移的话, 虚拟ip迁移走, 主节点的pg_hba.conf可以不用修改, (当然如果有dns的话, 也可以配置为主机名, 就没有这么麻烦了))

主节点配置pg_hba.conf允许虚拟ip过来的流复制协议连接.

一个用户对应一个主节点, 每个用户编译各自的pg软件(因为不同的实例,pg软件编译参数可能不一样).

编译与主节点一致的postgresql软件以及插件.

编译项见主节点的pg_config输出或查看源编译文件的config.log.

例如 :

自定义的插件查看, 可以查看$pghome/lib目录或, 最好是拿到数据库档案, 翻阅编译过的插件, 新增的动态链接库等.

例如

配置环境如下

在备份机, 所有的表空间都不使用软链接, 直接使用$pgdata/pg_tblspc/oid目录.

recovery.conf, postgresql.conf, (注意监听端口的修改, 因为一台主机开启多个standby, 避免端口冲突., 注意pg_log位置的修改. )

配置.pgpass ,设置流复制秘钥

配置主节点pg_hba.conf, 允许备机的虚拟ip访问. (如果是流复制集群的话, 主备两边都需要配置.)

开启standby进行恢复, (随便使用open模式hot_standby = on 或 recovery模式hot_standby = off)

recovery.conf中添加 :

确保当主备网络中断时可以从归档继续恢复

1. nfs 监控

2. nfs 端口监控

3. pitr上所有数据库集群的端口监控

4. pitr上所有数据库集群的stream wal receiver进程监控

5. 流复制延迟监控

6. 归档文件时间戳监控, 发现归档失败.

7. 恢复监控, 10分钟内如果没有新建的xlog文件则告警.

vi /usr/local/nagios/libexec/mon_pitr.sh

因为pgdata是700的权限, 所以find这些目录会受到权限限制, nagios监控用户会报错, 所以可以把这个命令加入sudo

1. 如果归档失败, 主节点的pg_xlog目录会暴增, 不能rotate. 所以pg_xlog目录尽量配置大一些, 同时加上监控.

当然更靠谱的方法是使用多个归档路径, 一个失败就归档到下一个路径. 但是需要注意调小一点超时. 否则每次归档都要等待超时也会造成拥堵.

2. 对nfs主机需要添加监控, 以防有问题.

3. 对于主节点有流复制ha的情况, nfs挂载, 归档都需要在主备节点同时配置. nfs的exports也需要配置允许主备节点的ip rw.

4. 因为是集中的归档和流复制所以务必注意网络带宽是否够用. 不够用的话, 可以考虑多网卡绑定增加带宽.

5. nfs端口固定后, 可以防止nfs服务器重启后或服务重启后, nfs client需要重新mount的问题. 或者防火墙精确控制的问题.

8. 关于zfs的写入优化. 参见末尾

9. 关于zfs的压缩优化. 参见末尾

10. 多数据库集群的路径冲突问题. 不使用pg_tblspc/link, 直接一个集群一个zfs dataset来解决.

11. 开启归档后, standby节点参数修改, 如wal keep 改小, listen port 修改避免冲突, log_directory目录位置修改.等

12. zpool创建时, 务必设备名建议by-id, 放在因为设备别名变更后导致无法使用.

例如把zil和spare设备换成uuid.

13. slog的大小4g 上下就足够了.

14. 操作系统内核参数稍作调整.

15. 不建议使用linux, 因为zfs在linux下有一定的性能问题, 可以考虑freebsd. 参见

<a href="http://blog.163.com/digoal@126/blog/static/16387704020145253599111/">http://blog.163.com/digoal@126/blog/static/16387704020145253599111/</a>

<a href="http://blog.163.com/digoal@126/blog/static/1638770402014526992910/">http://blog.163.com/digoal@126/blog/static/1638770402014526992910/</a>

<a href="http://blog.163.com/digoal@126/blog/static/16387704020145264116819/">http://blog.163.com/digoal@126/blog/static/16387704020145264116819/</a>

16. 集中式的配置standby节点可能导致资源不够用, 例如shared_buffer, 要调小的话同时还需要调小connection_max 等关联参数, 而这些参数在postgresql.conf - hot_standby=on 的情况下, 需要检测是否大于等于上游节点的参数, 所以建议standby节点的hot_standby=off, 然后就不需要检测了, 然后就可以调小shared_buffer, connection_max等了.

如果要打开hot_standby=on, 那么再调会connection_max 等检测项即可.

17. 原来如果主节点已是流复制的ha节点, 可以把recovery.conf或recovery.done修改一下.

因为默认情况下standby节点不会产生archive, 所以不必担心重复的archive文件.

所以双方挂载对方的pgarch目录到pgrestore即可.

如果想让standby也产生archive, 参考我前面写的blog, 修改一些源代码.

重启流复制备库生效.

9. man nfs 超时