开头先解释下全功能什么意思,所谓的全功能指的是支持绝大部分的SQL特性,像主键,触发器,约束,函数,存储过程,跨节点join等等。而且这些特性的支持对业务完全透明,业务可以像使用一台单机数据库一样来使用PGXZ。

PGXZ凝结了数平小伙伴们一年多的辛苦劳动,在 2015年10月份正式上线接入业务。当前主要的用户有微信支付,数据平台。最大的线上集群规模31个节点,每分钟55万请求

本文先介绍下PGXZ的渊源,然后对PGXZ的特性进行下总结。

要讲PGXZ就不得不先说下PGXZ的祖父--Postgresql。

PostgreSQL介绍

PostgreSQL 是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是目前世界上最先进,功能最强大的开源数据库管理系统。

现在被称为 PostgreSQL 的对象-关系型数据库管理系统是从伯克利写的 POSTGRES 软件包发展而来的。经过十几年的发展, PostgreSQL 是世界上可以获得的最先进的开源数据库系统, 它提供了多版本并发控制,支持几乎所有 SQL 特性(包括子查询,事务和用户定 义类型和函数), 支持广泛的客户端开发语言 (包括 C、C++、Java、perl、tcl 和 python)。而且几乎提供了所有 SQL 功能,包括 子查询、事务 以及用户自定义类和功能。

PostgreSQL支持大部分SQL标准并且提供了许多其他现代特性:**复杂查询、外键、触发器、视图、事务完整性、多版本并发控制**。同样,PostgreSQL 可以用许多方法扩展,比如, **通过增加新的数据类型、函数、操作符、聚集函数、索引方法、过程语言、扩展包等等**。并且,因为许可证的灵活,任何人都可以以任何目的免费使用、修改、和分发 PostgreSQL, 不管是私用、商用,还是学术研究使用。

从Postgresql8.4以来,PG增加了许多的企业级的特性支持,随着这些特性的发布,PG在世界范围内变得越来越流行。Postgresql当前的最新稳定版本是9.5,9.6beta版本已于本月发布,值得一提的是在9.6中Postgresql将支持多核并行执行SQL,通过这一技术其进一步巩固了自己最先进的开源数据库管理系统的地位。

PG是一个单机的数据库解决方案,说到这里PG肯定有同学问:有没有PG的数据库集群呢?答案是肯定的,下面介绍下PGXZ的Daddy,PGXC。

PostgreSQL-XC

PostgreSQL-XC 是一种提供写可靠性,多主节点数据同步,数据传输的开源集群方案,它包括很多组件,稍后会详细介绍这些组件,这些 PostgreSQL-XC 组件可以分别安装在多台物理机器或者虚拟机上。

写可扩展 (Write-scalable ):

是指可以部署多个数据库主节点,并且向这些主节点发出 update 语句,这种特性单个 PostgreSQL 库是无法提供的;

多主节点 (Multi-master ):

是指有多个主用数据库节点可以提供统一完整的数据库视图;

主节点数据同步(Synchronous):是指在一台数据库上更新操作会立刻呈现在另一台数据库中;

数据透明(Transparent):

是指数据位于不同的数据库节点中,当查询数据时,不必关心数据位于具体的节点。

可以将 PostgreSQL-XC 配置一台或者多台主机上, Postgresql-XC 数据以分布式存储,有几种方式,hash, replicated 或者随机分布,当向 PostgreSQL-XC 发送查询 SQL时, PostgreSQL-XC 会自动向数据节点发出查询语句并获取数据。

通过上面这些特性,PGXC对业务提供了一个统一的数据库视图,业务可以像使用一台Postgresql一样使用PGXC,而不用关心内部的数据细节。

PGXC的架构:

Coordinator:

协调节点,对外提供接口,负责数据的分发和查询规划,多个节点位置对等;CN上只存储系统的元数据,并不存储实际的业务数据

Datanode:

存储实际数据,并执行协调节点分发的执行请求,实际存储数据的节点;DN上存储业务数据

GTM:

全局事务管理器,负责全局事务管理;GTM上不存储数据

PGXC执行SQL的过程:

