posts - 262,  comments - 221,  trackbacks - 0

最近一直在学习大型网站的架构和性能优化,疯狂地从网上寻找各种可能的架构资料,终于在InfoQ上找到2009 QCon举办的QCon全球企业开发大会北京站演讲资料。

挑了我最喜欢的几个大型网站(豆瓣、淘宝、优酷),先看了豆瓣的主讲人洪强宁分享的《豆瓣网技术架构变迁》。看完后有几个感觉:

 ※ 罗马不是一天建成的

豆瓣在5年内经历了6次架构的调整,和淘宝有得一拼啊。任何优秀的架构都是在不断的问题和瓶颈中发展起来的

 ※ 总是考虑使用Memcached

应该在系统架构的第一时间就考虑使用Memcached,按照洪大师的说法。豆瓣现在的内存缓存有38G。Memcached的好处地球人都知道了

 ※提防Memcached的并发访问

Memcached虽然是剂猛药,但也有可 能成为毒药。特别是在高并发的情况下同时获取一批缓存数据的时候(不知道新版本的Memcached解决这个问题没有,当时我第一次看到这个功能时那是激 动得内牛满面啊~~~)。要知道Memcached毕竟只是个缓存工具,不是内存数据库。不要指望他提供什么锁、并发控制的机制(不过它倒是提供了一个原 子操作increment,用于递增数据,对于刷新页面访问量之类的比较有用)

 ※ 根据数据访问特性合理规划表类型

使用MySQL的数据库,可以方便地使用不 同的存储引擎对应不同操作类型的表(貌似对于其它数据库,还没有这种功能。也可能是我孤陋寡闻了)。对于读写不平衡但并发低的情况,采用MyISAM可以 获得较高的效率。网上google了一把,ISAM的意思是Indexed Sequential Access Method (有索引的顺序访问方法),它的优势是速度快,支持全文搜索;但对事务支持差(PS:个人意见这个用来做数据分析或者数据挖掘最好了 ^_^)。如果是用于高并发的读写访问,那么只能采用InnoDB类型的表了。

 ※ 动静分离

使用lighttpd具有比Apache更好的静态文件处理功能(PS:个人见到从豆瓣的第一个版本开始到目前为止的版本,只有两点是不变的:1.使用lighttpd对精通文件进行分离,直接从FS读取。动态的走SCGI接口。2.使用Memcached)。

 ※ 对缓存、数据库进行负载均衡,例如MySQL Proxy

使用类似于Load Balance来平衡Memcached的负载。不同于Round-robin方式,采用的是hash分配。自己实现Hash算法(PS:这个倒是和网上 的多数观点一样,但缓存的东西多了,命中率总是会下降,要么扩大内存要么改算法,避免多次的重新分配)

 ※ 不要忽视小文件的读写

在豆瓣的某个发展阶段,就出现了因为大量的小图片读写而造成大量的磁盘IO和碎片的问题。原来豆瓣一开始也是把所有图片都放在一个目录下啊(),后来出现问题后才改成1000个图片一个目录。要不按照洪大师的说法:一个ls就可以让服务器挂掉。

 ※  屏蔽表名和物理表的关系

通过中间映射实现底层物理数据表的无缝迁移。(PS:这个只要是做过Java的都知道了,IoC,代理其实也就是这个作用),具体的做法就是只传一个逻辑表名进去,后台函数映射后解析成一个真正的物理表所在的位置,方便日后的数据迁移,只要维护这个映射表就好了

 ※ 数据复制(主从模式)是必经阶段

 当主数据库出现瓶颈时,要考虑采用数据库 复制的方式(Master / Slave模式),主库负责事务性读写,从库负责非事务性读(不能有写)。数据库复制的形式在豆瓣的发展上发生了很多次变化,我看到的就有从单点的复制到 最终的跨机房复制。这一点可以从后面的PPT看到

 ※ 数据库复制是存在时间延迟的

数据库复制的延迟时间要考虑在内,否则会出现当主库写完后,未来得及复制到从库就出现Application从从库读数据的情况,严重的话用户每次更新数据后再刷新看到的永远都是旧的数据(缓存还没有更新,同步的数据还在路上呢....)。


 ※ 人肉刷新缓存有时候是必要的

接上面的问题,洪大师的团队最终采用了“人肉刷新”---- 即在可预见的情况下,内存中的数据更新后,主动调用Memcached的flush()方法刷新一下缓存,先同步了缓存再说,后面的数据你就慢慢复制吧。这个只能靠程序员自己控制了....ORZ

 ※ 统一的Data mining入口

豆瓣的数据库复制机制中有一个特别的“Data mining”模块,由它负责把数据写到主DB,再从主DB replicate到从DB,然后Data mining模块从从DB read。这个有点搞不懂?这个“Data mining”到底是什么来头?怎么所有数据都从这里写,甚至连主DB的数据都是从这里写进去的?

 ※ 分离服务器

把服务器分成控制服务器、应用服务器、代理服务器。分别对应入口转发,应用请求,负载均衡。把数据挖掘、日志分析、爬虫应用之类占用带宽,耗内存的东西全都移到后端,放在月黑风高,夜深人静的时候去进行吧。

 ※ 硬件的故障不可忽视

SCSI比SATA的稳定性要高,花在内存上的钱是值得的

 ※ 永远不要高估机房托管方、空间提供商的智商和责任心

比如洪大师说的:搬机器的时候不小心把你们服务器的电源线拔了之类的问题...

 ※ 如果你够牛B,那么考虑实现自己的内存数据库和文件系统

例如DoubanFS、DoubanDB(貌似这是一个基于key-value的内存数据库,看来内存数据库在未来大有可为啊,该死的hibernate,该死的iBatis,该死的OR-Mapping)。

以上是豆瓣洪大师的观点,加上最近看到的其它,也一并总结一下吧:

 
※ 尽可能在长事务的情况下使用异步通信,例如发送SMS、MMS到网关然后等待回应

 ※ 对数据库采用水平分区而非垂直分区以加强后期的扩展性

 ※ 合理恰当地使用索引

 ※ 在高层次的地方使用缓存,而不要在低层次的地方使用缓存

 
※ 建立科学合理的性能、压力测试环境。性能瓶颈总是出现在你意想不到的地方



-------------------------------------------------------------
生活就像打牌,不是要抓一手好牌,而是要尽力打好一手烂牌。
posted on 2010-03-19 22:21 Paul Lin 阅读(1501) 评论(0)  编辑  收藏 所属分类: 架构与性能

只有注册用户登录后才能发表评论。


网站导航:
 
<2010年3月>
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

常用链接

留言簿(21)

随笔分类

随笔档案

BlogJava热点博客

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