《浅谈12306核心模型设计思路和架构设计》阅读笔记

一、背景

  也许是否是因为目前12306的核心领域模型设计的不够好,导致用户购票时要处理的业务逻辑异常复杂,维护数据一致性的难度也几百倍的上升,同时面对高并发的订票也难以支持很高的TPS。

  我觉得,越是复杂的业务,就越要重视业务分析,重视领域模型的抽象和设计。

  如果不假思索,凭以往经验行事,则很可能会被以往的设计经验先入为主,陷入死胡同。我发现技术人员往往更注重技术层面的解决方案,比如一上来就分析如何集群、如何负载均衡、如何排队、如何分库分表、如何用锁,如何用缓存等技术问题,而忽略了最根本的业务层面的思考,如分析业务、领域建模。

  我认为越是复杂的业务系统,则越要设计一个健壮的领域模型。如果一个系统的架构我们设计错了,还有补救的余地,因为架构最终沉淀的只是代码,调整架构即可;而如果领域模型设计错了,那要补救的代价是非常大的,因为领域模型沉淀的是数据结构及其对应的大量数据,对任何一个大型系统,要改核心领域模型都是成本非常高的。

二、需求简述

  12306这个系统,核心要解决的问题是网上售票。

  涉及到2个角色使用该系统:用户、铁道部

  用户的核心诉求是查询余票、购票;铁道部的核心诉求是售票。

  购票和售票其实是一个场景,对用户来说是购票,对铁道部来说是售票。因此,我们要设计一个在线的网站系统,解决用户的查询余票、购票,以及铁道部的售票这3个核心诉求。看起来,这3个场景都是围绕火车票展开的。

  1、查询余票:

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

  2、购票:

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

  其实还有很多其他的需求,比如给不同的车次设定销售座位数配额,以及不同的区段设置不同的限额。我觉得这个需求不是核心最重要的诉求,所以,本文针对这个需求不做具体讨论,也不是本文分析设计的重点。

三、需求分析

  确实,12306也是一个电商系统,而且看起来商品就是票了。

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

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

  另外,经过更深入的分析,我们还发现区间有4种关系:

  1、不重叠;

  2、部分重叠;

  3、完全重叠;

  4、覆盖;

  不重叠的情况我们已经讨论过了,而覆盖也是重叠的一种。所以我们发现如果重叠,比如有两个区间发生重叠,那重叠部分的区间(可能夸一个或多个站点)是在争抢座位的。因为假设一列火车有100个座位,那每个原子区间(两个相邻站点的连线),最多允许重叠99次。

  所以,经过上面的分析,我们知道了一个车次能够出售一张车票的核心业务规则是什么?

  这张车票所包含的每个原子区间的重叠次数加1都不能超过车次的总座位数,实际上重叠次数+1也可以理解为线段的厚度。

 四、模型设计

  我们再来看看怎么设计模型,来快速实现购票的需求,重点是怎么设计商品聚合以及减库存的逻辑。

五、 架构设计

  我觉得12306这样的业务场景,非常适合使用CQRS架构;因为首先它是一个查多写少、但是写的业务逻辑非常复杂的系统。所以,非常适合做架构层面的读写分离,即采用CQRS架构。

  而且应该使用数据存储也分离的CQRS。这样CQ两端才可以完全不需要顾及对方的问题,各自优化自己的问题即可。

  我们可以在C端使用DDD领域模型的思路,用良好设计的领域模型实现复杂的业务规则和业务逻辑。而Q端则使用分布式缓存方案,实现可伸缩的查询能力。

 

  原文链接:

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

posted @ 2019-06-02 09:57  我命倾尘  阅读(520)  评论(0编辑  收藏  举报