听豆瓣架构变迁分享会总结

要点如下:


目前23台pc server


每天pv数2k万左右。注册用户数300万。
表的数据,大部分是行数量是千万的。

5个人算法团队。另外开发人员总共11个,包括全职和兼职(以前看百姓网分享其技术也只有10名)

06年的时候每天120万左右动态请求。这个时候主要瓶颈在磁盘i/0上面,拿到风投,有钱购买硬件设备。购买两台iu服务器(双核,4g内存)
一台作为应用服务器,一台作为数据库服务器,迁移到双线ip机房,使用dns解析不同网段ip(自己去找哪些网段是电信的哪些网段是网通,然后自己进行解析)。看演讲后面提到的机房调整感觉到,其实这是走了弯路,可以选择一个好的机房来解决dns解析方面(后来总结是靠ip段来分布数据不靠谱)

具体怎么做,就是放到一个支持多线的(教育网铁通等)机房,现在我们公司用的阿里云就是多线)
那么这样子就不需要自己多ip段分配了(就是判断访问用户是电信还是网通等)。

使用内存缓存(豆瓣使用的是memcached)的两点原则:


1、对于需要比较消耗资源的数据。比如需要大量计算才能得到结果,那么预先计算好,放入到缓存中供查询。
2、需要重复使用的数据。如果只需要使用一次,那么即便是比较消耗资源,丢入缓存也没多少意义

理解:内存缓存也需要内存,没必要浪费。如果不需要重复使用,丢入内存中也比较浪费(毕竟内存不便宜,也占用服务器资源)

豆瓣的memached命中率挺高的。靠这个也缓解了很多压力。



innodb并发访问支持好,因为支持行级存储。使用myisam还是innodb他们的的业务特点是:读多写少使用myisam,写多读少使用innodb

数据库切分方面:目前是按照功能进行分区(作者没有详细解释,应该是按照功能模块划分表。一个功能模块相关的表放到一个库中去),提到,采用了经典的mysql主从架构。所以每个库其实是重复三份的(他说的主辅库)。应该是三个mysql从服务器

分库之后,操作多个库,使用游标的方式获取具体的库和具体的表。传入参数进去(具体没看懂)

 

其实,水平切分维护起来很麻烦,比较复杂。先还是垂直拆分为好。实在满足不了了。后面考虑水平拆分。



数据库主从复制延迟问题一直是一个常见问题。

购买硬盘是一个教训:刚开始还是宁愿投资多点钱购买好的点的磁盘,因为磁盘这东西升级不太可能。到时候网站扛不住了。仍然得换。那么,刚开始宁愿多花点钱,购买高速磁盘,因为业务如果发展快了的话,就得换。即便开始贵点,应用远远没达到硬盘瓶颈,磁盘仍然没有被浪费。



200万每天的动态请求的时候,豆瓣提到,静态的小文件服务(用户头像、封面图片)使得磁盘i/0成为瓶颈,以前愚蠢得把图片都放到一个目录下面,这个目录下面有几十万个小文件(直接导致不能使用ls命令,一使用服务器就死掉了),这个时候把文件分目 录。分成每个目录存储10000个文件。



有专门的数据挖掘团队。算法团队进行矩阵计算,把结果放入mysql,供前端查询显示出来。


豆瓣的fs是专门针对图片存储,自己开发的。其实机制是参考了amazon的,写的时候写三份数据。


磁盘随机寻道比吞吐量更加重要,当时的性能瓶颈在磁盘寻道速度上(这点跟之前看淘宝的图片文件系统分析的大量的图片访问带来的磁盘磁头频繁定位造成的延时类似)


后来把所有myisam表改为innodb表。

innodb的缓存:是在进程中自我管理(也就是内存中),而myisam的缓存是基于文件中(受操作系统控制)。以前既用myisam表也用innodb表,导致两种类型的表相互竞争内存,效率不高。索引全部换成innodb存储引擎(这点我不是很理解,只明白其考虑点是为了更好利用内存)



应用服务器故障:nginx自带功能。


图片的流量成为很大成本:迁移到天津机房是因为更加便宜点。机柜比较便宜,把数据挖掘方面的数据和图片数据都搬过去。

北京与天津两个机房。里面各自搭建mysql的master-slave结构。



