title: “秒杀开发历程(三)” lang: cn ref: seckill-development-journey-part-III permalink: /cn/docs/seckill-development-journey-part-III/ excerpt: “介绍如何一步一步构建秒杀项目的过程” last_modified_at: 2017-09-13T09:00:00+08:00 author: Yangyong Zheng tags: [秒杀] redirect_from:
[上文]({{ site.url }}{{ site.baseurl }}/cn/docs/seckill-development-journey-part-II/) 中我们已经构建了一个完整功能的秒杀系统,版本定为0.1.0-RELEASE;您应该发现,数据的持久化集中在单一的数据库上,秒杀作为一个高并发压力的场景,这种架构很难适应可扩展的要求,并且正如我们一开始就提到的,微服务推荐拥有独立的存储,所以本篇开始我们将配合Event Sourcing实现CQRS模式,以增强应对大规模并发压力的能力。
CQRS 的含义是命令查询职责分离(Command Query Responsibility Segregation),是一种常用的程序设计模式,常常与Event Sourcing一起使用,关于CQRS有一张科普的图,来源于Microsoft MSDN:
{: .align-center}
CQRS是读写分离以及消息驱动的最佳实践,现在我们把目光聚焦在原来的MySQL数据库上:
{: .align-center}
Admin微服务维护Promotion实体;
Command微服务写入Event值对象,当恢复Promotion的时候,Relapy Event。
Event微服务写入ActivePromotion值对象和Coupon值对象;
Query微服务查询ActivePromotion值对象和Coupon值对象。
之前的版本由于没有引入Event Sourcing,Event实体只需要直接写入数据库即可,现在需要将Event发布给Message Broker,为了支持云服务(华为云)提供的分布式消息服务,我们定义了通用消息发布接口:
public interface SecKillMessagePublisher { void publishMessage(String messageContent); }
Event微服务订阅Message Broker获取Event Message,然后根据不同的Event类型,转化为对ReadDB中的值对象操作或Coupon值对象操作:
同样,为了支持云服务(华为云)提供的分布式消息服务,我们定义了通用消息订阅接口:
public interface SecKillMessageSubscriber { void subscribeMessage(String messageContent); }
经过了读写分离的改造,现在所有活跃的Promotion都保存在ActivePromotion值对象表中,而客户成功秒杀的Coupon都保存在Coupon值对象表中,因此直接查询即可,不再需要Replay Event。
现在,我们完成了完整的Event Sourcing架构改造,为了能够方便启动,我们提供了编排好的脚本,使用Docker Compose将所有服务一条指令全部拉起来,具体的操作请参见SecKill。
{: .align-center}