主题:【原创】好吧,给一个铁道部订票系统的正确答案 -- 布老虎
达到适当长度,那么就另起新楼。
为了避免铁道部把这个系统再次搞成世界级的笑话,那我就免费给他们大概地,简单地设计一个每秒千万级响应的系统吧。
首先,实际的做法是eventual consistency,而不是immediate consistency。全世界最大的电商Amazon,就是eventual consistency的老祖宗。有的同学提出async processing,算是摸着点儿边了。IBM之流肯定会忽悠你去搞一个实时交易系统,然后通过系统硬件升级狠宰你一刀。注意,这就一个人民群众买车票的系统,我草,别把自己当NYSE了。
其次,绝对不能和其他系统互联。高峰时间的流量未必能crash铁道部的这套系统,但是一定会搞死工农中建的交易支付系统。简单的解决方法就是全国人民用身份证号登陆,事先在铁道部的系统里存钱。
最后,所有的数据库必须offline,绝对不能让实时的流量冲击数据库,不管是NoSQL还是SQL,这帮数据库都不行。Oracle肯定一定绝对会忽悠铁道部升级到“高级”数据库。铁道部的“专家们”,请一定要大叫呀咩跌。
好了,下面就是系统描述:
查询车次:请求被负载均衡到任意一台前端服务器,前端服务器直接按车次/时间把做好的html从一个hashmap里取出来,扔回去给用户。全部响应时间应该在毫秒级。
有勤于思考的同学就要迷惑地问,这个车次之类的东西,难道不更新吗?我摸摸这个同学的脑袋,慈祥地说,“this is a good question.”。每个前端服务器都定时(每5秒吧,要不每3秒?每2秒?)从后端的cache里取出更新数据。No, no, 先不要问这个cache的问题,叔叔马上告诉你。
下订单:请求被负载均衡到任意一台前端服务器,前端服务器知道这哥们要下订单了,二话不说把订单扔到一个message queue(叫做fund checking queue吧, 瞧,我连变量名字都替铁道部起好了),然后返回一个响应给用户,订单已经提交,请查email或短信。全部响应时间应该在毫秒级。
后端服务器先检查这哥们的钱够不够。因为这钱已经存进铁道部的系统, 这就直接在铁道部的数据库里(就叫存款数据库吧)查询就行了,用不着到工农中建的服务器上去做啥web service。钱够了,直接扣就行。简单的按身份证号sharding数据库table就行了,200个MySql serve, 每个32G内存,够全国人民用的吧?全部响应在毫秒级。
如果这哥们钱不够,把请求扔到一个message queueu(就叫insufficient funds queue吧), 然后email 短信啥的就不多说了。
如果这哥们钱够了,先扣钱,然后把请求扔到一个message queue(就叫 seat checking queue 吧),这个queue主要就是占座位了。如果座位被占了,那么就回到存款数据库里把钱退回去。如果座位还有,那么就占座,然后发送两个message, 一个message到另外一个message queue (就叫做cache update queue吧),这个queue的任务是更新第一步里面的cache(看,叔叔没有骗你吧?)。另一个message当然就是发短信确认订座了。 这一步的响应也应该在毫秒级。
当然肯定存在这样的二百五,事先没往铁道部的系统里存钱,要订座了才开始存钱。也有的无聊人士定完座之后不愿意等,不停地刷个人账户的网页看看有没有更新。存款的过程会比较慢,因为要和其他银行系统互联。个人账户/订票历史网页倒可以飞快,把前面的系统照抄一遍就可以了。
7. 当然中国电信/移动/网通之类的必须在春运期间保证铁道部的带宽,如有差错,那就必须不得不把这几个老总们与数名女性发生或保持不正当性关系了。
至于https reverse proxy之类的load balancer问题,就留给小的们办吧。
那么大概盘算一下开销,前端服务器/cache/数据库/message quque,每样来个300台吧,那就1200台,每台大概$1000,一两百万美刀左右吧。加上开发费用,5个mil美刀应该搞定了。报价个2000万美刀不过分吧?
其实像这样的系统实在太初级,世界上现有的highly scalable (Amazon EC2 可以随时调用数百上千个instance救急),高频系统(NYSE的高频交易系统让Knight Capital在一个半小时内损失4.4亿美元),那处理的交易流量不知道比铁道部水平高到哪里去了,人家还不是谈笑风生就搞定了?
你们呀,还是图森破,奶一捂。
能否个人直接查询 个人账户/订票历史网页
获得车票订座的信息?
提交订票信息时可否附加:多车次,优先车次,优先座次信息?
谢谢!
这个可以大幅增加黄牛的成本,并且通过数据分析也可以很容易找出黄牛党,呵呵。
还可以为以后票价浮动做准备,春运期间拍卖车票好了,呵呵。
我有一种感觉,那就是把大象装冰箱里拢共需要几个步骤?
好像一用message queue,就万事大吉了?冰箱门打开,大象塞进去,结束了!
No,No,图森破,奶一捂。
队列这里肯定会成为瓶颈,如果按车次弄他几千个queue,多不多?好像也行,不同的服务器处理不同的车次队列,热门车次多来几个服务器处理
IBM的MQ应对这么大的流量行么,还是自己开发queue管理软件?
你折腾queue干什么?queue上边又没有收费站,不会造成拥堵。1000个queue输出到1台8G的MySql,一样会堵。如果只有一个queue,下游有300个MySql,一样不会堵。
queue只是一个临时存储的storage而已。
注意原文:前端服务器/cache/数据库/message quque,每样来个300台吧,那就1200台,每台大概$1000,一两百万美刀左右吧。
那么就算300个MySql,每个16G内存吧。假设全国每天开行3000列,预售10天,也就3万个车次,分到300台服务器,每台100个车次,没有任何挑战性。
这也就是我根本不提数据库如何实现的原因,因为数据量实在不值一提,小老鼠一只。
唯一的大象就是全国人民在铁道部的个人账户,我已经详细给出了结论。
“存款的过程会比较慢,因为要和其他银行系统互联。个人账户/订票历史网页倒可以飞快,把前面的系统照抄一遍就可以了。 ”
查询车次座位可以随意组合,随时查询多个车次,因为“查询车次:请求被负载均衡到任意一台前端服务器,前端服务器直接按车次/时间把做好的html从一个hashmap里取出来,扔回去给用户。全部响应时间应该在毫秒级。”
册那,这12306居然又宕机了。高,实在是高。
听说国内一帮人还开始搞什么12306开源,估计那帮孙子还在吭哧吭哧地“优化sql”。听着就不靠谱。别SQL了,现在都NoSQL了。
吼一声,转载一定得注明西西河布老虎。
按楼主的说法,性能的瓶颈在数据库,那么配置个1000,2000或者5000台sql,就什么都搞定了。还折腾同步异步干什么?
不能闭着眼睛瞎设计。
不过小同学还是善于思考滴,虽然没有实际经验,还是值得表扬。
Memcache一般40ms左右,数据库要高一点,到100-200ms左右。这个仅仅是正常延迟(包括线路延迟,查询延迟)。如果搞一点fancy的query,那就200ms往上了。
所以要在前端做好HTML,从cache里面pull数据(当然也可以从cache里push数据到前端服务器),隔离read request,也就是刷屏请求,不让它进入后端。
只有write request可以进到后端,但是后端有若干业务逻辑,累积延迟就难说了。所以每一步都要用queue来削峰平谷。
你地明唔明啊?
分离读写没有问题,可以分离读写数据库,读数据库用memcache也好用普通数据库也好,都问题不大
但按你的估计,积累延迟有多少?会不会一次订票的延迟达到不可忍受的地步?
读写分开后,只有订票的业务会访问写入数据库。按我google的结果“8日,铁道部副部长胡亚东介绍,网络和电话订票每天达200万张[B][/B],从1月1日至8日,12306网站日均点击次数超10亿。”。这样的访问压力级别,即使同步访问也可以轻松应付,压根用不着异步。
节假日前几千万人一起存钱或者查询余额,这个存钱系统说不定死的也很快。可能预付卡更好一点吧。
小同志,我也想今天打一个冲锋,明天就消灭蒋介石反动派。但是不行啊,革命没有那么简单。我们既要防止右倾投降主义,比如说全国人民永远没法网上订票之类的,也要防止左倾盲动主义,比如像你这样的,随便一个LAMP两天就搭好架子。
总的来说,用async是scalability的要求,是一个good design priciple,是无数先烈用website crash换来的教训。它可以完成和sync call同样的任务,但是容错性和scalability是sync call无法达到的。
In conclusion, anyone who suggests to use blocking calls to scale to the web, should be fired into oblivion.