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

Best practice for high-volume transactions with real time balance updates

我目前有一个处理大量交易的 MySQL 数据库。为简单起见,它是实时发生的操作(点击和其他事件)的数据流。结构是这样的,即用户属于子分支机构,子分支机构属于分支机构。

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

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

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

我正在考虑的一些事情:

1 - 创建一个 cron 作业,该作业将非实时更新次级联盟和联盟级别的余额,比方说每 5 分钟一次。

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

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

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

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

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

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

解决方案很多,选择一个的范围不在这个答案的范围内,但需要考虑一些包:

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

...等...

就存储而言,它实际上取决于您要实现的目标,快速读取、快速写入、批量读取、sharding/distribution、高可用性……每个问题的答案都不同方向

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

点击余额(和 "Like counts")应与所有相关数据分开 table。这有助于避免干扰系统中的其他 activity。如果您拥有的数据多于可以在 buffer_pool.

中缓存的数据,则可能会提高余额的可缓存性

请注意,我的设计不包括 cron 作业(除了 "keep-alive")。它处理 table,翻转 tables,然后循环回处理——尽可能快。

这听起来像是 Clustrix which is a drop in replacement for MySQL. They do something like sharding, but instead of putting data in separate databases, they split it and replicate it across nodes in the same DB cluster. They call it slicing, and the DB does it automatically for you. And it is transparent to the developers. There is a good performance paper 的优秀候选者,展示了它是如何完成的,但它的缺点是它是一个横向扩展的 OTLP DB,恰好能够吸收大量的对实时数据的分析处理也是如此。