Step1:

业务发送请求到Coord节点,Coord节点向GTM请求 事务信息

Step2:

Coord发送SQL语句和事务信息到Datanode

Step3:

Datanode执行完SQL后返回结果给CN

Step4:

CN收集DN的结果并汇总会后返回给业务

PGXC的吞吐量扩展能力:

这个图展示了随着PGXC集群中节点规模的增加,扩展系数的变化,从图上看当前当前机器台数从1台变到10台,扩展系数在10台机器时差不多到6。数据平台在Z3机器上测试集群的事务处理能力,单节点时TPS能达到2W,按照同样的系统扩展,10台机器时这个值会达到12W TPS,以去年淘宝双11峰值8.6W TPS来算,就事务量这个层面上PGXC集群可以轻松cover。

PGXC使用上和单机的PG完全兼容,而且PGXC还继承了PG丰富的功能,触发器,函数,约束,主键,自定义函数等全部都继承了下来。除此之外PGXC还提供了一些数据库集群特有的功能,包括跨节点JOIN等。因此可以说PGXC是一个特性完备的数据库集群系统。

介绍完了爸爸,现在主角出场了。PGXZ是数据平台的小伙伴们在过去一年多的时间里面基于PGXC打造的关系数据库集群。数据平台定位PGXZ是高效,稳定,可靠的OLTP关系数据库集群。希望通过PGXZ来解决单机数据库面临的容量,性能,扩展性方面的问题。

PGXZ特性分析

集群分区表

PG的用户很多都会抱怨PG的分区表难用性能差。数据平台的小伙伴们为了改善业务的使用体验同时优化性能,专门为PGXZ开发了集群分区表。集群分区表在数据库内核中实现,业务无需像PG分区表那样创建继承表,关注插入数据的细节,大大简化使用。在易用性改善的同时,我们还对性能和资源使用进行了高度的优化,在分区较多时性能比PG的分区表高1-2个数量级。

分区表的逻辑结构如图,CN负责纵向分表,不感知表分区(横向分表)的逻辑, 看到DataNode上就是一张逻辑表,也就是说CN并不知道一张表是不是分区表。DN负责横向分表,根据分表字段将一张逻辑表划分为多张物理表,承载分区表的主要实现逻辑。

开发完成后我们针对微信支付的业务场景对分区表的性能进行了对比:

上面的优化前指的是社区的继承表实现,优化后是PGXZ的集群分区表实现,测试结果来看性能提升10-几百倍。

在线线性扩容

为了迎接业务的快速增长,系统不可避免的需要进行扩容,PGXC社区版本的实现使得扩容成本高昂,需要对业务进行长时间的中断。PGXC社区表的分布方式有以下几种,HASH最常用。

在HASH表中, PGXC通过如下方式决定一条记录的存储节点:

  **DN = Hash(row) % nofdn**

也就是说先对分布列计算hash值,然后使用这个值对集群中的节点个数取模来决定记录去哪个节点。这里有一个问题,扩容后节点数会变多,数据分布的计算逻辑就会导致已经存在的数据无法正常访问。为了解决这个问题,就必须把业务停掉,把所有数据导出,扩容后重新导入,在数据量较多时,这个过程会持续几天,这对一个每天几千万笔交易的系统来说显然是不能接受的。

为了解决这个问题,PGXZ引入了一种新的分表方法—sharded table。Sharded table的数据分布采用如下的方式:

1、 引入一个抽象的中间层--shard map。Shard map中每一项存储shardid和DN的映射关系。

2、 Sharded table中的每条记录通过 Hash(row) % #shardmap entry来决定记录存储到哪个shardid,通过查询shardmap的存储的DN。

3、 每个DN上存储分配到本节点shardid信息,进而进行可见性的判断

有了上面的支撑,在我们新加节点时,我们只需要把一些shardmap中的shardid映射到新加的节点,并把对应的数据搬迁过去就可以了。扩容对业务的中断也就仅仅是在切换shardmap中映射关系的时刻,时间大大缩短。

PGXZ的在线扩容系统已经经过了实践的检验,过程中我们发现了一些问题,正在加紧增强中。

