如何在海量操作中使用富域?
Posted
技术标签:
【中文标题】如何在海量操作中使用富域?【英文标题】:How to use Rich Domain with Massive Operations? 【发布时间】:2013-10-16 22:18:27 【问题描述】:由于我正在处理一个相对复杂的问题,我想使用领域驱动设计方法来解决它。有问题的问题是为客户计算月度发票。当前的解决方案是作为一个很难维护的很长的存储过程来实现的。
我想使用面向对象的环境(可能是 POCO 和实体框架),但我担心性能。当前 SP 使用集合操作需要大约 10 分钟才能生成超过 300 000 条记录。我认为这对于任何 ORM 都很难实现,因为它将一个一个地加载实体并以相同的方式发送更新。 (以前的版本一个一个访问记录需要 5 个小时。)
您将如何为大规模操作创建丰富的模型?
【问题讨论】:
可维护性和性能常常相互矛盾。你的问题不具体,问题很全面。在我看来,您不太可能得到满意的答复。 如果是月度发票,生成它们需要 10 分钟还是一天? 任何关于它的完整源代码真实世界示例? 【参考方案1】:在应用富域模型时,我尽可能避免使用大量操作。
某些批次可以替换为事件。例如,我需要一份每日订单计数报告。
批处理解决方案:
在一天结束时触发的调度任务从今天下达的订单中收集数据。
或者使用事件
下新订单时,PlaceOrderService 会发布 OrderPlacedEvent。并且 eventHandler 接收事件并插入到 T_ORDER_COUNT_ENTRY
|TODAY |ORDER_ID|
|2012-04-01|123 |
|2012-04-01|124 |
我们可以使用 SQL count() 来计算每日订单计数报告。
其他批次可以并行运行。例如,如果我的订单在 30 分钟内未付款,则应自动取消。
原始的批处理解决方案是一个一个地获取所有满足的订单并调用它们的cancel()。
目前的解决方案是逐一获取所有满足的订单并发送 OrderIsOverdue 消息。消息处理程序接收包含 orderId 的消息并检索订单然后取消。
我认为当取消操作比发送消息花费更多的时间时,这很有用。如果硬件资源负担得起,可以添加更多消息处理程序以提高吞吐量。
【讨论】:
【参考方案2】:想了想,发现你的问题和这个差不多:
如何将存储过程重写为域驱动代码?
理论上,这是可能的。您需要做的就是识别和分离存储过程中存在的关注点,并以面向对象的方式重写它们。
话虽如此,我预计为实现这一目标需要解决以下类型的任务:
1 - 数据预加载
存储过程可以使用临时表或表类型的变量,这在域驱动代码中是不可用的。因此,它归结为预加载实体。这样做是为了提前加载所有数据,而无需稍后在迭代每个实体时加载依赖/子实体 - 您需要将它们全部放在内存中。
对此,请参考[aggregate roots]
这种方法有一个很大的缺点:高内存消耗。因此下面的下一步。
2 - 没有预加载的数据迭代
存储过程有游标之类的东西。这不会加载数据,而是以有效的方式对其进行迭代。但是,在域驱动的代码中,您无法真正实现完全相同的效果。有一些接近游标的东西 - [SqlDatReader],但它并没有真正在幕后使用 SQL 游标,所以要小心它。
3 - 批量数据修改
这部分可以通过在域模型中正确实现[Unit of Work]来轻松实现。因此,所有修改都会立即提交到数据库,即使您正在逐个调用实体实例上的修改操作。
我不确定这是否为问题增添了一些亮点,但如果您有任何我可以解决的问题,请告诉我。
【讨论】:
以上是关于如何在海量操作中使用富域?的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点#海量数据下如何使用多线程的导出 Excel