共计 6962 个字符,预计需要花费 18 分钟才能阅读完成。
1 月 11 日,腾讯云 TDSQL PG 开源版(开源代号 TBase)再降级:分布区表关联查问性能(join)晋升超 10 倍,同时晋升了产品在分布式场景下的易用性,减少灵便可用的性能组件。
该降级版本在第十一届 PostgreSQL 中国技术大会上正式颁布,同时更新文档已同步在 GitHub 上。依靠社区和外部业务零碎的实际测验,TDSQL PG 开源版根本放弃每月一次小降级、每半年一次重大降级的节奏,助力泛滥开发者利用前沿数据库技术。
本期将为大家深度解读 TDSQL PG 开源版降级个性,具体包含:分区表性能加强、异地多活易用性加强、分布式死锁自动检测并解锁性能、2PC 残留自动检测并清理性能等硬核干货。
TDSQL PG 版开源倒退历程
TDSQL PG 版(原名 TBase)是腾讯自主研发的新一代分布式国产数据库,其具备业界当先的 HTAP 能力,属于 MPP 无共享架构,在企业级平安方面采纳三权分立平安体系。
图片
2020 年,腾讯云正式发表数据库品牌 TDSQL 的全新策略降级打算。原有的 TDSQL、TBase、CynosDB 三大产品线对立降级为“腾讯云企业级分布式数据库 TDSQL”。全新降级后的腾讯云 TDSQL 涵盖分布式、剖析型、云原生等多引擎交融的残缺数据库产品体系。TDSQL PG 版则是 TDSQL 系列产品之一,次要针对 HTAP 场景。
下图是 TDSQL PG 版的总体框架。左上角为事务管理器 GTM,负责整个集群的事务管理和全局事务的协调。右上角为协调节点 CN,它是业务利用拜访的入口,每个节点对等,业务连贯任意节点,最终返回的数据都雷同。右下角为数据节点 DN,每个 DN 只存储局部用户数据,所有 DN 一起组成残缺的数据集。最右边和最下边的局部属于管控零碎,负责零碎的资源管理和告警监控。
图片
TDSQL PG 版最早可追溯到 2008 年,2012 年其公布第一个分布式版本,2015 年其公布第二个分布式版本。截至目前,TDSQL PG 版曾经在泛滥市场客户中失去利用,包含数字广东、云南公安、微信广告、微信领取等。值得一提的是,TDSQL PG 版在 2019 年中标 PICC,成为行业内第一个胜利落地保险外围零碎的分布式国产数据库。
图片
TDSQL PG 版在 2019 年 11 月 7 日正式发表开源。开源地址在 Github 平台上,下图是供宽广开发人员应用参考文档的 wiki 地址。
图片
TDSQL PG 版开源对用户有重要价值,别离体现在:
版本通过大量业务验证,成熟稳固,开源版本和腾讯自用版本共基线,可能帮忙用户疾速构建外围业务。同时反对 OLTP/OLAP 能力,提供一站式数据库解决方案。平安可控的企业级分布式数据库能力,腾讯业余研发经营团队继续投入开发和保护,推动社区提高。团队踊跃回馈开源社区,即时响应用户需要,努力创造开源社会价值。
TDSQL PG 版开源个性回顾
2021 年 7 月,咱们进行了 TDSQL PG 版 2.2.0 版本的降级。2.2.0 降级次要包含四个方面:内存治理优化,提供会话内存视图,进行优化治理;优化分布式执行器、优化器;分布式调优性能加强;分布式执行可视化能力加强。图片
2.1 执行器 / 优化器优化
咱们将子查问在外部优化成一个关联查问,进步查问效率。以视图中的表格为例,须要依据表 A 中的 ID 找到表 B 中每一条对应 ID 的数据,再用表 A 的值与表 B 中值的 MIN 进行比拟。在优化前,因为这是一个子查问,如果表 A 有 1000 条记录,则 A 中每一条记录都要在表 B 进行全量扫描。做完这个查问至多要将表 B 扫描一千次,这样做的老本十分高。在优化后,因为表 B 须要取 B 的 MIN 最小值,且咱们须要利用 id 做 join,所以能够先扫描一遍 B 表,依据 id 先进行汇集,把每一个 id 最小的 MIN 值取出来,生成汇集表,最初汇集表与表 A 进行 hash join,因而咱们只需将 B 表进行一次扫描即可。图片
咱们还对 distinct 进行性能优化。在优化前,须要将所有数据从 DN 节点拉到 CN 节点,由 CN 节点进行 distinct 的去重操作。因为分布式系统数据量特地大,如果全副拉到 CN,会导致数据量大,网络负载高,CN 也会成为单点瓶颈,难以施展分布式个性。咱们针对此类情况进行优化。先在 DN 本地进行局部的 distinct 去重,使得每个 DN 能够并行计算,并行后将后果全副发到 CN 上,由 CN 进行最终的去重操作,缩小了大量的网络交互,充分发挥出分布式数据库的个性。图片
在对优化器进行优化后,咱们取局部 TPCDS 规范测试集进行测试,发现有些 SQL 的性能能够晋升上千倍。图片
2.2 内存治理优化
咱们提供 Memory 的内存视图详情,可能具体看到每一个过程占用的内存状况。除了对视图进行加强外,咱们还对内存应用进行具体优化。图片
下图展现的是假如有一个用户连贯,这个连贯在拜访一万张表后的内存占用状况(拜访完该连贯还没有退出、仍处于闲暇状态时的内存占用状况)。从下表中能够看到,TopMemoryContext 上呈现数量级增长,实现 10 倍以上晋升,CacheMemoryContext 也实现 20 倍的晋升。图片
针对显著闲暇的连贯却占用大量内存的不合理状况,咱们进行了优化。咱们将内存的应用分为两局部:第一局部是 RelCache,即用户数据表的 Cache;第二局部是 Cat Cache,即元数据的 Cache。如果须要对某个 Rel 进行 Cache,咱们会将新来的项放在 Relation LRU List 的最后面,尔后每次来新的项咱们都往前面加。当 LRU 我的项目超过预约意义的参数时,咱们会从后往前去遍历 LRU,将援用计数为 0 的 Relation 的内存项开释掉。Cat LRU 元数据缓存也同理,咱们将新来的某条元数据缓存,将其放在 Cat LRU List 的最后面,再从后往前进行遍历,将援用计数为 0 的项进行删除,从而开释内存。由此能够将局部占用内存大且低频应用的闲暇连贯,通过 LRU 将其替换进来,使会话内存缩小 55.7%。图片
对于分布式系统,除了单点外还要思考分布式内存治理。当一个应用程序连贯到 CN 后,CN 须要跟 DN 进行数据通信。但它与 DN 的通信的 DN 过程须要向本地的 Pooler 申请连贯,Pooler 会将本地缓存的局部到 DN 的闲暇连贯调配给 CN,尔后 CN 能力与 DN 进行通信。Pooler 本地缓存了很多到 DN 的闲暇连贯,实时筹备为 CN 提供服务,以至于存在许多闲暇连贯。对此,咱们在 Pooler 外部上线实时检测闲暇连贯的性能,将大于配置参数的连贯开释掉,使得闲暇连贯占用缩小 89.3%。图片
通过优化后,在 2CN、2DN 的状况下,仍旧是一个连贯在拜访一万张表后的内存占用状况,优化前总内存占 51.4M,经优化后只占 5.4M。节点外部 DN 主动开释闲暇连贯,闲暇连贯间接缩小 89%,通过 RelCache LRU 替换后,CN 连贯内存缩小 55%。图片
2.3 分布式执行可视化
以下图为例,表 A 和表 B 进行 join,A 表作为散布键,B 表作为非散布键,咱们进行 join 时要将 join 的过程下推到 DN 节点执行,但因为表 B 不是散布键 join,所以须要对表 B 按 f2 字段进行重散布。在重散布过程中,DN1 上有一个 backend 过程,须要扫描本地的表 B,把扫描到的局部数据留给本地的 DN 节点,局部数据则重散布到 DN2 数据节点。所以一次重散布中,本地会新创建一个 DN1 的 backend 过程进行数据扫描,还要创立另一个 backend 过程负责发送数据给 DN2。图片
利用分布式可视化的能力,能够查到任意一个用户的 session id,查到 session id 后,能够依据 session id 查到对应的在不同 CN、DN 上的各个过程目前在做什么。比方这个节点咱们须要做 hash join,因为须要依据 f2 字段做数据重散布,当初在期待重散布的数据,另外一个过程是扫描表 B,扫描完后会提供给后面的过程,能力进行 hash join,CN1 则是在执行查问事务。通过分布式执行过程的可视化视图,咱们能够具体晓得一个 SQL 上来各个节点在做什么。图片
下图展现的是分布式可视化性能的应用办法,详情可参考 Github 上的 wiki 地址:
图片
TDSQL PG 版开源重磅降级
TDSQL PG 开源版此次降级 V2.3.0 版本包含四个方面:分区表能力加强、异地多活易用性加强、分布式死锁检测、2PC 残留主动清理。图片
3.1 分区表能力加强
针对分区表能力,本次 TDSQL PG 版降级,整体响应速度更快,有效应对此前业界依然面临数据量大时读写性能慢等问题。新版本通过分区表性能加强,包含减少 hash 分区类型、反对 default 分区子表创立、分区父表索引操作主动同步子表等,实现分区表便捷治理;同时,新版本实现了分区剪枝性能晋升 30%,分布区表关联查问性能(join)晋升超 10 倍,完满解决查问效率问题。
具体来说,在原有反对 range 和 list 分区表的根底上,TDSQL PG 版新增 hash 分区表性能。用户在创立时能够指定该分区表为 hash 分区表,再指定分区键,同时须要指定 hash 模数和余数。
TDSQL PG 版还新增了 default 分区。在上一版本中,在创立分区表且创立子分区时,如果没有创立 default 默认分区,用户插入数据时,如果插入不属于指定分区的其余数据,会呈现报错。在本次降级后,如果插入的数据不属于其余指定子分区,所有数据会落到 default 分区。比方下图左边的例子,2019 年 12 月和 2020 年 3 月的数据,都不属于指定的其余子分区,因而会落入 default 分区。其长处是不须要报错,同时必要时能够查问不属于指定分区的其余零散值。该性能目前仅反对 range 和 list 分区,不反对 hash 分区。因为在指定 hash 的模数和余数后,数据就必然会落在指定分区,不存在不属于指定分区的状况。图片
TDSQL PG 版也反对分区键更新。在上一版本中,如果要更新创立表时指定的分区键,就会呈现报错,不容许更新。新版本对此进行降级。在下图右边的例子中,一个分区子表存储 0 到 30 的数据,另一个分区子表存储 30 到 60 的数据,用户能够对分区键即 id 键进行更新,将 id 从 25 改为 50,数据会主动从原来的分区转移到新的分区。
此外,TDSQL PG 版还反对分区父表建索引主动同步子表。在上一版本中,如果要为分区表建索引,只能给某个指定子表建分区,不能给父表建分区。在新版本中,咱们对此进行优化,反对在父表上指定建分区。在下图左边的例子中,假如要给 tbl 表的 id 字段建索引,在创立后它会主动将索引同步到所有子分区上,比方 2020 年 1 月分区、2020 年 2 月分区和 default 分区。用户只须要在父表上执行一条 SQL,它就会主动在所有子分区上全副创立该索引,其长处是不便用户对分区里的索引进行保护。咱们也反对创立惟一分区,但须要蕴含分区键。图片
除了分区能力的加强,TDSQL PG 版还引入 partition-wise join,对原有性能进行晋升。假如有两个分区表,别离为 A 表和 B 表,它们的分区数量完全相同,且分区的字段类型统一。如果没有 partition-wise join,在进行 join 时,须要先将 A 表中所有子分区的数据全副捞取,再将 B 表中所有子分区的数据全副捞取,再用 A 表全量数据与 B 表全量数据进行 join,这种操作形式的数据量十分大。在引入 partition-wise join 后,因为两个分区键为同一类型,且分区数量雷同,咱们能够将 A 表的分区 1 与 B 表的分区 1 进行 join,A 表的分区 2 与 B 表的分区 2 进行 join。咱们并不需要将 A 表的全量数据与 B 表的全量数据进行 join,只须要将对等的分区进行 join 即可,从而使性能失去大幅晋升。
下图是该性能实际效果的测试比照。在 partition-wise join 关上的状况下,与上一版本相比,最新版本的性能有 10 倍的晋升。图片
3.2 异地多活的易用性加强
另一重要降级,是异地多活的易用性加强。原先单活时跨区接入延时大,一旦产生故障服务和数据库都须要切换,流程简单;而异地多核心接入时延小,业务在一个核心内能实现闭环,秒级即可实现切换。本次降级新增多活插件化性能,不便用户装置配置,晋升了产品易用性。
异地多活次要区别于传统两地三核心的单活模式。在单活模式中,假如主库在北方,南方的服务要写入主库,因为地区相隔太远,延时会十分大。如果呈现南北网络故障,南方用户就无法访问主库,呈现不可用状况。如果采纳异地多活模式则不存在上述问题。咱们能够在南方多设立一个主库,南方的服务写入南方主库,北方的服务写入北方主库,南北主库之间进行双向复制。其长处在于南北主库各自都有全量数据集,且业务能够就近接入,在一个核心外部实现闭环,即便南北呈现网络故障也不会影响服务。图片
异地多活采纳双向复制性能,下图是异地多活架构示意图。区域 1 是深圳,区域 2 是上海,咱们将区域 1 的数据节点作为公布端,将区域 2 的 CN 节点作为订阅端(CN 能够订阅作为公布端的数据节点上的数据),在实现数据订阅后,CN 须要通过一个路由能力将订阅到的数据写入本地的 DN 节点上,这样咱们反对了异构集群之间的同步,一个 CN 能够订阅多个数据节点。图片
在新版本中,咱们对易用性进行加强。通过 tbase_subscription 工具,用户能够利用 SQL 间接创立整个同步的异地多活过程。创立时还能够指定订阅的并行度,从而进步订阅效率。此外,因为一个 CN 能够订阅多个 DN,用户能够将订阅工作下发到不同 CN 上,使 CN 进行负载平衡。图片
3.3 分布式死锁自动检测
以下图为例。假如有两个 CN,别离为 CN1 和 CN2。有两个用户,用户 1 连到 CN1,产生一个 session,用户 2 连到 CN2,也产生一个 session。用户 1 应用显示事务查问 A 表数据,用户 2 也采纳显示事务查问 B 表数据。用户 1 查问完 A 表数据时,想将 B 表进行删除。因为是分布式系统,CN2 上也存在 B 表,须要同步进行删除。如果要删除 B 表则须要 B 表的排他锁。但这时在 CN2 上,用户 2 刚启动显示事务查问 B 表,取得 B 表的共享锁,这就产生了锁抵触,反之亦然。
在这种状况下,CN1 有 A 表的共享锁,须要等 B 表的排他锁,CN2 有 B 表的共享锁,又要等 A 表的排他锁,两个事务之间就造成了分布式死锁。图片
针对这种状况,咱们引入了 pg_unlock 工具。该工具可通过 extension 装置,疾速便捷。用户装置后能够查到分布式死锁之间的依赖关系。比方在下面的例子中,CN1 是一个依赖于 CN2 的事务,CN2 是一个依赖于 CN1 的事务。用户还能够查到集群中一个死锁的详细信息。比方 CN1 上的 drop b 须要 B 表的排他锁,CN2 上的 drop a 也须要 A 的排他锁,它们之间都是求而不得存在死锁。咱们能够通过执行 pg_unlock execute 来解开死锁,解开的办法是回滚掉一个事务。在回滚事务时,咱们会在外部进行优化,计算出回滚代价最小的事务并进行回滚。图片
3.4 2PC 残留主动清理
以下图为例,假如有两个 CN,别离为 CN1、CN2,有两个 DN,别离为 DN1、DN2。用户连进来创立 A 表,再进行 prepare transaction,该事务命名为 create a。咱们通过另一个 CN 连贯进来,能够查问处于 prepare 状态的事务有哪些,能够看到 CN1 上有一个 prepare 事务叫 create a,CN2、DN1、DN2 也有。
用户继续执行在 DN2 上将 create a 事务进行回滚的操作,尔后该操作会话间接退出。退出后咱们再去查处于 prepare 状态的事务,发现 CN1、CN2、DN1 各有一个 create a 事务,但 DN2 上没有。因为上述会话在退出前,对 DN2 上的 create a 事务进行回滚,相当于该事务不存在 prepare 状态。因为会话曾经退出,该事务永远不会终止,就呈现了 2PC 残留的状况。图片
针对这种状况,咱们引入了 pg-clean 工具。通过 pg_clean check transaction,用户能够间接查到目前有哪些 2PC 残留事务,以及这些事务的名称、参加的节点等。通过 pg_clean execute,咱们能够对 2PC 残留事务进行主动清理。这实际上是将残留事务进行 abort 操作。因为 CN1、CN2、DN1 上的事务都处于 prepare 状态,但 DN2 上执行了 abort,它只能将该事务 abort,不能将其提交,否则会呈现局部提交数据不统一的问题。咱们可能依据事务状态主动抉择回滚或提交,从而将 2PC 残留事务进行清理。图片
在下个版本中,咱们打算在以下四个方面对 TDSQL PG 开源版进行增强:存储能力增强。反对通明压缩,缩小磁盘存储老本;提供 Direct IO 能力,进步某些状况下的写效率。索引优化。反对全局索引,晋升非散布键查问性能。优化器能力晋升。进步执行效率,晋升业务查问及写的性能。分布式状态可视化。优化全局 session 可视化、query 可视化、分布式锁可视化、分布式事务状态可视化,帮忙用户更好地掌控零碎。
开源的实质是以技术凋谢促成技术创新。腾讯云对 TDSQL PG 版一直开发和投入,版本通过大量业务验证,成熟稳固,开源版本和腾讯自用版本共基线,可能帮忙用户疾速构建外围业务,将继续给客户带来价值,与宽广开发者独特打造可继续的国产数据库开源生态。
同时欢送各位感兴趣的小伙伴增加下方微信进入技术探讨群,与咱们一起独特助力国产数据库技术创新与开源生态倒退!