具有实时余额更新的大容量交易的最佳实践

Posted

技术标签:

【中文标题】具有实时余额更新的大容量交易的最佳实践【英文标题】:Best practice for high-volume transactions with real time balance updates 【发布时间】:2017-02-25 20:02:39 【问题描述】:

我目前有一个处理大量事务的 mysql 数据库。为简单起见,它是实时的动作数据流(点击和其他事件)。该结构是这样的,即用户属于子附属公司,而子附属公司属于附属公司。

我需要平衡点击次数。为简单起见,假设我需要将每个用户、子关联公司和关联公司的点击余额增加 1(实际上取决于事件的处理更多)。目前我做的非常简单——一旦我收到事件,我会在 php 中进行顺序查询——我读取用户的余额,加一并存储新值,然后我读取子附属公司的余额,递增并写入等。

用户的余额对我来说是最重要的指标,所以我希望尽可能保持实时。 sub-aff 和会员级别的其他指标不太重要,但它们越接近实时越好,但我认为 5 分钟的延迟可能是可以的。

随着项目的发展,它已经成为一个瓶颈,我现在正在寻找替代方案 - 如何重新设计余额计算。我想确保新设计每天能够处理 5000 万个事件。对我来说,不要丢失一个事件也很重要,我实际上将每个更改周期包装到一个 sql 事务中的点击余额。

我正在考虑的一些事情:

1 - 创建一个 cron 作业,该作业将不实时更新子会员和会员级别的余额,假设每 5 分钟一次。

2 - 使用存储过程将数字处理和余额更新移动到数据库本身。我正在考虑添加一个单独的数据库,也许 Postgress 会更适合这项工作?我试图查看是否有显着的性能改进,但互联网似乎在这个话题上存在分歧。

3 - 将这个特定的数据流移动到类似带有 parquet 的 hadoop(或 Apache Kudu?),并在需要时添加更多服务器。

4 - 对现有数据库进行分片,基本上为每个附属公司添加一个单独的数据库服务器。

对于此类任务是否有一些最佳实践/技术或我可以做的一些显而易见的事情?非常感谢任何帮助!

【问题讨论】:

【参考方案1】:

我对高速摄取的建议是here。在你的情况下,我会在它描述的乒乓表中收集原始信息,然后让另一个任务总结表来做计数器的质量UPDATEs。当流量激增时,它会变得更有效率,从而不会倒下。

点击余额(和“点赞数”)应位于与所有关联数据分开的表格中。这有助于避免干扰系统中的其他活动。如果您的数据多于 buffer_pool 中可以缓存的数据,则可能会提高余额的可缓存性。

请注意,我的设计不包括 cron 作业(可能作为“保持活动”除外)。它处理一个表,翻转表,然后循环返回处理 - 尽可能快。

【讨论】:

【参考方案2】:

如果我是你,我会实现 Redis 内存存储,并在那里增加你的指标。它非常快速和可靠。您也可以从此数据库中读取。同时创建 cron 作业,将这些数据保存到 MySQL 数据库中。

【讨论】:

【参考方案3】:

您的 Web 层是否在接收和处理 HTTP 请求时进行数字运算?如果是这样,您要做的第一件事就是将其移至工作队列并异步处理这些事件。我相信您在第 3 项中暗示了这一点。

有很多解决方案,选择一个的范围超出了这个答案的范围,但是需要考虑一些包:

Gearman/PHP Sidekiq/Ruby 亚马逊 SQS RabbitMQ NSQ

...等等...

在存储方面,它实际上取决于您要实现的目标,快速读取、快速写入、批量读取、分片/分发、高可用性......每个问题的答案都指向不同的方向

【讨论】:

【参考方案4】:

这听起来像是 Clustrix 的绝佳候选者,它是 MySQL 的替代品。他们执行分片之类的操作,但不是将数据放在单独的数据库中,而是将其拆分并在同一数据库集群中的节点之间复制。他们称之为切片,数据库会自动为您完成。它对开发人员是透明的。上面有一个good performance paper,它显示了它是如何完成的,但它的不足之处在于它是一个横向扩展的 OTLP DB,恰好能够吸收大量的实时数据分析处理。

【讨论】:

以上是关于具有实时余额更新的大容量交易的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot REST API 端点映射最佳实践

Laravel 中批量更新关系的最佳实践

海量数据的分库分表技术演进,最佳实践

JavaScript 最佳实践通过三个因素过滤数组

分库分表技术演进&最佳实践-修订篇

基于Flink+ClickHouse构建实时游戏数据分析最佳实践