Mar*_*ann 7 azure cqrs azure-table-storage dddd
我仍然在努力解决与CQRS风格架构相关的基本(和解决)问题:
我们如何实现依赖于一组聚合根的业务规则?
以一个预订申请为例.它可以让您预订音乐会的门票,电影的座位或餐厅的桌子.在所有情况下,只有有限数量的"物品"可供出售.
让我们想象一下这个活动或地点非常受欢迎.当销售为新事件或时段开放时,预订开始很快到达 - 可能每秒很多.
在查询方面,我们可以进行大规模扩展,并将预留放在队列中以由自治组件异步处理.首先,当我们从队列中取出预约命令时,我们将接受它们,但在某个时间我们将不得不开始拒绝其余的.
我们怎么知道什么时候达到极限?
对于每个预约命令,我们必须查询某种商店以确定我们是否可以容纳请求.这意味着我们需要知道当时已收到多少预订.
但是,如果域存储是非关系数据存储,例如Windows Azure表存储,我们就不能很好地做到 SELECT COUNT(*) FROM ...
一种选择是保持一个单独的聚合根,它只是跟踪当前的计数,如下所示:
第二个聚合根将是第一个聚合根的非规范化聚合,但是当底层数据存储不支持事务时,它们很可能在高容量场景中不同步(这是我们正在尝试的首先解决).
一种可能的解决方案是序列化预留命令的处理,以便一次只处理一个,但这违背了我们的可扩展性(和冗余)目标.
这种情况让我想起了标准的"缺货"情景,但不同之处在于我们不能很好地将预订放在后面.一旦活动售罄,它就卖光了,所以我看不出补偿行动会是什么.
我们如何处理这种情况?
经过一段时间的思考后,我终于意识到,根本问题与 CQRS 的关系不大,而与不同 REST 服务的非事务性质相关。
实际上归结为这个问题:如果需要更新多个资源,如果第二次写操作失败,如何确保一致性?
假设我们要按顺序写入资源 A 和资源 B 的更新。
第一次写操作遇到异常并不能轻易回滚,那我们该怎么办呢?捕获并抑制异常以对资源 A 执行补偿操作并不是一个可行的选择。首先,它实现起来很复杂,其次它也不安全:如果由于网络连接失败而发生第一个异常,会发生什么?在这种情况下,我们也无法针对资源 A 编写补偿操作。
关键在于显式幂等性。虽然 Windows Azure 队列不保证恰好一次语义,但它们确实保证至少一次语义。这意味着,面对间歇性异常,该消息稍后会被重播。
在前面的场景中,会发生以下情况:
当所有写操作都是幂等的时,可以通过消息重放来实现最终一致性。
| 归档时间: |
|
| 查看次数: |
1140 次 |
| 最近记录: |