数据倾斜应对方案--双KEY分布:

对于一个分布式数据库系统来说,不可避免的都会存在数据倾斜问题。微信支付商户系统中这个问题就更加明显。无论使用hash分布表还是shard表,同一个商户的数据都只会落到一个DN,京东每天的数据量和一个普通小商户的数据量肯定是天地差别,大商户一个月的数据可能就会把一个DN的空间塞满,这时系统就无法再存储更多的数据,系统只有停机一条路。因此我们必须要有一个有效的手段来解决数据倾斜,保证在表数据分布不均匀时系统仍然能够高效稳定的运行。

为了有效的应对这个问题,PGXZ团队设计了专门的方案来解决数据倾斜问题:

首先我们把系统的DN分为group,每个group里面:

1、 包含一个或者多个DN

2、 每个group有一个shardmap

3、 在建sharded表时,可以指定存储的group,也就是要么存储在group1,要么group2

4、 CN可以访问所有的group,而且CN上也存储所有表的访问方式信息

对于系统中数据量较大用户进行特别的识别,并为他们创建白名单,使用不同的数据分布逻辑:

普通用户使用默认的数据分布逻辑:

Shardid = Hash(merchantid) % #shardmap

大商户使用定制的数据分布逻辑:

Shardid = Hash(merchantid) % #shardmap + fcreate_time dayoffset from 1970-01-01

通过在大商户group分布逻辑中加入日期偏移,来实现同一个用户的数据在group内部多个节点间均匀分布。从而有效的解决数据分布不均匀问题。

举个例子来说明数据的大小商户的不同处理逻辑:

从这个例子可以看到,大商户的数据每天都有不同的shardid,不同的shardid也就意味着不同的数据库节点,从而可以达到数据在group内部的完美平衡。从当前的实践结果来看,大商户的数据在group内部的各个节点间很好的进行了平衡。

海量数据高效排序:

对一个数据库系统来说我们经常会遇到上亿条数据的排序。而且往往这些查询业务要求非常快速的返回。在微信支付的系统中我们就有这么一个例子。

业务在列表查询场景下会收到如下的查询sql:

select * from t_trade_ref where (ftotal_amount between 1 and 683771 and fcreate_time >= '2015-07-31 00:00:00' AND fcreate_time < '2015-08-30 00:00:00' and fmerchant_id = 7777777) ORDER BY ffinish_time DESC LIMIT 10 offset x;

这里在大商户场景下,每天的数据有300W,在查询范围为一个月时数据量可能会达到9000W,也就是说我们需要面向一个9000W数据的排序结果数据,而且这个面向的是终端用户,用户能够等待的时间是有限的。

表定义,建立集群分区表,按月分表,每个月一张表;对排序字段ffinish_time建立索引,这样每个分区进行扫描是可以使用索引。

执行计划的优化,CN下推order by和limit offset子句到DN;DN上在执行对应的sql使用使用Merge Append算子对各个子表执行的结果进行汇总输出,这个算子本身会保证输出是有序的,也就是说对子表进行索引扫描,同时Merge Append又对各个子表的结果进行归并,进而保证节点本身的结果是排序的。CN对多个DN的结果同样使用Merge Append进行归并,保证整个输出结果是有序的,从而完成整个排序过程。

排序性能测试结果:

9000W数据的排序在最短可以在25 ms内完成,QPS最高可达5400。

整体方案对业务来说,只需要按照条件创建索引,其他的数据库内核会自动处理,从而保证了解决方案的通用易用。

冷热数据分离

业务的数据的访问频率随着时间都会有一个下降的趋势,虽然数据的访问量小了,但是这些数据还是要保留,如果继续使用和热数据同样的存储设备,成本往往难以承受。如果能够对热数据和冷数据采用不同的存储设备,就可以大大降低业务的使用成本。

为了有效的降低业务的资源成本,PGXZ针对性的开发了冷热数据分离的功能,内核原生态支持数据的冷热分离,业务无需感知底层存储介质的不同,对外提供一个统一的数据库视图。

