其他
重磅 | 十年来扩展PostgreSQL的一些经验和教训
工作近十年来,开源关系数据库PostgreSQL一直是OneSignal的核心部分。多年来,我们已经在近40台服务器上扩展了多达75 TB的存储数据。我们的实时分段功能极大地受益于PostgreSQL的性能,但是由于繁重的写入负载和PostgreSQL升级路径的限制而导致的膨胀,有时我们也一直在挣扎。
溢出 数据库升级 XID环绕 分区 分片
高层数据概述
subscribers
。就推送通知而言,一个subscriber
被标识为支持用户细分的推送令牌,订阅状态和数据标签(key : value
可以通过我们的SDK添加到设备的字符串或数字数据的自定义对)。subscribers
订阅状态为未订阅。这些记录的写入频率非常高-每次打开应用程序时,我们都会在上次看到该订阅者时进行更新。在阅读方面,我们既支持事务发送(即,以特定的参与里程碑发送给特定的订户),也可以发送给具有特定特征的大量受众(即细分受众群)。将通知发送到由各种参数定义的较大段时,查询可能很快变得复杂并且需要花费几分钟的时间执行,因为它们可能从数千万个集合中返回数百万条记录。subscribers
,notifications
是我们的下一个最大数据集。记录的大小差异很大,从很小的记录(例如“发送给我的所有用户”通知)到包含特定订户ID列表的很大的记录都很大。这些记录的大部分在创建时就被写入,然后在整个交付过程中添加或更新各种计数器和时间戳。很少读取此数据-几乎所有访问后创建操作都是有针对性的,UPDATE
或者是从OneSignal仪表板查询以获取最新通知的概述。有时还会导出客户端应用程序的通知数据,但这些访问数据只占很小的一部分。最后,我们对该数据运行批量删除以实施保留策略。该notification
数据集被划分并且类似地分片,以subscribers
。subscribers
在INSERT
和方面都是繁重的工作,UPDATE
并且还面临频繁,长时间运行的分析查询以支持向细分受众群投放的附加挑战。notifications
除了繁重的UPDATE
工作量和频繁的批量删除以实施保留策略外,通常还有相当大的记录。
溢出
1
表溢出
VACUUM
此表上允许的空间内,该表为将来重复使用INSERT
或UPDATE
,但如果,例如,你有第二个大表,可以使用一些额外的空间,这些网页将无法使用。更新是PostgreSQL中another肿的另一个来源,因为更新是通过
DELETE
加号实现的INSERT
。即使删除在数据集上并不常见,但严重更新的表也可能成为受害者。2
索引溢出
UPDATE
值实际上是一个DELETE
加号INSERT
,这意味着每次更新一列时,无论索引值是否更改,索引条目也都必须更新。subscribers
数据集已经大量更新和大量读取。有21个索引,这意味着每次更新都会创建大约20个失效条目。最终的结果是该表及其索引的磁盘占用量迅速增加。3
防止溢出
autovacuum
是一项功能,其中数据库将VACUUM
代表您自动生成进程。但是,什么是吸尘?从文档中:autovacuum
必须经常运行,以使死角保持在可接受的水平。autovacuum
是一个大话题,不应该发表自己的文章,值得庆幸的是,2ndQuadrant的优秀人士已经写了一篇详尽的博客文章,涵盖了这个确切的话题。4
模式优化
created_at
并且您只想保留最近30天的数据。为此,您最多可以创建30个分区,每个分区都将保留一个特定的日期范围。实施保留策略时,使用简单DROP TABLE
的方法从数据库中删除单个分区表,而不是尝试从整个表中进行有针对性的删除。此策略可以首先防止膨胀。该pg_partman扩展,甚至可以自动为你这个过程!big_column
和int_column
。big_column
每个记录中存储的数据通常约为1千字节,并且int_column
更新非常频繁。对的每次更新int_column
也会导致big_column
被复制。因为这些数据列是链接的,所以更新将创建大量的浪费空间,每次更新大约为1kb(模块化磁盘分页机制)。int_column
到一个单独的表中。在该单独的表中更新它时,不会big_column
生成任何重复项。尽管拆分这些列意味着您需要使用一个JOIN
来访问两个表,但是根据您的用例,可能值得权衡取舍。我们针对subscribers
和notifications
数据集都使用了这一技巧。订户上的数据标签可以是多个千字节,并且像列这样last_seen_time
的更新非常频繁。这显着降低了肿率。数据库升级
pg_upgrade
。该工具将数据库从旧格式重写为新格式。它要求数据库在升级过程中处于脱机状态。如果您甚至没有适当大小的数据集和可用性要求,那么这个要求就是一个大问题-这就是为什么我们从未使用这种方法来升级数据库。使用升级的PostgreSQL版本设置新服务器。 设置逻辑复制,在新版本上有效地创建热备用。 切换或正常切换到热备用。为了实现正常切换,与内置的逻辑复制功能相比,pgologic扩展 提供了更多的旋钮来调整复制流的应用方式以及如何处理冲突。
XID环绕
SELECT power(2, 31) - age(datfrozenxid) AS remaining
FROM pg_database
WHERE datname = current_database();
autovacuum_freeze_max_age
。这是强制真空之前所需的最大XID年龄。触发吸尘时剩余的XID数为2^31 - autovacuum_freeze_max_age
。分区
subscribers
和notifications
数据进行分区。由于规模的扩大,我们可能会将其扩展到4096个分区,这既是出于希望利用更多服务器的原因,又是为了提高查询和维护流程的效率。分片
结论
干货直达👇
更多精彩👇