云时代架构读后感(十)

浅谈12306核心模型设计思路和架构设计

原文地址:https://mp.weixin.qq.com/s?__biz=MjM5NDMwNjMzNA==&mid=403433235&idx=1&sn=d2e421511791c1a49910ff778325beee&scene=21#wechat_redirect

我觉得,越是复杂的业务,就越要重视业务分析,重视领域模型的抽象和设计。如果不假思索,凭以往经验行事,则很可能会被以往的设计经验先入为主,陷入死胡同。我发现技术人员往往更注重技术层面的解决方案,比如一上来就分析如何集群、如何负载均衡、如何排队、如何分库分表、如何用锁,如何用缓存等技术问题,而忽略了最根本的业务层面的思考,如分析业务、领域建模。我认为越是复杂的业务系统,则越要设计一个健壮的领域模型。如果一个系统的架构我们设计错了,还有补救的余地,因为架构最终沉淀的只是代码,调整架构即可(一个系统的架构本身就是不断演进的);而如果领域模型设计错了,那要补救的代价是非常大的,因为领域模型沉淀的是数据结构及其对应的大量数据,对任何一个大型系统,要改核心领域模型都是成本非常高的。

本文的重点不是在如何解决高并发的问题,而是希望从业务角度去分析,12306的理想模型应该是怎么样的。

12306也是一个电商系统,而且看起来商品就是票了。因为如果把一张票看成是一个商品,那购票就类似于购买商品,然后每张票都有库存,商品也有库存的概念。但是如果我们仔细想想,会发现12306要复杂很多,因为我们无法预先确定好所有的票,如果非要确定,那只能通过穷举法了。

一张票的核心信息包括:出发时间、出发地、目的地、车次、座位号。持有票的人就拥有了一个凭证,该凭证表示持有它的人可以坐某个车次的某个座位号,从某地到某地。所以,一张票,对用户来说是一个凭证,对铁道部来说是一个承诺;那对系统来说是什么呢?不知道。这就是我们要分析业务,领域建模的原因,我们再继续思考吧。

作者提出的解决思路。

根据订单信息,拿到出发地和目的地,然后获取这段区间里的所有的原子区间。然后尝试将每个原子区间的可用票数减1,如果所有的原子区间都够减,则购票成功;否则购票失败,提示用户该票已经卖完了。是不是很简单呢?知道了出票的逻辑,那退票的逻辑也就很简单了,就是把这个票的所有原子区间的可用票数加1就OK了。如果我们从线段的厚度的角度去考虑,那出票时,每个原子区间的厚度就是+1,退票时就是减一。就是相反的操作,但本质是一样的。

 

所以,通过这样的思路,我们将一次订票的处理控制在了一个聚合根里,用聚合根内的强一致性的特性保证了订票处理的强一致性,同时也保证了性能,免去了并发冲突的可能性。传统电商那种把票单做类似商品的核心聚合根的设计,我当时第一眼看到就觉得不妥。因为这违背了DDD强调的强一致性应该由聚合根来保证、聚合根之间的最终一致性通过Saga来保证的原则。

我觉得12306这样的业务场景,非常适合使用CQRS架构;因为首先它是一个查多写少、但是写的业务逻辑非常复杂的系统。所以,非常适合做架构层面的读写分离,即采用CQRS架构。而且应该使用数据存储也分离的CQRS。这样CQ两端才可以完全不需要顾及对方的问题,各自优化自己的问题即可。我们可以在C端使用DDD领域模型的思路,用良好设计的领域模型实现复杂的业务规则和业务逻辑。而Q端则使用分布式缓存方案,实现可伸缩的查询能力。

总结:

这篇文章,主要是对12306的业务流程进行的分析,通过这篇文章认识到,有时候在一个系统的优化过程中,不仅仅是对技术方面的优化,同时,也要优化业务流程,这样可能同样可以提高系统的质量。

原文地址:https://www.cnblogs.com/wys-373/p/11014084.html