简单讨论火车票系统后面的架构设计
来源:51CTO技术博客 2012-01-16
简单说,在线服务scalability有两种方式,scale-up和scale-out。Scale-up追求单机性能,如高级硬件、异步架构等,而scale-out则用加机器的方法。Scale-out也是最简单的方法,在规模不是非常大时很好用,也很容易解决问题,普通工程师就足以胜任。有很多现成的方法或模块可以使用。
也就是说,很多时候通过加机器就能解决大多数问题。只要规模在一定量级下(通常的在线系统规模都不会特别大),我们可以先不考虑硬件故障以及自动运维。
但为什么很多时候系统还是崩溃呢?罪魁祸首就是请求的尖峰,10倍于平常的压力是很正常的。普通模型到达性能瓶颈后,开始堆积请求(可能在web server,也可能在请求队列,不过通常不会在CDN),吞吐急剧下降,延迟急剧上升,而随着堆积请求越多,情况越糟,引起雪崩效应。而这样的压力通常不会持续很久,如果性能不急剧下降的话,一段时间后其实也就能把请求都响应了。
为10倍压力而准备机器是不合适的,我们需要有办法能扛住瞬间压力。这时候架构设计主要考虑的问题,也就是我上个weibo所说的,如何保证极限情况下的稳定吞吐。有很多种办法,分级队列、请求调度、延迟截断、主动拒绝等等,这些都有助于帮系统度过艰难时刻。具体的做法,就不在这里讨论了。
当然,我也并不是说这个系统是非常难做的,因为可以有很多种做法,如普通文艺、高级文艺等,:)。如何用软件架构的方法来实现scale-up就很困难,做得好与不好可能性能差异能达几倍到一个量级。但对于普通公司来说,直接scale-out是最合适的,规模不大时多一些机器也不会对成本产生太大影响。但关键的是,要注意如何处理峰值压力,提供极限情况下的稳定输出。也就是说对于普通在线系统,即那些transaction-based systems,规模不太大,只是可能有海量的用户请求。只要在设计时注意极限情况下的稳定输出就可以了,实现的工艺水平高不高,差别只是机器多少而已,通常看不出来。
对于大数据量的系统,无论在线或离线(其典型代表就是搜索引擎),则又是另外的故事了。
再谈谈火车票系统
昨天那篇weibo发后,收到很多反馈。有很多朋友给了正面评价,非常感谢。也有些亲给了差评,这本无可厚非,只是其中有些人我感觉都没仔细看文章,时有露怯。也有人怀疑我只会说,没写过程序。我不想自吹,在十几年的程序和研究生涯里,几乎所有名字中含system字样的系统我都亲手做过。到百度做了几个实际系统后,负责了更多事情,这才转为设计规划,不再事必躬亲。
令人反感的是,有人说我拿了黑钱,这纯属无稽之谈。
还有些朋友给了一些非技术层面的建议,也非常感谢。我也知道这些问题所在,也考虑过用产品设计的方法来避免。之所以还来讨论,只不过是想借这个系统谈谈架构设计的一些看法。本人一向喜欢风花雪月,不想凑热闹不好为人师。只是恰好碰上自己的专业领域,这才斗胆来碰这么热门的事件。
我再阐述一下我的观点。这个系统的复杂度在于海量的并发请求,并发性可以通过scale-out(简单来说,就是堆机器)加以解决,但最难的却是保证系统的稳定吞吐。我想说明的是,在线系统应以保证极限情况下的稳定输出(sustained throughput)为首要设计目标,而这是不容易实现的。至于如何切分数据,如何scale-out,这和具体业务特点关系密切,在不知道火车售票具体业务模型的情况下,不好进行讨论。
对于一个理想的在线服务系统,应该包括几方面的能力。1) 单机高性能,也就是所谓的c10k能力。2) 良好的scalability。简单来说,就是加机器可以提升系统性能。3) 稳定输出,特别在极限情况下。4) 良好的自管理自运维能力,在故障、升级或扩容时尽量减少人工介入。
但是,并不是所有的服务都*需要*在以上4个方面做得很好,也不是所有的互联网公司都*有能力*在这4个方面做得很好,甚至很多工程师或架构师都没有*意识*到需要考虑这些方面。
所以,前一篇文章中我的建议是:
a) 可以先不考虑1,因为要提高单机性能难度很大,而效果却并不明显,通过加点机器即可取得同样效果。当然,作为一个old-fashioned engineer,我个人很喜欢做这样的事情。百度的快照库是我到百度后做的第一个系统,单机性能比旧系统提升了10倍以上。
b) 在业务不太复杂的情况下,加机器是最容易提升scalability的方法。我不了解具体的火车票业务模型,不太好讨论,但通常只要能把锁和正常的业务逻辑decouple,问题就不大了。谈到锁,多说两句。用它来保证的同步互斥,是并行系统中最基本的问题。有很多种做法,难度迥异。比如一些lock-free patterns,如果工程师的志向不在于此,不建议尝试。在实际中,按照我的review经验,只要能分解掉那把全局大锁,效果就很好了。
c) 最重要的是sustained throughput。在峰值压力情况下,平滑过渡,可以有效避免雪崩效应,大幅提升用户体验。我提了一些做法,很多朋友说这在通信系统中也是常用的。有兴趣的朋友也可以去研究一下queuing theory,看看latency和throughput是怎样的关系。
d) 在小规模时可以先不考虑自管理自运维能力。随着机群的扩展,故障处理、扩容减容以及服务调度等等逐渐成为最头疼的问题,而这正是分布式系统所要解决的最难的问题。对于大互联网公司来说,应该深有体会。
相对于普通的在线服务,搜索引擎的规模和复杂度要高出一到两个量级,很多考虑问题的出发点也不一样。习惯了这样的思考方式后,我也不太敢直接来设计一个火车票售票系统,over-design就麻烦了,呵呵。所以,以上根据系统的设计原则给出一些建议,希望有用。
本文来自: http://baidutech.blog.51cto.com/4114344/762993[ comments ]