关于订单数据统计的问题

2020-12-11 17:24:16 +08:00
 nano91

要求:实时获取当天订单的数据,比如今天 17:00 要获取的是 00:00-17:00 的数据

当时的设计:用户下单的时候用异步队列处理数据统计部分,不要影响正常的订单流程,这样订单表和订单统计表就完全独立,但是具体的方案是 有一个日志表 log 去记录所有和订单有关的操作(下单-支付-退款等),并且每一步操作也有具体的金额相关字段, 但是问题就在于 前面提到的异步队列 是定时的从 log 表去读这些操作日志 然后把响应的金额、数量等数据 写入订单统计表 所以做不到实时拿到当前整个平台的订单数据

问题: 1 、虽然 log 表确实必须得有,但是订单的统计为什么不能直接在订单操作的过程中直接把相关的数据写入统计表,而是要异步的定时任务去做?(比如支付后除了去继续进行订单流程外,还要把金额直接加到统计表中,而不是定时任务去统计) 2 、这样的设计有什么好处吗? 3 、更合适的方案是怎样的?

这个是以前的公司参与过的项目,但是问设计的人也没说为什么这样做

1120 次点击
所在节点    程序员
1 条回复
crclz
2020-12-11 20:44:18 +08:00
> 问题 1 、虽然 log 表确实必须得有,但是订单的统计为什么不能直接在订单操作的过程中直接把相关的数据写入统计表,而是要异步的定时任务去做?

因为统计数据的更新是订单操作事件的**副作用**。

副作用是一定会成功的,因为并没有事务关系(如果你下单成功了,那么统计数据中的订单数量一定能够加 1,没有业务规则能够阻碍统计数据的改变)。

如果你把订单操作和副作用放在同一个事务里面,那么就会降低响应时间和吞吐量。


> 2 、这样的设计有什么好处吗?

第一,解耦。订单处理只需要考虑怎么处理订单,以及订单的操作应当写哪些日志。至于日志怎么做统计信息,订单处理的程序不需要考虑。

第二,batching 。如果日志处理和修改某些统计信息可以是批量的,那么这种 batching 可以提升速度( 10 次订单数量+1 操作,vs 1 次订单数量+10 操作)

> 3 、更合适的方案是怎样的?

首先,如果想要做到实时,可以考虑“推”方式的消息队列。

其次,如果系统本身并发要求不高,那么应当采取把订单操作和副作用放在同一个事务里面进行提交,这可以**简化编程**。

原来的方案虽然性能较好,但是把副作用从事务里拆出,需要保证两点:1. log 是 1 次或多次送达的。2. log 可以被重复消费。

第一点可以使用 outbox pattern + ack 来保证;第二点可以让消费者建立去重表。 我所说的这两点是标准的解决方案。

可以看出提升性能的代价就是开发复杂度的增加。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/734590

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX