关于12306网站和清华某院长的微博言论,我做了一个小答复,说这玩意不难,2小我2周,40台办事器可以弄定。
下面详细诠释一下年夜概的思路。免费share一下,看看靠谱不靠谱。
他人看到的是流量,我先看布局,这里的数据布局是相当简单的,主要满足的需求是:
1.车次查询(最常见的是起点站,终点站查询 和车次直接输入查询)+余票显示
所谓的用户刷页面,绝年夜部分应该在这里。日均10亿pv(这个数字我先质疑一下,不过么关系,后面再说怎么措置),估计主要落在这个查询上。
2.注册,登岸。每天过千万人次是有的
3.下单,也就是日成交订单量,可能存在下单失败,约几百万次。
这里根基不涉及复杂的关系操作,不涉及推拉布局,和新浪微博,facebook这样的应用场景相比,在数据关系上的确毫无难度,这也才是我敢说年夜话的原因。
因为不涉及复杂的关系操作,不涉及个性展示(不适用户搜索同样的条件,成果一致),那么缓存化就是最佳途径。
1.存储key-value化, 推荐redis
根基上查询都是直线式的,所以key-value就是很好的东西;因为出票可能需要找一下车次,座位,只能一一对应的查询就欠好用;弄个redis带个列表布局(dict or zset ,哪个布局更适合?问问新浪架构师杨卫华吧,这事估计对他太简单了)进去便可以了。春节放票总共多少张?又不是一次放出来,每张票对应一个key,一个value,能吃多少内存?后面跟个数据库做同步,这点数据量对现在的办事器来讲底子不是问题。
注册登岸也可以在 mysql根本上弄个redis挂在前头响应,这种查询速度,biu.
按照不合车次分几台办事器,响应速度底子不是问题。
2.将所有查询成果缓存化,静态化
首先明确一下查询的步调,实际上主要查询分两步
第一步是查询适合要求的车次,第二步是查询余票。
缓存也就分两步做,起始地,目标地查询 - 常见查询目标(如北京到成都)全部预制缓存。很是见查询目标,基于第一次查询的成果缓存,这样查询车次根基上无压力。
查询有票状态就更简单了,因为票数只有有票,无票两个状态,某日某车次作为一个key-value类型存储(仍用redis便可)。某类车票产生从有到无或从无到有的转变,才通知缓存更新。更新是后台通知的,而非基于用户查询。比如某车次硬卧票售完,通知一次更新,硬座售完,通知一次更新,软座售完,通知一次更新。以此类推,这样的缓存更新次数少少。并且可以给前端返回甚至静态成果(基于查询条件生成静态成果,是个搜索引擎优化er城市的,后台在票数转变时通知更新,这样布局上就与前端查询无关了,并且一样可以连健壮时性)。
如果你叫真说,其实一个车次在不合区间也存在有无票的不合,的确,不过依照同样思路,布局多做一层死不了人的。事实成果这只是概述。可是核心思路不变,缓存的变动次数远少于查询请求次数,这就够了。
3.前端缓存措置
很多人被10亿请求数吓到了,其实这里水分很年夜,最多的是重复刷新和外挂东西,那么如果你做到基于2的查询成果缓存化,这一步就简单了;直接拜见这篇文章,年夜量的用户重复刷新底子不是问题。 想知道实际效果,看这里1小时20亿的刷新都不怕,还怕你一天10亿刷新?
4.i/o优化
其实我甚至感觉用了redis都不需要做i/o优化了,如果用户单据需要数据库保存,一天200万单嘛,搜一下 淘宝手艺专家余锋分享的qcon讲座文档,顺便读一下他历来新浪微博分享的文字,这个需求的确就是小儿科了。 年夜不了狠狠心买几块ssd硬盘做raid1/0,对我这样的穷架构师来讲,都属于年夜手笔了,至于昂贵的fusion-io,我真感觉,这个场景用不着,实在用不着。
这里关头点,是查询成果的静态化和前段缓存的操纵
查询怎么可能静态化?
因为
1:重复查询的频度远远年夜于数据更新的频度(即便是票数的更新,也是500:1,更不消说是有无的转变)
2:静态化不代表不动态更新,在订票成功后,如果产生了票数状态的改变(是状态改变,而不是数字改变),办事端更新或删除该静态成果(下一次查询重新生成静态成果)
至于为什么说2人2周,别弄花的,别图都雅,就把这些布局捋清楚,代码能有多少行?这玩意没什么工作量。