百万级访问网站前期的技术准备(中)

Posted in 互联网, 编程 on 2010/12/05 12:47 by 志一 – 21 Comments

书接上文 百万级访问网站前期的技术准备(上)

七、数据库

几乎所有操作最后都要落到数据库身上,它又最难扩展(存储也挺难)。对于mysql,什么样的表用myisam,什么样的表用innodb,在开发之前要确定。复制策略、分片策略,也要确定。表引擎方面,一般,更新不多、不需要事务的表可以用myisam,需要行锁定、事务支持的,用innodb。myisam的锁表不一定是性能低下的根源,innodb也不一定全是行锁,具体细节要多看相关的文档,熟悉了引擎特性才能用的更好。现代WEB应用越来越复杂了,我们设计表结构时常常设计很多冗余,虽然不符合传统范式,但为了速度考虑还是值得的,要求高的情况下甚至要杜绝联合查询。编程时得多注意数据一致性。

复制策略方面,多主多从结构也最好一开始就设计好,代码直接按照多主多从来编写,用一些小技巧来避免复制延时问题,并且还要解决多数据库数据是否一致,可以自己写或者找现成的运维工具。

分片策略。总会有那么几个表数据量超大,这时分片必不可免。分片有很多策略,从简单的分区到根据热度自动调整,依照具体业务选择一个适合自己的。避免自增ID作为主键,不利于分片。

用存储过程是比较难扩展的,这种情形多发生于传统C/S,特别是OA系统转换过来的开发人员。低成本网站不是一两台小型机跑一个数据库处理所有业务的模式,是机海作战。方便水平扩展比那点预分析时间和网络传输流量要重要的多的多。

NoSQL。这只是一个概念。实际应用中,网站有着越来越多的密集写操作、上亿的简单关系数据读取、热备等,这都不是传统关系数据库所擅长的,于是就产生了很多非关系型数据库,比如Redis/TC&TT/MongoDB/Memcachedb等,在测试中,这些几乎都达到了每秒至少一万次的写操作,内存型的甚至5万以上。例如MongoDB,几句配置就可以组建一个复制+自动分片+failover的环境,文档化的存储也简化了传统设计库结构再开发的模式。很多业务是可以用这类数据库来替代mysql的。

八、缓存。

数据库很脆弱,一定要有缓存在前面挡着,其实我们优化速度,几乎就是优化缓存,能用缓存的地方,就不要再跑到后端数据库那折腾。缓存有持久化缓存、内存缓存,生成静态页面是最容易理解的持久化缓存了,还有很多比如varnish的分块缓存、前面提到的memcachedb等,内存缓存,memcached首当其冲。缓存更新可用被动更新和主动更新。被动更新的好处是设计简单,缓存空了就自动去数据库取数据再把缓存填上,但容易引发雪崩效应,一旦缓存大面积失效,数据库的压力直线上升很可能挂掉。主动缓存可避免这点但是可能引发程序取不到数据的问题。这两者之间如何配合,程序设计要多动脑筋。

九、队列。

用户一个操作很可能引发一系列资源和功能的调动,这些调动如果同时发生,压力无法控制,用户体验也不好,可以把这样一些操作放入队列,由另几个模块去异步执行,例如发送邮件,发送手机短信。开源队列服务器很多,性能要求不高用数据库当做队列也可以,只要保证程序读写队列的接口不变,底层队列服务可随时更换就可以,类似Zend Framework里的Zend_Queue类,java.util.Queue接口等。

十、文件存储。

除了结构化数据,我们经常要存放其他的数据,像图片之类的。这类数据数量繁多、访问量大。典型的就是图片,从用户头像到用户上传的照片,还要生成不同的缩略图尺寸。存储的分布几乎跟数据库扩展一样艰难。不使用专业存储的情况下,基本都是靠自己的NAS。这就涉及到结构。拿图片存储举例,图片是非常容易产生热点的,有些图片上传后就不再有人看,有些可能每天被访问数十万次,而且大量小文件的异步备份也很耗费时间。

为了将来图片走cdn做准备,一开始最好就将图片的域名分开,且不用主域名。很多网站都将cookie设置到了.domain.ltd,如果图片也在这个域名下,很可能因为cookie而造成缓存失效,并且占多余流量,还可能因为浏览器并发线程限制造成访问缓慢。

如果用普通的文件系统存储图片,有一个简单的方法。计算文件的hash值,比如md5,以结果第一位作为第一级目录,这样第一级有16个目录。从0到F,可以把这个字母作为域名,0.yourimg.com到f.yourimg.com(客户端dns压力会增大),还可以扩展到最多16个NAS集群上。第二级可用年月例如,201011,第三级用日,第四级可选,根据上传量,比如am/pm,甚至小时。最终的目录结构可能会是 e/201008/25/am/e43ae391c839d82801920cf.jpg。rsync备份时可以用脚本只同步某年某日某时的文件,避免计算大量文件带来的开销。当然最好是能用专门的分布式文件系统或更专业点的存储解决方案。

下面,我们要谈谈代码了。

新浪微博 QQ空间 人人网 开心网
  1. youstar 说道:

    写的不错,谢谢分享

  2. 魂飞魄散 说道:

    写的很好 期待楼主更多佳作 小说写的也不赖

  3. wellhome 说道:

    Hi Zhiyi,
    关于你说的 pull方式的备份mysql 可否详细说明几点?
    我现在的数据还非常小。但当年我记得数据库很大了。用mysqldump是个非常傻的备份策略。。。
    主从replication总是有各种原因造成出错。。。好像当年的replication不是很稳定。。

  4. Rock 说道:

    能不能写点介绍NoSQL的文章

  5. kuhanzhu 说道:

    你真的确定你的“百万级”的网站用ubuntu做系统?

  6. 教育网 说道:

    不得不学习一下

  7. 陌上清溪 说道:

    写的不错。有空在多写点,多爆点料出来。

  8. leeign 说道:

    写得真不错,支持~

  9. 站长工具 说道:

    写得太好了,学习了.

  10. felix021 说道:

    经验之谈,学习了。期待下篇。

  11. feng 说道:

    mysql 数据库的扩展,负载均衡有什么办法吗,我的db 压力很大!

  12. zigbee 说道:

    网站到了百万级别,就不愁没有没有钱请技术了

  13. javalet 说道:

    你好,这量篇帖子很有技术含量,期待下一篇
    我也了解过淘宝网和优普系统的发展历程,前期发展和你说的很相似,遇到了很多发展瓶颈,如果早点看到你的文章,可能会少走很多弯路
    我留了邮箱在留言中,可否发个信给我,期待认识仁兄
    ooo,我也从事大型网站开发很多年了。

  14. magic 说道:

    非常赞

  15. brillian 说道:

    Extremely useful!
    so, shall we make friends.( A technology man with hard steps)

  16. 纳粹 说道:

    我晕死。
    头大,好复杂啊。
    我现在也就是用着虚拟主机跑着开源的WP、DZ等程序,唯一限制网站发展的,就是我的流量上不去。
    我觉得,如果哪天我的流量突破了5G/天的话,也就有钱请技术员了。
    这帖头疼的事,还是留给技术好了。

  1. There are no trackbacks for this post yet.

Leave a Reply