冷热数据分离的整体逻辑框图如下:

1、冷热数据使用不同的节点group存储,这些节点组内部使用的机型不同,从而达到冷热分离节省成本的目的。

2、冷热分离中大商户问题依然存在需要专门考虑,大商户在冷数据中也有专门的存储大商户group。

3、建表时业务根据需要指定热数据和冷数据的分布集群。

1、表按天分区,每张表在冷数据组和热数据组节点中都有一张物理表。

2、数据写入时都写入到热数据部分,对应的冷数据表为空表。

3、冷热数据转换的阈值是集群公用的值,是距离当前日期多少天的数值。

4、当冷数据阈值达到时,后台搬迁变冷的当天数据。

5、热数据搬迁到冷数据集群后,热数据部分的表truncate为空表。

通过上面的逻辑结构,业务无需关心集群的冷热数据存储情况,系统即可实现自动的冷热分离。

并行优化

随着当前硬件的发展,系统资源越来越丰富,多CPU大内存成了系统标配,充分利用这些资源可以有效的提升的处理效率优化性能。我们在2014年底开始进行postgresql多核执行优化。

PG9.6社区版也会包含部分并行化特性,但是没有数据平台这么丰富,数据平台PG团队在参加纽约PG技术大会时和PG社区核心成员进行了沟通,腾讯会根据自己的实践和线上经验为PG社区的并行化提供建议。

数据平台TPG并行化的相关工作:

l 系统创建一个全局的共享内存管理器,使用bitmap管理算法进行管理。

l 系统启动时创建一定数据的Executor,这些Executor用来执行执行计划的碎片。

l 系统会创建一个计划队列,所有的Executor都会在任务队列上等待计划。

l 每个Executor对应一个任务结果队列,Executor在输出结果时就把结果的指针挂到结果队列中去。

l 计划队列,结果队列,计划分片执行结果都存放在共享内存管理器中,这样所有的进程都可以访问到这些结构。

l Postgres会话进程在收到sql时,判断是否可以并行化,并进行任务的分发;在结果队列中有结果时就读出返回。

数据平台完成优化的算子:

l Seqscan

l Hash join

l Nestloop join

l Remote query

l Hash Agg

l Sort Agg

l Append

测试环境:

     24核超线程

     64G内存

     1G FusionIO卡

各个算子的优化结果:

整体来说性能普遍是优化前的10-12倍,优化的效果比较明显。

两地三中心容灾

数据库的两地三中心容灾能力是数据库的必备能力,对于金融类业务数据安全是最基本也是最重要诉求,因此我们必须要要有高效稳定的数据容灾能力。我们也为PGXZ建设了完善的两地三中心自动容灾能力。PGXZ的两地三中心部署结构如下:

在每台物理机上部署 CAgent,agent收集机器状态并进行上报,并进行相应的告警和倒换执行功能。

每个IDC至少部署一个JCenter,JCenter负责收集上报每个agent上报的状态到ZK集群。这么多个JCenter中只有一个是主用,主用的JCenter除了进行状态上报还进行故障裁决和倒换。在主用的JCenter异常后,系统通过ZK自动裁决挑选一个备用的JCenter升主。

JCenter和CAgent是两地三中心的控制和裁决节点。

对于数据库节点,CN在每个IDC至少部署一个。DN在每个中心部署一个,一个为主,另外两个并联作为备机放在主机上,一个为同步备机,另外一个为异步备机。

在主机故障宕机时,JCenter优先选择同城的备机升主。

自动化运维监控系统

高效,稳定,可靠的数据库集群离不开高效可靠运维系统,数据平台也为PGXZ打造了高效一套完备的运维监控系统。当前可以做到系统指标实时监控,远程故障倒换,在线扩容,冷热数据自动搬迁。

这里是PGXZ的指标展示系统

当前PGXZ线上集群规模:

当前最大的集群是微信支付集群:5个CN,2台gtm,24组DN

下一步计划:

1、 持续进行运维能力建设和系统易用性的改善。

2、 压缩引擎开发

3、 PostGIS的移植

其他

文章来源于腾讯云开发者社区,点击查看原文