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

摘要:我发现也许是不是由于目前12306的核心领域模型设计的不够好,致使用户购票时要处理的业务逻辑异常复杂,维护数据一致性的难度也几百倍的上升,同时面对高并发的订票也难以支持很高的TPS。我以为,越是复杂的业务,就越要重视业务分析,重视领域模型的抽象和设计。若是不假思索,凭以往经验行事,则极可能会被以往的设计经验先入为主,陷入死胡同。我发现技术人员每每更注重技术层面的解决方案,好比一上来就分析如何集群、如何负载均衡、如何排队、如何分库分表、如何用锁,如何用缓存等技术问题,而忽略了最根本的业务层面的思考,如分析业务、领域建模。我认为越是复杂的业务系统,则越要设计一个健壮的领域模型。若是一个系统的架构咱们设计错了,还有补救的余地,由于架构最终沉淀的只是代码,调整架构便可(一个系统的架构自己就是不断演进的);而若是领域模型设计错了,那要补救的代价是很是大的,由于领域模型沉淀的是数据结构及其对应的大量数据,对任何一个大型系统,要改核心领域模型都是成本很是高的缓存

需求简述

12306这个系统,核心要解决的问题是网上售票。涉及到2个角色使用该系统:用户、铁道部。用户的核心诉求是查询余票、购票;铁道部的核心诉求是售票。购票和售票实际上是一个场景,对用户来讲是购票,对铁道部来讲是售票。所以,咱们要设计一个在线的网站系统,解决用户的查询余票、购票,以及铁道部的售票这3个核心诉求。看起来,这3个场景都是围绕火车票展开的。数据结构

查询余票:用户输入出发地、目的地、出发日三个条件,查询可能存在的车次,用户能够看到每一个车次通过的站点名称,以及每种座位的余票数量。架构

购票:购票分为订票和付款两个阶段,本文重点分析订票的模型设计和实现思路。并发

其实还有不少其余的需求,好比给不一样的车次设定销售座位数配额,以及不一样的区段设置不一样的限额。我以为这个需求不是核心最重要的诉求,因此,本文针对这个需求不作具体讨论,也不是本文分析设计的重点。负载均衡

需求分析

确实,12306也是一个电商系统,并且看起来商品就是票了。由于若是把一张票当作是一个商品,那购票就相似于购买商品,而后每张票都有库存,商品也有库存的概念。可是若是咱们仔细想一想,会发现12306要复杂不少,由于咱们没法预先肯定好全部的票,若是非要肯定,那只能经过穷举法了。分布式

咱们知道一张票的本质是某个车次的某一段区间(一条线段),这个区间包含了若干个站点。而后咱们还发现,只要区间不重叠,那座位就不会发生竞争,能够被回收利用,也就是说,能够同时预先出售。高并发

另外,通过更深刻的分析,咱们还发现区间有4种关系:1)不重叠;2)部分重叠;3)彻底重叠;4)覆盖;不重叠的状况咱们已经讨论过了,而覆盖也是重叠的一种。因此咱们发现若是重叠,好比有两个区间发生重叠,那重叠部分的区间(可能夸一个或多个站点)是在争抢座位的。由于假设一列火车有100个座位,那每一个原子区间(两个相邻站点的连线),最多容许重叠99次。优化

 

因此,通过上面的分析,咱们知道了一个车次可以出售一张车票的核心业务规则是什么?就是:这张车票所包含的每一个原子区间的重叠次数加1都不能超过车次的总座位数,实际上重叠次数+1也能够理解为线段的厚度。网站

 

模型设计

上面我分析了一下票的本质是什么。那接下来咱们再来看看怎么设计模型,来快速实现购票的需求,重点是怎么设计商品聚合以及减库存的逻辑。spa

 

架构设计

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

 

总结

本文彻底是凭本身对12306这个网站的核心业务的简单思考而获得的一些设计结果。若是真正的DDD领域建模,更多的是要和业务一线的工做人员、领域专家进行深刻沟通,才能更深刻的了解该领域内的业务知识,从而才能设计出更靠谱的领域模型和架构设计。我本人很是惭愧由于没有上12306买过火车票,家离的比较近,就算要买也是家人给我买:)因此,本文所分享的内容不免是纸上谈兵。但我以为12306这个系统的业务确实比传统的电商系统要复杂,且并发又这么高。因此,我以为这个系统真的很值得你们重视模型的设计,而不仅是只关注技术层面的实现。

相关文章
相关标签/搜索