暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PG:全球20亿事务

飞象数据 2019-09-20
698

事务ID(Xid)从一开始就一直是Postgres的一个棘手的问题。一方面,它们对于区分过去、现在和并发事务之间的元组可见性是必要的。另一方面,存储它的计数器只有32位,这意味着在没有某种干预的情况下,最终有可能溢出。

重塑问题

这里问题的关键在于默认的假设,在任何现代背景下,20亿事务就足够了。在许多大型数据库中,它甚至不是特别值得注意的,更不用说“足够”了。极高的OLTP系统每天可以轻松消耗很多事务,甚至可以通过足够强大的硬件来消耗更多。

RobertHaas分享了一些分析,当时DEVS正在疯狂地调整Postgres的锁定代码,并在2012年展示了相当惊人的性能提升。那时,64核服务器每秒可以提供超过350 k的只读事务。现在想象一下,如果生产数据库系统实际上管理了这么高的写事务吞吐量。以这种速度完成20亿笔交易需要不到两个小时。数据库中的每个表至少需要每两个小时冻结一次。

这根本不实用。甚至不可能给定表访问和vacuum都在不断争夺相同的IO资源。即使是内存数据库,也可能有太多的非冻结页面分布在数百个或数千个表中 。

这是监控

在事务ID方面,绝对需要保持对潜在问题的警惕。这一点上,已经有很多从专业顾问和业余爱好者那里收集起来的关于监控的文章。甚至亚马逊也解释了如何使用他们的界面来创建警告系统,以防止他们的RDS平台用户出现XID溢出问题。

每个人都知道,但它仍然让工程师措手不及。除了多版本并发控制(MVCC)上下文之外,它还非常不直观。如果Postgres是一个文件系统,我们可以说XID等同于剩余的文件系统空间,因为它们都是应该密切监视的可替代资源。

然而,或许这种类比并不能很好地理解这种情况。用户更有可能将数据库本身视为一种文件系统。在哪种情况下,谁会觉得有必要防止完全普通的文件突然腐败,仅仅因为它们太老了?任何使用像ZFS一样使用Copy on Write文件系统的人都可以获得与MVCC类似的好处,但是没有相当于XID环绕的东西。

假设XID耗尽仅仅是懒惰,无能或不完全监控的结果,这将是愚蠢的。请记住,如果数据库足够活跃,即使在一小时内回复也可能为时已晚。监控是一回事,有效解决警报是另一回事。

我们很多人学到的教训是,范围几乎从不是静态的。在原始架构和堆栈设计中可能已经完全足够的东西可能随着时间的推移变成完全不同的东西。也许去年还没有风险,或突然涌入的业务 - 通常是一个偶然的场合 - 突然淹没了一个没有准备好处理该数量的系统。在这种情况下扩大规模只会使问题变得更糟,除非有一位了解其影响的Postgres专家。

监控只是我们箭袋中的第一个箭头; 一箭不能落下猛犸象。

我们如何到达这里

Postgres 实施 MVCC的方式是关键点。

Postgres的起源,尽管有许多超前的决定,但在历史上仍然是一个非常昂贵和相对较小的存储点。因此,其中一个选择是尽可能高效地限制页面和元组头部,并细细品味最后一点。毕竟,对于XID使用64位会大大增加与数据库中每一行相关的元数据的空间量。

考虑一下Postgres 元组头中的内容 。如果我们将XID从32位扩展到64位,我们需要扩展不是一个,而是三个头元素。这会将元组的头部从23个字节扩展到35个。这是每1B行12GB的额外开销!23对35字节多少钱?

I'll always like to eatI'll always like to eat my enemies!

更重要的是,现有行无法从这种扩展中受益。这将意味着一个非常耗时且过时的转储和恢复过程,这是我们早已过去的事情,这要归功于像pg_upgrade
这样的工具。谁愿意花费数天或数周时间将50TB的数据转移到新的目标中,以消除XID问题?使用逻辑复制来防止停机可能是唯一可行的方法。幸运的是,自Postgres 10以来,我们已经拥有了这个功能,或者自9.4以来通过pglogical扩展。

这里也没有任何措施; 在Postgres中,XID无处不在。替换它将意味着与所有先前版本和相关工具的整个后端的硬兼容性中断。它会从根本上改变Postgres的内容。为了更好,这将是一个多事的过渡!

出路

也许解决方案是使用分片或其他复杂的分发机制来水平扩展数据库。然而,即使只考虑到体量和流量平衡,也只能避免群集中包含的节点数量问题。在问题再次发生之前,十个节点仅提供最多200亿个事务。

也许可以使用像BDR这样的多主解决方案?交换当前的活动数据库并关闭“脱机”系统,同时尽可能激进。只要来自其余节点的写活动不具有破坏性,这种方法就能工作,但是在足够大的容量下,即使这个解决方案也无法跟上。请记住,在开始时,活动数据库;我们可能必须每隔几个小时交换节点,以保持可行。

一旦数据存储与引擎本身分离,就会打开一个全新的世界。它可以直接替换,而不是使用鞋拔来延长老忠实的生命。我想开发人员一直希望实现一些改进,但由于旧标头设计的限制而无法实现。所以现在他们可以添加一个全新的系统,用户可以按照自己的节奏过渡到它。

插入替换,运行alter语句将每个表重写为新的存储格式,并在一天内调用它。那不是很好吗?

EnterpriseDB目前正在开发zheap ,这类似于Oracle使用回滚段管理就地元组替换的方式。

我主要期待的是主分支的本机存储后端替换。会是什么?是否存在集成标识符,以便多主系统可以在群集中唯一地标记行?谁知道。但可能会有。如果没有,那么......至少可以提供存储后端。

这种发展与Postgres增加扩展时的影响相似。如果Postgres没有做某事,添加它只是“只需几行代码”。但是这种能力从未扩展到存储系统,因为数据持久性由写入日志(WAL)控制。没有它,就没有崩溃安全性,逻辑或物理复制以及任何数量的相关功能。

最终的结果可能还有一两个版本,但是现在隧道的尽头有一个非常清晰的光。这已经是很长一段时间了,希望一次就把它做好。

本文翻译自:https://www.2ndquadrant.com/en/blog/around-world-two-billion-transactions/

文章转载自飞象数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论