搜索方面:以前一直使用mysql的全文索引。后来迁移使用sphinx(这个结合mysql来使用,作为mysql的一个存储引擎),后来又变为xapain

为什么没使用sphinx了?没有详细解释


使用MogileFS来存储图片,后来又自己开发了doubanfs存储。迁移的原因:mogilefs出现性能瓶颈,由于mogilefs是把元数据(命名空间, 和文件在哪里)存储在mysql中,数据库行数变多之后,就会变得越来越慢。而大量的小文件需要读取数据库,也影响了速度。当时的行数增长非常快,当时瓶颈在于mysql数据库上。



大字段影响了数据库的性能,实际上数据表行数并不多。就是大字段的影响。大文本字段移除出去,存储到自己开发的doubanDB中(是一个key-value数据库,参考了亚马逊的dymamo,进行简化)。底层存储基于tokyocabinet。后来把doubanfs重写,基于doubandb实现,把图片存储进去。


使用双master方案。解决了复制延迟问题,因为写和读都是对同一个master,读取到的数据是最新的。而以前:从master写入,然后从slave读,存在数据延迟



部署lvs。

之前使用spread作为消息队列,后来使用rabbitMQ替代

 

 

关于mysql数据库进行在线ddl

 

听过豆瓣网的架构变迁分享会中提到,他们以前在这方面也吃过苦头的,一张很大的表(比如上千万),在线加个索引,由于数据量大,整个应用就卡死了。

其实有时候卡几个小时可能都很正常。死锁了嘛。另外对临时表要进行复制数据,建立这个临时表也需要时间嘛。

 

他们现在用的办法是:先拷贝一张一模一样的表,数量也是差不多,先在这张表上面测试,看看需要多长时间。如果几分钟,是在可以接受的时间范围内,就可以。如果几个小时就不行了。这样子提早预先知道。

另外,也使用了online-schema-change这个工具(没明说,不过我从他们运维另外一篇文章分享教训的时候看到过)

 

这是很多大数据表在线ddl都会碰到麻烦,后来我专门总结了业界对此常见的办法:http://www.cnblogs.com/wangtao_20/p/3504395.html



=========================================================


总结:照搬其架构和技术方案是不可行的。借鉴他的错误经验和背后的设计思想才能学到本质(主要了解为什么那样子做,出于什么考虑)。

教训:磁盘的选择和机房的选择。磁盘选择转数快的,开始成本贵点值得。

分库,首先从功能角度划分区。暂时还没必要去做水平分区。功能相关表放到一个库中或者单独的服务器上这是必经的阶段。

把钱花在内存上是值得的的,一台机器的内存永远不嫌多,数据库消耗的内存比较多,一般内存往往会成为瓶颈(大量连接,计算数据都能导致内存不够用)。memcached并不廉价(网络i/0,消耗cpu)。放入memcached的东西要慎重。

避免数据库的join操作(这点与以前看的石展分享的观点类似,减少join操作,宁愿拆分成多次获取数据,facebook的架构中也提到不做JOIN 操作)



总体感觉,从豆瓣中学到数据库方面的经验是分库方面。他们的访问量级别还不需要进行到水平切分,进行分库即可了,按照业务功能分区。一个业务功能模块相关的表都拆分到同一个库中去。然后对数据库服务器做主从同步保持数据热备份。

Sharding 在业界的应用场景基本上也就是这种读应用比较重的情况,而且对事务的安全性要求不高,这样的场景会非常适合。

sata*3查了一下 450G 1000多块钱一个。

sata硬盘故障率比较高,换了scsi硬盘。

针对图片存储或者小文件存储方面,因为量大(流量成本,存储成本),开发了自己的文件系统

图片存储如果依赖于数据库做存储,数据量大之后,确实会成为瓶颈(难怪淘宝的图片文件系统,将一部分元数据隐藏到图片的保存文件名上)


疑问:北京和天津跨机房,两边的mysql之间进行同步数据,或者是天津那边的数据挖掘程序往北京写入数据,这个速度如何?

这个我查了一下资料,一般是需要使用专用光钎网络通道。

posted @ 2013-12-21 14:38  王滔  阅读(2154)  评论(0编辑  收藏  举报