秒级实现PostgreSQL版本升级方案

社区广播:运维派(Yunweipai.com)是国内最早成立的IT运维社区,欢迎大家投稿,让运维人不再孤寂的成长!

PostgreSQL

 一、为什么要升级PostgreSQL数据库

看到这个题目,很多使用 PostgreSQL 的同学可能会这样问,我当前使用的 PostgreSQL DB Instance 的 Major Version 虽然低一些,但是它一直很稳定,并且暂时也能满足当前业务对性能的需求,那我为什么还要去花费时间,消耗经历去做数据库升级呢?

1、对 PostgreSQL 熟悉的人或者经常看官方文档的同学会发现,基本上每年 PostgreSQL 都会有一个大版本发布,而随之发布的还有一些新特性,比如说

9.3版本的新增物化视图、支持事件触发

9.4版本新增的 jsonb 字段类型、可以通过 sql 命令 altersystem 来直接修改数据库参数命令以及新增的 logicaldecoding 特性

9.5版本新增的支持 upsert 特性、新增的 BRIN 索引

9.6版本新增的对顺序扫描的并行执行、为了提高数据库的可靠性,允许多台 standby数据库同时处于 sync 状态

10.0版本新增的支持表级的逻辑复制,允许对其进行发布和订阅、定义表分区及提高并行查询的效率

这里简单的列一下每个版本的新特性,如果想了解个多的新特性或者每个特性的详细信息,请参考https://www.postgresql.org/docs/current/static/release.html

每一个新特性在其特定的使用场景下,都会对数据库和应用程序的性能有质的飞跃,都会极大的节省开发及运维人员的时间成本、人力成本,所以我们为什么不站在巨人的肩膀上前行呢?

2、PostgreSQL 社区成员每年只会同时维护5个主板本的 PostgreSQL 数据库,也就是说每个数据库版本都是有生命周期的,从今年九月份(2017-09)开始,对于9.3以前的版本数据库不再进行维护,当然你依然可以在官网上下载9.3以前的版本使用,但是如果在使用过程中出现了小 bug,那么社区成员只会在维护的版本中修复,9.3以前的版本不会进行任何修改,所以为了避免低版本的 bug 引发应用程序故障崩溃,升级数据库还是很有必要的。

数据库

二、传统升级方案剖析 

数据库升级分为两种,一种是小版本迭代升级,另一种是主板本升级。小版本升级很简单,只需要重启一下数据库即可,我们这里主要说一下主板本升级。做过数据库升级方案的同学或者熟读官方文档的同学可能知道,官方提供两种大版本升级方案,分别是 pg_upgrade 和 pg_dumpall,这里对这两种方式的优缺点做一下整理:

数据库

在我们生产环境中,尤其是核心的生产环境中,数据库都是以集群的方式存在的,因为数据是一个公司的核心命脉,所以如果要以传统的方式来升级数据库,绝大部分同学会选择使用 pg_dumpall 的方式来实现,但是因为 pg_dumpall 的升级时间是与整个数据库集群的数据量成正比的,所以升级过程中需要长时间停止程序的写服务,这对核心的业务程序(特别是有99.999保证的程序)来说是不可接受的,那么既要升级数据库主板本,又要保证核心程序的99.999,就需要借助其他方式,而 PGQ 就可以实现秒级升级数据库。

三、PGO原理及特征       

首先我们先来了解一下什么是 pgq,其实 pgq 是 skytools 的一个模块,而 skytools 是 skype 公司的一个复制和容错的工具包。skytools里面有三个模块,分别是 pgq、londiste 和 walmgr。

pgq 是一个用 PL/pgSQL、Python 和 C 编写的一个队列系统,它分为3个部分,分别是 producers、ticker 和 consumers,其中 producers 负责调用数据库的存储程序将数据转换成 event,ticker 则负责将 event 进行批次划分,而 consumers 则负责将 event 转换成 sql 语句;londiste 是一个用 Python 写的复制工具,它利用 pgq 做为事件传输;walmgr 则是一个脚本,主要用来对 wal 做归档,对数据库做初始化备份以及恢复。

在 pgq 整个集群中还有 node 的概念,分别是 root node、branch node、leaf node。Root 节点是整个集群的数据唯一入口,同时负责向下游推送 event,root 节点的下游可以为 branch 节点、leaf 节点以及通过调用 pgq 的 api 接口自定义程序将数据同步到其他平台,比如 greenplum、elasticsearch、kafka、sqlserver 等等;branch 节点是转换节点,负责接受上游推送下来的数据写入到自己对应的 db 中,同时将 event 推送到下游(如果有下游的情况下),branch 可以挂载在 root 节点下,也可以挂载在其他 branch 节点;leaf 节点负责接受上游推送的 event 写入到自己对应的数据库中,它的挂载方式与 branch 节点一样。

个人一直将 pgq 做为一个增量数据同步工具来使用,现在对 pgq 的特点进行一下总结:

1、数据从一个节点到下游节点可以在毫秒级完成,数据同步的快慢由自定义时间和自定义批次量的大小来根据业务需求灵活控制;

