再再续:一张图搞定 12306

八风不动 发布于 2014/01/28 22:32
阅读 2K+
收藏 19


        本文是前三篇文章的续篇,针对网友提出的各种问题,详细介绍一下基于微仓储概念的12306网站总体架构设计。前文中,我们从仓储结构的设计逐步完善到仓储引擎的设计,这次我们画张图,详细介绍一下整体架构的设计。

        前文请移步至:

        12306 售票仓储结构的设计

        续篇:12306 火车售票系统的仓储结构设计

        再续:12306 火车售票系统的仓储引擎设计

        

        

        网站前台的系统架构采用静态页面加无刷新数据请求的方式实现,即HTML+AJAX。其中HTML网页内引用一段动态Javascript脚本,这段脚本会根据后台Web服务器集群的实时负载提供不同的AJAX访问网址,这样就把用户的数据请求均匀分配到多个Web服务器上了。别说是千万并发,再高的并发都没问题,因为这些并发请求压根儿就没堆在一起,发起请求的时候就朝着不同的服务器去的。有需要的话,还可以把Web服务器分散到全国各地甚至是全世界。Google的地图服务要为全世界提供地图瓦片数据,那个并发有多大,那个流量又多大?

    

        如图所示,www.12306.cn这台服务器提供静态页面,用户浏览器载入静态页面后就以AJAX请求为主了,AJAX请求被分配到多台Web服务器:web1.12306.cn,web2.12306.cn...


        


        

        Web服务器负责接收和解译AJAX查询或购票请求,根据用户要查询或购票的具体线路,向后台的售票引擎发送查询或购票请求。后台的售票引擎运行在一个运算服务器集群里,每台服务器启动多个售票进程,每个售票进程负责查询和销售一条线路的相关车票。每台运算服务器常驻一个调度进程,调度进程负责实时动态地调整本服务器上运行的售票进程数量,必要时可以增加或减少。整个运算集群是一个整体,售票进程可以在多台服务器间动态迁移。

         

        并发问题解决了,我们再来解决宕机或掉电问题。前文有网友提出了这个问题,在这里我就专门设计一个附加的数据保障服务器。假设数据保障服务器网址是192.168.0.9(没画在图里),运算服务器的调度进程会定期查看售票进程的共享内存,将其中的当前仓储状态(3k)和已运算未回送的结果列表(只包含买票和退票的结果)传送到数据保障服务器,数据保障服务器会给这块数据打一个时间戳,然后保存到持久性存储介质上,例如磁盘。这样,所有线路的仓储状态都定期备份到这台数据保障服务器上了。当意外发生时,数据保障服务器会根据时间戳和未回送结果列表的任务序号,对仓储状态进行自动恢复,然后把恢复好的该线路仓储数据发送给某一个调度进程,启动一个新的售票进程。



                Web服务器与运算服务器之间的沟通是异步的,用任务序号来标识,任务序号可以是uint或ulong,溢出时归0重复利用。发生意外情况时根据任务发出时间和任务序号确定数据一致性,避免出现错漏。以上说明已经把应对意外故障的架构设计描述清楚了,至于意外发生后具体的恢复细节,请自行脑补。线索都说得很明白了,无需赘述,夏洛克认为这个很Easy。

        

        顺便说一下,第一篇文章中的设计要稍做改动以提高系统性能,掩码中的比特位不再表示站点,改为表示站点间的路段。这是一个思维定势的陷阱,我也掉进去差点没爬出来,好在很快醒悟了。改成路段之后,买票和退票运算时的边界情况就无需考虑了,买票线程的性能又得到进一步提升。

        

        现在,仓储问题解决了!效率问题解决了!并发问题解决了!甚至宕机问题也解决了!还有什么问题么?欢迎探讨也欢迎提问,我是多么的喜欢解决难题啊,Oh Sherlock!

        

加载中
0
优雅先生
优雅先生
Sherlock是啥?
月光小南
月光小南
英剧
八风不动
八风不动
夏洛克.福尔摩斯,最近热播的美剧。:)
0
八风不动
八风不动
八风不动
做出来也难度不大,就是时间不够用啊,咱不还得上班挣饭吃么。
帖子列表
帖子列表
不明觉厉, 但是理论没有项目支撑, 始终没有说服力, 如果LZ能做出一个来, 用事实证明一切, 你就牛x了, 媒体们会再次口诛笔伐铁道部的技术部, 哈哈哈
0
你是错的我恒对
你是错的我恒对

