MQ And Domain Event
消息队列与领域事件
消息队列
两种模式
- Point-ti-Point: Queue (点对点: 队列)
- Pub/Sub: Topic (发布/订阅: 主题)
(非)持久订阅
发布/订阅分为非持久订阅(Redis pub/sub)和持久订阅(ActiveMQ). 持久订阅: 发布者在订阅者处于非活动状态时发布的消息,将在订阅者再次处于活跃状态时重新发布。
Point-to-Point | Pub/Sub |
---|---|
一个消费者(不可重复消费) | 多个订阅者(可重复消费) |
拉模式(懒/轮询) | 推模型 |
异步 | “同步” |
生成-消费队列 | 观察者 |
领域事件
消息队列和事件驱动有密不可分的关系。
领域事件(Domain Events)是领域驱动设计(Domain Driven Design,DDD)中的一个概念。
在DDD中有一条原则:一个业务用例对应一个事务,一个事务对应一个聚合根,也即在一次事务中,只能对一个聚合根进行操作。
在DDD中有一条原则:一个业务用例对应一个事务,一个事务对应一个聚合根,也即在一次事务中,只能对一个聚合根进行操作。但是在实际应用中,我们经常发现一个用例需要修改多个聚合根的情况,并且不同的聚合根还处于不同的限界上下文中。比如,当你在电商网站上买了东西之后,你的积分会相应增加。这里的购买行为可能被建模为一个订单(Order)对象,而积分可以建模成账户(Account)对象的某个属性,订单和账户均为聚合根,并且分别属于订单系统和账户系统。显然,我们需要在订单和积分之间维护数据一致性,通常的做法是在同一个事务中同时更新两者,但是这会存在以下问题:
- 违背DDD中”单个事务修改单个聚合根”的设计原则;
- 需要在不同的系统之间采用重量级的分布式事务(Distributed Transactioin,也叫XA事务或者全局事务);
- 在不同系统之间产生强耦合。
通过引入领域事件,我们可以很好地解决上述问题。 总的来说,领域事件给我们带来以下好处:
- 解耦微服务(限界上下文);
- 帮助我们深入理解领域模型;
- 提供审计和报告的数据来源;
- 迈向事件溯源(Event Sourcing)和CQRS等。