2、pgq 对 root 节点和 branch 节点的下游挂载节点个数没有限制,如果一个 branch 节点出现故障,那么可以将此节点的下游节点通过 change-provider 命令挂载到其他节点,在切换的过程中由 ticker 值来控制保证数据不会丢失,而故障节点会一直重试,直到故障恢复或在集群中摘除次节点;

3、root 节点可以根据业务需要通过 takeover 命令来和 branch 节点进行切换,同样可以保证数据不会丢失;

4、pgq 的同步对象是 tables 和 sequences,可以一次添加多张表进行同步,pgq 会对表先做 copy 全量同步,然后在进行增量同步,同步过程中不会影响其他表;

5、pgq 需要同步表必须还有主键或者非空的唯一索引,不满足此条件的表无法加入到同步集群中;

6、pgq 是一个开源工具,可以调用其 api 接口将数据同步到其他平台,如 greenplum、elasticsearch、kafka、sqlserver……

7、pgq 是单进程程序,所以不适合一次性操作上百万上千万的数据,建议分批次多次执行;

8、官方发布的 release 版本目前只支持到 pg9.5,需要修改源码中 keywrods 的路径才可以支持 pg9.6 以及 pg10 版本;

原 PGQ 同步集群架构

架构

branch 节点切换后的同步集群架构

四、PostgreSQL主板本升级过程

1、先要确定 pgq 的版本与 PostgreSQL 的版本是否匹配,如果不匹配需要手工修改一下 pgq 的源码

      vi sql/pgq/triggers/stringutil.c

          – * src/include/parser/keywords.h

+ * src/include/common/keywords.h

2、安装 pgq 同步集群,需在低版本数据库配置 root 节点环境,高版本数据库配置 branch 节点环境

两个节点都需要配置 pgqd.ini 文件,同时 root 节点配合 pgq_root95.ini 文件,branch 节点配置 pgq_branch96.ini 文件,配置文件的名字自己定义即可

         vi .pgqd.ini

[pgqd]
logfile = pgqd.log
pidfile = pgqd.pid
base_connstr = host=l-pgtest1.dev user=pgq password=pgq port=5432
database_list = postgres
ticker_period = 1

—————————

vi pgq_root.ini

[londiste3]
job_name = pgq_root
db = host=l-pgtest1.dev port=5432 dbname=postgres user=pgq password=pgq
pgq_queue_name = pgq
logfile = pgq_root.log
pidfile = pgq_root.pid
—————————-
vi pgq_branch.ini

[londiste3]
job_name = pgq_branch96
db = host=l-pgtest1.dev port=8432 dbname=postgres user=pgq password=pgq
pgq_queue_name = pgq
logfile = pgq_branch96.log
pidfile = pgq_branch96.pid

pgq_queue_name 在整个 pgq 集群中要保持一致,而 job_name 在整个集群中要唯一,同时这个集群中所有的数据库都要创建一个具有 superuser 权限的用户,比如此例中的 pgq

创建 root 节点:londiste3 pgq_root.ini create-root pgq_root ‘host=l-pgtest1.dev port=5432 dbname=postgres user=pgq password=pgq’

创建 branch 节点:londiste3 pgq_branch.ini create-branch pgq_branch96 ‘host=l-pgtest1.dev port=8432 dbname=postgres user=pgq password=pgq’ –provider=’host=l-pgtest1.dev port=5432 dbname=postgres user=pgq password=pgq’

3、添加同步对象(表)

先要对数据库的结构进行同步,因为 pgq 只关心数据,所以各个节点的数据结构要保持一致,然后确定要添加的同步表具有主键或者唯一索引,否则添加同步表报错

londiste3 pgq_root.ini add-table tablename1 tablename2   — 以此命令为模板来添加同步表

4、所有的同步表都添加完后,确定一下同步集群是否正常,可以通过各个节点的日志来看,也可以同步命令来看

londiste3 pgq_root.ini status

5、通过切换 root 节点的方式来实现数据库升级,在 branch 节点上执行 takeover 命令来实现

londiste3 pgq_branch.ini takeover pgq_root   –其中 pgq_branch.ini 是 branch 节点的配置文件,pgq_root 是 root 节点名

6、如果是在本服务器上进行操作,还需要重启一下高版本数据库实例,因为要改一下 db instance 的端口号;如果是升级到其他服务器则不用进行此操作

五、PostgreSQL主板本升级总结

1、数据库升级秒级实现,应用停服时间短;

2、升级回滚方式灵活,同样是以切换 pgq root 节点的方式来实现;

3、可以保证升级前后 PostgreSQL 的兼容性,尤其是一些 Extension 的兼容性 ;

原文来自微信公众号:Qunar技术沙龙

网友评论comments

发表评论

电子邮件地址不会被公开。 必填项已用*标注

暂无评论

Copyright © 2012-2017 YUNWEIPAI.COM - 运维派 - 粤ICP备14090526号-3
扫二维码
扫二维码
返回顶部