我有个问题哈,

1.12306现在的数据库 表结构 是如何设计的啊(现在的12306官网哈)

2.还有啊,你的用long 的比特位 表示整条线路 站点,这种方式 在哪学到的啊,感觉挺好的,但是不知道实际用到方不方便用

八风不动
八风不动
官网数据库咱可没见过,12306也不公开,他们只是叫嚷着很难、很难...。 比特位表示信息的方法不需要从哪儿学习,计算机系统内部就有很多标志位应用,深入了解下寄存器结构就知道了。
0
八风不动
八风不动

改进一下:

1、仓储状态的更新操作直接由买票线程负责,仓储状态发生变化时,将新的状态发送至数据保障服务器。

2、任务ID可以直接用128位的GUID代替,故障恢复时的运算会更加便捷。

0
奋奋

从第1篇看到这篇,想法很不错,

这个过程中,还有一个问题:座位号;没看到64位中有座位号的标识。

另外,在目前的12306中,如果同时购买2张以上的火车票,大多时候座位号都是连着的,这种人性化的问题如何处理?

八风不动
八风不动
这个问题好。 我原计划是把座位号放在外层去实现的,微内核只处理难度最大的部分,现在又有了新想法,稍候写篇说明。
0
l
letmesee
想法是好的,自己想像的业务模式之上的设计,根基就有问题。
八风不动
八风不动
有哪些是不符合实际的,请指出细节。
0
爆炸
爆炸
把标题换成 一张图搞定假象中的火车票购买系统 比较好。12306又没公开业务细节,纯粹猜测意义不大。
八风不动
八风不动
12306不公开,我有啥办法?我倒想帮他们设计一下,可人家是垄断企业。
0
我不叫大脸猫
我不叫大脸猫
并发请求是分散掉了,但是数据的计算和操作仍然是集中在一个点上
我不叫大脸猫
我不叫大脸猫
回复 @八风不动 : 不同的线路难道就没有相同的人去购买相同的路线?这一块的逻辑再怎么分散,还是要集中计算,如果你用加锁&排队来搞,跟12306现在的架构都是殊途同归,都无法解决最终实际的座位,车次资源不足的问题
八风不动
八风不动
怎么是一个点呢?每个进程只处理一条线路,不同的线路交给不同的进程,或者是不同的硬件服务器。
0
中山野鬼
中山野鬼
楼主,这种行业系统,我说了,200万给一个团队整个业务流程分析报告,我怀疑可能费用都不够。哈。说这个意思是,里面的东西比你想想的要复杂。别拿理想模型当实际工程看。哈。
中山野鬼
中山野鬼
回复 @八风不动 : 不是特殊,而是确实需要面对很多关联复杂的现实问题。哈。
八风不动
八风不动
而且实际工程中,往往会有些“特殊”的要求,搞得架构师不得不在优雅的架构上“打洞”,最后搞得整个架构“千窗百孔”。
八风不动
八风不动
这个明白,但不讨论不研究怎么进步呢?很多问题我想不到不代表大家想不到,提出的问题越多,研究讨论的也就越深入,最终的目的又不是开发一套12306,就算开发一套人家也不用不是。所以,只要讨论之后有进步,就O了。这就是我的观点咯。:)
0
修改登录密码
修改登录密码

这张图应该说非常非常普通,很多集群都是这么设计。 没有看到有什么独特之处

但是根据以前说过的高峰期每秒40w次点击,你估算过这要创建多少个进程? 

为了保持所有节点中数据库的一致性,每次交易需要交换多少数据量? 内网和外网带宽是否够用?  抢票软件又要给系统带来多少压力? 

 

金贞花
金贞花
:D
修改登录密码
修改登录密码
进程难道不要内存?不同节点间进程难道不需要通信带宽? 你估算过需要的节点数和通信压力么?
八风不动
八风不动
售票进程的数量只跟线路的数量有关,客户端的点击量早在网页上就已经分开指向不同的子域名了。
返回顶部
顶部