2008-03-03

互联网上有很多金矿,但是并不是属于你,好的创意只是成功的第一步。而且很多时候太好的创意反而最终是失败,只有成熟的商业模式和团队才是创业成功的关键。商业模式最终讲体现到盈利模式,而盈利模式有需要有实际的产品和调研数据来支撑,你需要清晰的讲出来你具备的团队,环境,资金,产品能够使你持续的盈利。不可否认也有很多前期商业模式并不是很清晰的最后创业成功的,但是这仅仅是个例而不能代表全部。

1.好的商业模式必须能够盈利

互联网大笔烧钱的时代已经过去,并不是说盈利一定要有多少,而是要实现投资回收期的尽可能短。这样的话商业模式才可以自我验证和适应,很多时候我们一开始就把产品或规模做的很大,但是后面可能是营销不出去,我们的投入无法真正产生收益,在这种模式下整个商业模式是不可持续发展的。

在互联网时代的创意需要的是尽可能短的时间拿出产品,我们的产品或服务必须定位到足够小的小点上,只有聚焦才可能发挥小型团队的优势,避免资金上的弱势。我们可以尽可能早的推出产品,尽可能早的获取相应的回报以支持产品开发的持续和自适应发展。

真正看好某个产品或服务的创业者必须要自己投入前期资金进行创业,而不是一开始就去选择创业或风险投资。自己都不看好的产品,自己都没有清晰的商业模式来确保盈利的产品是不值得马上投入的。

另外我们还必须清晰的认识到,盈利模式必须清楚,网站的访问量和用户资源仅仅是盈利的基础条件。互联网创业不可能是长期的亏钱赚吆喝,你必须要清楚的认识到在有了访问量和用户资源后可以形成的增值服务和盈利途径。

2.商业模式必须是自我保护的

创意是不值钱的,一个好的创意会很快的被竞争对手所仿效。或许对手在资金和积累上比你有更多的优势,对手看好了某个好创意后可能会推出竞争性的产品而后发制人。那么你可能仅仅变成的大企业对一种商业模式是否可行研究的一个试验田。

商业模式的自我保护会铸起一个壁垒而让对手不容易轻易的仿效。或者当对手想仿效的时候你已经培养了大量的忠实的用户群。互联网创业先入为主尽快的形成一批稳定的访问量和用户群是自我保护的一个要点,对于提供的产品或服务有某些核心的难以仿效的技术优势也是自我保护的重要体现。

当前期资金有限的时候,我们更强调的是创业需要聚焦到足够小的点上,在这些小点上有保持团队持续发展的盈利,但是由于聚焦点小往往又激励不起大型企业加入这块市场竞争的兴趣。这个时候你是最安全的,可以循序渐进的将自己壮大起来。

3.商业模式必须是自启动的

前期的资金量少并不是不能立刻开始的原因,前期投入少才更需要我们去考虑资金的回报周期和资金的周转。自启动需要我们就是前期投入少量的资金,这些投入能在尽可能短的时间内产生收益而补充到产品迭代开发中。

前期投入的越多,我们面临的风险和负债越大。自启动模式需要我们规划好产品的迭代开发计划,使产品尽早面市。同时产品推向市场又可以让用户来检验商业模式的可行性,以修正后续计划以降低风险。

4.商业模式必须是自适应的

在软件开发中我们经常强调自适应开发,强调开发要适应需求的变化。在互联网创业中我们同样强调的是商业模式能够适应外部环境,市场,人员和技术等各种因素的变化。这样,在环境和市场需求发生改变的时候,我们前期的投入往往就没有白费,而是可以很好的重用来研发其它的产品或服务。

5.商业模式要有财务退出策略(不是必须)

对于小型团队的互联网创业,我们所期望的财务退出策略是被大型企业所收购,或者说争取获取到风险投资后在中小板上市。如果你能创立起一摊生意然后把它卖掉,你就能从你建立起的公司净值中套现。如果你卖不掉,你所得的则是年盈利。两者可能有天壤之别。比如Yahoo,上市8个月后,它的净值有10亿美元,但过去一年中盈利只有2美元。这个5亿比一的巨大比例是不正常,也不长久的。

2008-02-18

目前随着手机与电脑等互联互通,智能手机的普及以及手机客户端软件的普及那么将来的手机病毒将会陆续出现,反手机反

病毒客户端软件在未来几年后将会是一块非常大的市场,目前几大杀毒软件产商可以研发这方面的软件了,那决对是一块甜

饼。

2008-02-14

这段时间呆在家里无聊就看了一部中韩合演的爱情电视连续句,看完之后学会了一些道理,虽然电视情节是以兵法中的36计来追寻自己的爱情为主题,但从中能够给人一种很深的如何做人哲学道理,现把我看完后的总体感受总结如下:

1、真心(对什么人、做什么事;爱情也好,事业也罢。都要以一颗真心去对待)。
2、爱好、执着、坚持(要想成功就一定要去坚持执着的去做自己喜欢的事)。
3、恋爱没有什么兵法妙计可言,顺其自然最好,不需要刻意的去讨好或者假装。
4、交朋友需要平等对待,用心去交,而不要以金钱,地位,外表等做为衡量友情或者爱情的标准。
5、总之一句话“对人对事都要以自己最真诚的心去对待”,“用心才是真理”。

这部电视剧给了我很深的体会,原来看看电视剧还是蛮有好处的。

2008-02-04

2002年到2007年,中国互联网市场经历了20世纪末期泡沫破裂以来的新一轮牛市。去年,阿里、巨人和金山的上市推动了互联网市场的繁荣走向了新的阶段,当然也为后市行情注入了活力。与中国股市不同的是,有超过2亿的网民支撑的互联网市场在可预见的几年内,将仍然保持牛市行情,甚至发展还有进一步加速的迹象。

 

2008年,在国家宏观调控政策的影响和互联网行业自身运行规律的共同作用下,中国互联网市场将会出现新一轮的波动和洗牌,一些成长性较强的网络公司可能会脱颖而出,成为今年的IT新秀。

 

依笔者多年的观察和总结,初步认为以下八个网站可能将在新的一年里崭露头角。

 

1、阿里妈妈(http://www.alimama.com

 

把广告位作为商品在c2c平台上叫卖是马云的独创,这充分显示了马总独特的眼光和非凡的智慧。虽然阿里妈妈仅仅推出几个月的时间,却在阿里巴巴、中国雅虎等大靠山的辅佐下迅速成长,再加上马云“病毒式”的营销策略,阿里妈妈目前的日IP已接近15万,而日PV更是越过了百万大关。随着中小企业网站和个人博客访问量的增加,以及交友、互动网站的崛起,阿里妈妈为这些网站提供了一个创造利润的平台,届时妈妈的商业价值也会进一步凸显。从实质上说,阿里妈妈开创了互联网盈利模式的一个时代。

 

2、校内网(http://www.xiaonei.com

 

随着大洋彼岸互动交流网站Facebook的兴起,国内与它有着类似功能的校内网日前被各界看好。并且有传闻说,陈一舟欲把校内网卖给facebook,而后者也有收购的意向。其实,在我看来,这只是陈一舟借facebook的风头自我自我炒作的一个骗局。陈一舟何许人也,千橡集团的总当家,涉足互联网多年,并且有着非凡的眼光和远大的抱负。2000年陈一时冲动,把chinaren卖给张朝阳之后,就后悔的死去活来。几年之后,他再次杀回校园,收购了校园网,可见陈不是为一时的小钱而在折腾,目前他不可能将潜心经营的校内网再次出售,他也不缺这么几个零花钱。倒是好像在酝酿着一个大的动作,从学校到白领,再到海内外,不出意外,2008年的校内网将会有一个质的突破。

 

3、红娘网(http://www.hongniang.com

 

“中国互联网第一股”网盛科技上市后刚满一年,其掌门人孙德良宣布隶属旗下非上市公司浙江都市网(zj.com)的“浙江红娘网” (love.zj.com)从中剥离,并在此基础上正式升级为“中国红娘”,另启用年初以24.8万元人民币价格收购的国际顶级域名 “hongniang.com”。此举可被视为,孙德良正式吹响进军全国婚恋市场的号角。网上婚恋市场在中国这样一个人口大国具有非常有想象力和诱惑力,根据艾瑞的预测,2008年,中国网络婚介交友的市场规模将达到6.53亿元人民币,而且网上交友的人数将以每年60%的速度递增。虽然国内已经有世纪佳缘、百合网等同类的竞争者,但依靠网盛科技背后强大的资本实力与运作经验,有理由相信孙德良能够把“中国红娘”经营的像中国化工网一样红火。中国管理层已经放出风声,两会之后即将退出创业板块,有着国内上市经验的网盛科技,很有可能在2008年将中国红娘推向A股市场。

 

4、普加网(www.pojaa.com

 

刚刚过去的一两年间,一个叫“垂直搜索”的词语不断充斥在各大媒体报端。随着互联网上信息量的急速增加,百度、谷歌等通用搜索引擎虽然用途广泛,但弊端也逐步凸现,越来越不能满足所有人的需求。有人说在google上求租一套房子,就如同在沙漠中找一粒特定的沙子。随着人们需求的多样化,搜索引擎逐步由“宽广”向“纵深”方向发展。于是垂直搜索和本地搜索一夜之间大批出现,随着市场的整合,眼前被各界看好的综合性垂直搜索的普加网发展势头迅猛,短短两个月的时间攻城略地,全国各地的代理商纷纷加盟,发展实力逐步壮大。据悉普加网日前即将有大批风险资金介入 ,2008年对普加来讲也将是波澜壮阔的一年,值得期待。

 

5、义乌全球网(www.yiwu2.com

 

义乌是联合国与世界银行公认的全球最大的小商品批发市场,义乌小商品指数是世界小商品价格走势的航标,它拥有饰品、工艺品、玩具、水晶、服装、皮具、袜业等十几大优势产业,市场优势非常明显。作为一个义乌人,中国“博客之父”方兴东回到了家乡,创办了义乌全球网,其目的是借义乌的优势打造全球第一的小商品B2B网上交易平台,

做成小商品领域的阿里巴巴。目前,义乌全球网的英文版已经上线,一个连接世界各地的小商品网上交易平台已经形成,最终经营状况和业绩究竟如何,还要看方兴东团队的日后运作。

 

6、百特网(www.handbest.com

 

看到这样一个名字,相信大部分网民还不认识这是一个什么样的网站。但是如果我告诉你它的母体是百度,你可能会大吃一惊。就在去年李彦红宣布百度要进军c2c领域之后,网上对百度c2c的域名猜测就没有中断过。最终网友们有了一个较为统一的认识,百度电子商务上线之后,其域名将定为handbest.com,并给他起了个名字,美名其曰:“百特网”,既与百度有着相同的“百”字,又有一个较为合理的英文解释,hand 在百度词典中有 “面交,,传递”之意,而 best 可以做名字“最佳,最好”“Baidu hand us the best to shopping.”的意思是“百度提供给我们一个最佳的购物平台”。对于这个无可挑剔的域名,网友已经诠释的非常清楚了,李彦红哪里还有不用的道理?且不论百度高层最终推出什么样的域名,handbest.com 是否合适,百度进军c2c这一事实就值得我们去期待了。上线之后的百度在电子商务领域,怎样与淘宝和拍拍竞争,李彦红怎样在“二马”(马云、马化腾)之间分得自己的一杯羹,同样值得大家期待。

7、儒豹网(www.roboo.com wap.roboo.com

 

中国目前的手机用户已经接近6亿,这个庞大的市场除了被中国移动和中国联通两家巨头垄断之外,外部势力基本无法靠近。但是这不等于在手机市场就没有机会,与互联网相连接,各种旋音酷图下载、手机游戏等业务随着手机软硬件的不断更新,将会迎来巨大的市场利润。儒豹手机搜索在韩松的带领下已经初见成效, 面对庞大的市场,我们期待并相信有着丰富经验、“更懂中国人”的韩博士能够在这一领域有所作为。

 

8、优酷网(www.youku.com

 

目前随着国家政策的对视频网站的整顿渐入佳境,各视频网站都在小心翼翼行事,以往在土豆网大肆播放的色情《金瓶梅》早已被管理员删除,就在视频网站纷纷叫嚣日子不好过的时候,优酷网老总古永锵却宣布,优酷在中国互联网视频行业创下日视频播放量过亿的佳绩。目前,在视频网站中,优酷的技术水平算的上一流的,它可以上传1G大小的视频文件,这是其他同类网站无法比拟的。在加上优酷网拥有一批忠实的观众和素质较高的拍客,怪不得古总敢狮子大开口:争取2008年优酷的广告收入要超亿元大关。视频网站在政策的调整下能否实现顺利的转型,优酷能否实现既定目标,同样值得我们期待。

2008-02-01

YouTube架构学习                  
                  
YouTube发展迅速,每天超过1亿的视频点击量,但只有很少人在维护站点和确保伸缩性。
平台
Apache
Python
Linux(SuSe)
MySQL
psyco,一个动态的Python到C的编译器
lighttpd代替Apache做视频查看
状态
支持每天超过1亿的视频点击量
成立于2005年2月
于2006年3月达到每天3千万的视频点击量
于2006年7月达到每天1亿的视频点击量
2个系统管理员,2个伸缩性软件架构师
2个软件开发工程师,2个网络工程师,1个DBA
处理飞速增长的流量

代码

  • while (true)
  • {
  •   identify_and_fix_bottlenecks();
  •   drink();
  •   sleep();
  •   notice_new_bottleneck();
  • }

每天运行该循环多次Web服务器
1,NetScaler用于负载均衡和静态内容缓存
2,使用mod_fast_cgi运行Apache
3,使用一个Python应用服务器来处理请求的路由
4,应用服务器与多个数据库和其他信息源交互来获取数据和格式化html页面
5,一般可以通过添加更多的机器来在Web层提高伸缩性
6,Python的Web层代码通常不是性能瓶颈,大部分时间阻塞在RPC
7,Python允许快速而灵活的开发和部署
8,通常每个页面服务少于100毫秒的时间
9,使用psyco(一个类似于JIT编译器的动态的Python到C的编译器)来优化内部循环
10,对于像加密等密集型CPU活动,使用C扩展
11,对于一些开销昂贵的块使用预先生成并缓存的html
12,数据库里使用行级缓存
13,缓存完整的Python对象
14,有些数据被计算出来并发送给各个程序,所以这些值缓存在本地内存中。这是个使用不当的策略。应用服务器里最快的缓存将预先计算的值发送给所有服务器也花不了多少时间。只需弄一个代理来监听更改,预计算,然后发送。
视频服务
1,花费包括带宽,硬件和能源消耗
2,每个视频由一个迷你集群来host,每个视频被超过一台机器持有
3,使用一个集群意味着:
-更多的硬盘来持有内容意味着更快的速度
-failover。如果一台机器出故障了,另外的机器可以继续服务
-在线备份
4,使用lighttpd作为Web服务器来提供视频服务:
-Apache开销太大
-使用epoll来等待多个fds
-从单进程配置转变为多进程配置来处理更多的连接
5,大部分流行的内容移到CDN:
-CDN在多个地方备份内容,这样内容离用户更近的机会就会更高
-CDN机器经常内存不足,因为内容太流行以致很少有内容进出内存的颠簸
6,不太流行的内容(每天1-20浏览次数)在许多colo站点使用YouTube服务器
-长尾效应。一个视频可以有多个播放,但是许多视频正在播放。随机硬盘块被访问
-在这种情况下缓存不会很好,所以花钱在更多的缓存上可能没太大意义。
-调节RAID控制并注意其他低级问题
-调节每台机器上的内存,不要太多也不要太少
视频服务关键点
1,保持简单和廉价
2,保持简单网络路径,在内容和用户间不要有太多设备
3,使用常用硬件,昂贵的硬件很难找到帮助文档
4,使用简单而常见的工具,使用构建在Linux里或之上的大部分工具
5,很好的处理随机查找(SATA,tweaks)
缩略图服务
1,做到高效令人惊奇的难
2,每个视频大概4张缩略图,所以缩略图比视频多很多
3,缩略图仅仅host在几个机器上
4,持有一些小东西所遇到的问题:
-OS级别的大量的硬盘查找和inode和页面缓存问题
-单目录文件限制,特别是Ext3,后来移到多分层的结构。内核2.6的最近改进可能让Ext3允许大目录,但在一个文件系统里存储大量文件不是个好主意
-每秒大量的请求,因为Web页面可能在页面上显示60个缩略图
-在这种高负载下Apache表现的非常糟糕
-在Apache前端使用squid,这种方式工作了一段时间,但是由于负载继续增加而以失败告终。它让每秒300个请求变为20个
-尝试使用lighttpd但是由于使用单线程它陷于困境。遇到多进程的问题,因为它们各自保持自己单独的缓存
-如此多的图片以致一台新机器只能接管24小时
-重启机器需要6-10小时来缓存
5,为了解决所有这些问题YouTube开始使用Google的BigTable,一个分布式数据存储:
-避免小文件问题,因为它将文件收集到一起
-快,错误容忍
-更低的延迟,因为它使用分布式多级缓存,该缓存与多个不同collocation站点工作
-更多信息参考Google ArchitectureGoogleTalk ArchitectureBigTable
数据库
1,早期
-使用MySQL来存储元数据,如用户,tags和描述
-使用一整个10硬盘的RAID 10来存储数据
-依赖于信用卡所以YouTube租用硬件
-YouTube经过一个常见的革命:单服务器,然后单master和多read slaves,然后数据库分区,然后sharding方式
-痛苦与备份延迟。master数据库是多线程的并且运行在一个大机器上所以它可以处理许多工作,slaves是单线程的并且通常运行在小一些的服务器上并且备份是异步的,所以slaves会远远落后于master
-更新引起缓存失效,硬盘的慢I/O导致慢备份
-使用备份架构需要花费大量的money来获得增加的写性能
-YouTube的一个解决方案是通过把数据分成两个集群来将传输分出优先次序:一个视频查看池和一个一般的集群
2,后期
-数据库分区
-分成shards,不同的用户指定到不同的shards
-扩散读写
-更好的缓存位置意味着更少的IO
-导致硬件减少30%
-备份延迟降低到0
-现在可以任意提升数据库的伸缩性
数据中心策略
1,依赖于信用卡,所以最初只能使用受管主机提供商
2,受管主机提供商不能提供伸缩性,不能控制硬件或使用良好的网络协议
3,YouTube改为使用colocation arrangement。现在YouTube可以自定义所有东西并且协定自己的契约
4,使用5到6个数据中心加CDN
5,视频来自任意的数据中心,不是最近的匹配或其他什么。如果一个视频足够流行则移到CDN
6,依赖于视频带宽而不是真正的延迟。可以来自任何colo
7,图片延迟很严重,特别是当一个页面有60张图片时
8,使用BigTable将图片备份到不同的数据中心,代码查看谁是最近的
学到的东西
1,Stall for time。创造性和风险性的技巧让你在短期内解决问题而同时你会发现长期的解决方案
2,Proioritize。找出你的服务中核心的东西并对你的资源分出优先级别
3,Pick your battles。别怕将你的核心服务分出去。YouTube使用CDN来分布它们最流行的内容。创建自己的网络将花费太多时间和太多money
4,Keep it simple!简单允许你更快的重新架构来回应问题
5,Shard。Sharding帮助隔离存储,CPU,内存和IO,不仅仅是获得更多的写性能
6,Constant iteration on bottlenecks:
-软件:DB,缓存
-OS:硬盘I/O
-硬件:内存,RAID
7,You succeed as a team。拥有一个跨越条律的了解整个系统并知道系统内部是什么样的团队,如安装打印机,安装机器,安装网络等等的人。With a good team all things are possible。


作者: shine    时间: 2007-11-29 16:50     标题: Twitter架构学习

Twitter是目前为止最大的Ruby on Rails应用,几个月间页面点击由0增长到几百万,现在的Twitter比今年月快了10000%
平台
Ruby on Rails
Erlang
MySQL
Mongrel
Munin
Nagios
Google Analytics
AWStats
Memcached
状态
成千上万的用户,真实数量保密
每秒钟600请求
每秒钟平均200-300个连接,峰值为800个连接
MySQL每秒钟处理2,400个请求
180个Rails实例,使用Mongrel作为Web服务器
1个MySQL服务器(one big 8 core box)和1个slave用于只读的统计和报告
30+进程用于处理其余的工作
8台Sun X4100s
Rails在200毫秒内处理一个请求
花费在数据库里的平均时间是50-100毫秒
超过16GB的memcached
架构
1,遇到非常常见的伸缩性问题
2,最初Twitter没有监听,没有图,没有统计,这让解决问题非常困难。后来添加了Munin和Nagios。在Solaris上使用工具有点困难,虽然有Google Analytics但是页面没有loading所以它没什么用
3,大量使用memcached作缓存
-例如,如果获得一个count非常慢,你可以将count在1毫秒内扔入memcached
-获取朋友的状态是很复杂的,这有安全等其他问题,所以朋友的状态更新后扔在缓存里而不是做一个查询。不会接触到数据库
-ActiveRecord对象很大所以没有被缓存。Twitter将critical的属性存储在一个哈希里并且当访问时迟加载
-90%的请求为API请求。所以在前端不做任何page和fragment缓存。页面非常时间敏感所以效率不高,但Twitter缓存了API请求
4,消息
-大量使用消息。生产者生产消息并放入队列,然后分发给消费者。Twitter主要的功能是作为不同形式(SMS,Web,IM等等)之间的消息桥
-使用DRb,这意味着分布式Ruby。有一个库允许你通过TCP/IP从远程Ruby对象发送和接收消息,但是它有点脆弱
-移到Rinda,它是使用tuplespace模型的一个分享队列,但是队列是持久的,当失败时消息会丢失
-尝试了Erlang
-移到Starling,用Ruby写的一个分布式队列
-分布式队列通过将它们写入硬盘用来挽救系统崩溃。其他大型网站也使用这种简单的方式
5,SMS通过使用第三方网关的API来处理,它非常昂贵
6,部署
-Twitter做了一次review并推出新的mongrel服务器,还没有优雅的方式
-如果mongrel服务器替换了则一个内部错误抛给用户
-所以的服务器一次杀死。没有使用rolling blackout方式因为消息队列状态保持在mongrel里,这将导致剩余的mongrel被堵塞
7,误用
-系统经常宕机,因为人们疯狂的添加任何人为朋友,24小时内有9000个朋友,这将让站点崩溃
-构建工具来检测这些问题,这样你可以找到何时何地发生这些错误
-无情的删除这些用户
8,分区
-将来计划分区,目前还没有。当前所做的改变已经足够
-分区的计划基于时间,而不是用户,因为大部分请求都是本地的
-由于memoization分区会很难。Twitter不能保证只读的操作真的为只读,有可能写入一个只读的slave,这很糟糕
9,Twitter的API流量是Twitter站点的10倍
-Twitter所做的最重要的事情就是API
-保持服务简单允许开发人员在Twitter的基础组织上构建一些比Twitter自己所想到的更好的主意。例如,Twitterrific是一个使用Twitter优美的方式
学到的东西
1,和社区交流。不要隐藏并尝试自己解决所有问题。如果你提问,有许多聪明的人士愿意帮忙
2,将你的伸缩计划当成一个商业计划,聚集一帮顾问来帮助你
3,自己构建它。Twitter花费大量时间来尝试其他人的似乎可以工作的解决方案,但是失败了。自己构建一些东西会更好,这样你至少可以控制它并且构建你需要的特性
4,在用户的限度上构建。人们可能尝试弄垮你的系统。提高理由的限度和检测机制来保护你的系统不被杀死
5,不要让数据库成为首要瓶颈,并不是所有东西都需要一个很大的join,缓存数据,考虑其他创造性的方式来获得结果。一个好例子在里Twitter, Rails, Hammers, and 11,000 Nails per Second谈到
6,让你的应用一开始就很容易分区。这样你会一直有一种方式来伸缩你的系统
7,认知你的系统是很慢的,马上添加报告来跟踪问题
8,优化数据库
-索引所有东西,Rails不会为你做这件事
-解释你的查询是怎样运行的,索引可能不是按你想像的去做
-大量的非常规化。例如,Twitter一起存储用户ID和朋友ID,这预防了大量的开销昂贵的join
9,缓存所有东西,个别的ActiveRecord对象目前没有被缓存。目前查找已经足够快
10,测试一切
-你想知道当你部署时一起工作正常
-Twitter现在有一个完整的test suite。所以当缓存失效时Twitter可以在go live之前找到问题
11,使用异常提示和异常日志来获得立即的错误提示,这样你可以发现正确的方式
12,不要做傻事
-伸缩改变了傻东西
-尝试一次加载3000个朋友到内存中可能带来服务器崩溃,但是当只有4个朋友时它工作的很好
13,大部分性能不是来自语言,而是来自应用设计
14,通过创建一个API来让你的站点开放服务。Twitter的API是它成功的一个大原因。它允许用户创建一个扩展和生态系统。你可以从不做你的用户可以做的工作,这样你就不会有创造性。所以开发你的系统并且让其他人将他们的应用与你的应用集成变容易


作者: shine    时间: 2007-11-29 16:51     标题: Google架构学习

Google是伸缩性的王者。Google一直的目标就是构建高性能高伸缩性的基础组织来支持它们的产品。
平台
Linux
大量语言:Python,Java,C++
状态
在2006年大约有450,000台廉价服务器
在2005年Google索引了80亿Web页面,现在没有人知道数目
目前在Google有超过200个GFS集群。一个集群可以有1000或者甚至5000台机器。成千上万的机器从运行着5000000000000000字节存储的GFS集群获取数据,集群总的读写吞吐量可以达到每秒40兆字节
目前在Google有6000个MapReduce程序,而且每个月都写成百个新程序
BigTable伸缩存储几十亿的URL,几百千千兆的卫星图片和几亿用户的参数选择
堆栈
Google形象化它们的基础组织为三层架构:
1,产品:搜索,广告,email,地图,视频,聊天,博客
2,分布式系统基础组织:GFS,MapReduce和BigTable
3,计算平台:一群不同的数据中心里的机器
4,确保公司里的人们部署起来开销很小
5,花费更多的钱在避免丢失日志数据的硬件上,其他类型的数据则花费较少
可信赖的存储机制GFS(Google File System)
1,可信赖的伸缩性存储是任何程序的核心需求。GFS就是Google的核心存储平台
2,Google File System - 大型分布式结构化日志文件系统,Google在里面扔了大量的数据
3,为什么构建GFS而不是利用已有的东西?因为可以自己控制一切并且这个平台与别的不一样,Google需要:
-跨数据中心的高可靠性
-成千上万的网络节点的伸缩性
-大读写带宽的需求
-支持大块的数据,可能为上千兆字节
-高效的跨节点操作分发来减少瓶颈
4,系统有Master和Chunk服务器
-Master服务器在不同的数据文件里保持元数据。数据以64MB为单位存储在文件系统中。客户端与Master服务器交流来在文件上做元数据操作并且找到包含用户需要数据的那些Chunk服务器
-Chunk服务器在硬盘上存储实际数据。每个Chunk服务器跨越3个不同的Chunk服务器备份以创建冗余来避免服务器崩溃。一旦被Master服务器指明,客户端程序就会直接从Chunk服务器读取文件
6,一个上线的新程序可以使用已有的GFS集群或者可以制作自己的GFS集群
7,关键点在于有足够的基础组织来让人们对自己的程序有所选择,GFS可以调整来适应个别程序的需求
使用MapReduce来处理数据
1,现在你已经有了一个很好的存储系统,你该怎样处理如此多的数据呢?比如你有许多TB的数据存储在1000台机器上。数据库不能伸缩或者伸缩到这种级别花费极大,这就是MapReduce出现的原因
2,MapReduce是一个处理和生成大量数据集的编程模型和相关实现。用户指定一个map方法来处理一个键/值对来生成一个中间的键/值对,还有一个reduce方法来合并所有关联到同样的中间键的中间值。许多真实世界的任务都可以使用这种模型来表现。以这种风格来写的程序会自动并行的在一个大量机器的集群里运行。运行时系统照顾输入数据划分、程序在机器集之间执行的调度、机器失败处理和必需的内部机器交流等细节。这允许程序员没有多少并行和分布式系统的经验就可以很容易使用一个大型分布式系统资源
3,为什么使用MapReduce?
-跨越大量机器分割任务的好方式
-处理机器失败
-可以与不同类型的程序工作,例如搜索和广告。几乎任何程序都有map和reduce类型的操作。你可以预先计算有用的数据、查询字数统计、对TB的数据排序等等
4,MapReduce系统有三种不同类型的服务器
-Master服务器分配用户任务到Map和Reduce服务器。它也跟踪任务的状态
-Map服务器接收用户输入并在其基础上处理map操作。结果写入中间文件
-Reduce服务器接收Map服务器产生的中间文件并在其基础上处理reduce操作
5,例如,你想在所有Web页面里的字数。你将存储在GFS里的所有页面抛入MapReduce。这将在成千上万台机器上同时进行并且所有的调整、工作调度、失败处理和数据传输将自动完成
-步骤类似于:GFS -> Map -> Shuffle -> Reduction -> Store Results back into GFS
-在MapReduce里一个map操作将一些数据映射到另一个中,产生一个键值对,在我们的例子里就是字和字数
-Shuffling操作聚集键类型
-Reduction操作计算所有键值对的综合并产生最终的结果
6,Google索引操作管道有大约20个不同的map和reduction。
7,程序可以非常小,如20到50行代码
8,一个问题是掉队者。掉队者是一个比其他程序慢的计算,它阻塞了其他程序。掉队者可能因为缓慢的IO或者临时的CPU不能使用而发生。解决方案是运行多个同样的计算并且当一个完成后杀死所有其他的
9,数据在Map和Reduce服务器之间传输时被压缩了。这可以节省带宽和I/O。
在BigTable里存储结构化数据
1,BigTable是一个大伸缩性、错误容忍、自管理的系统,它包含千千兆的内存和1000000000000000的存储。它可以每秒钟处理百万的读写
2,BigTable是一个构建于GFS之上的分布式哈希机制。它不是关系型数据库。它不支持join或者SQL类型查询
3,它提供查询机制来通过键访问结构化数据。GFS存储存储不透明的数据而许多程序需求有结构化数据
4,商业数据库不能达到这种级别的伸缩性并且不能在成千上万台机器上工作
5,通过控制它们自己的低级存储系统Google得到更多的控制权来改进它们的系统。例如,如果它们想让跨数据中心的操作更简单这个特性,它们可以内建它
6,系统运行时机器可以自由的增删而整个系统保持工作
7,每个数据条目存储在一个格子里,它可以通过一个行key和列key或者时间戳来访问
8,每一行存储在一个或多个tablet中。一个tablet是一个64KB块的数据序列并且格式为SSTable
9,BigTable有三种类型的服务器:
-Master服务器分配tablet服务器,它跟踪tablet在哪里并且如果需要则重新分配任务
-Tablet服务器为tablet处理读写请求。当tablet超过大小限制(通常是100MB-200MB)时它们拆开tablet。当一个Tablet服务器失败时,则100个Tablet服务器各自挑选一个新的tablet然后系统恢复。
-Lock服务器形成一个分布式锁服务。像打开一个tablet来写、Master调整和访问控制检查等都需要互斥
10,一个locality组可以用来在物理上将相关的数据存储在一起来得到更好的locality选择
11,tablet尽可能的缓存在RAM里
硬件
1,当你有很多机器时你怎样组织它们来使得使用和花费有效?
2,使用非常廉价的硬件
3,A 1,000-fold computer power increase can be had for a 33 timeslower cost if you you use a failure-prone infrastructure rather than aninfrastructure built on highly reliable components. You must buildreliability on top of unreliability for this strategy to work.
4,Linux,in-house rack design,PC主板,低端存储
5,Price per wattage on performance basis isn’t getting better. Have huge power and cooling issues
6,使用一些collocation和Google自己的数据中心
其他
1,迅速更改而不是等待QA
2,库是构建程序的卓越方式
3,一些程序作为服务提供
4,一个基础组织处理程序的版本,这样它们可以发布而不用害怕会破坏什么东西
Google将来的方向
1,支持地理位置分布的集群
2,为所有数据创建一个单独的全局名字空间。当前的数据由集群分离
3,更多和更好的自动化数据迁移和计算
4,解决当使用网络划分来做广阔区域的备份时的一致性问题(例如保持服务即使一个集群离线维护或由于一些损耗问题)
学到的东西
1,基础组织是有竞争性的优势。特别是对Google而言。Google可以很快很廉价的推出新服务,并且伸缩性其他人很难达到。许多公司采取完全不同的方式。许多公司认为基础组织开销太大。Google认为自己是一个系统工程公司,这是一个新的看待软件构建的方式
2,跨越多个数据中心仍然是一个未解决的问题。大部分网站都是一个或者最多两个数据中心。我们不得不承认怎样在一些数据中心之间完整的分布网站是很需要技巧的
3,如果你自己没有时间从零开始重新构建所有这些基础组织你可以看看Hadoop。Hadoop是这里很多同样的主意的一个开源实现
4,平台的一个优点是初级开发人员可以在平台的基础上快速并且放心的创建健全的程序。如果每个项目都需要发明同样的分布式基础组织的轮子,那么你将陷入困境因为知道怎样完成这项工作的人相对较少
5,协同工作不一直是掷骰子。通过让系统中的所有部分一起工作则一个部分的改进将帮助所有的部分。改进文件系统则每个人从中受益而且是透明的。如果每个项目使用不同的文件系统则在整个堆栈中享受不到持续增加的改进
6,构建自管理系统让你没必要让系统关机。这允许你更容易在服务器之间平衡资源、动态添加更大的容量、让机器离线和优雅的处理升级
7,创建可进化的基础组织,并行的执行消耗时间的操作并采取较好的方案
8,不要忽略学院。学院有许多没有转变为产品的好主意。Most of what Google has done has prior art, just not prior large scale deployment.
9,考虑压缩。当你有许多CPU而IO有限时压缩是一个好的选择。


作者: shine    时间: 2007-11-29 16:53     标题: Load Balancing

基于Shared Nothing Architecture做Load Balancing,遵循REST的无状态模型,不用考虑Sticky Sessions
一、DNS Load Balancing
DNS Load Balancing是最简单的方式,它将相同域名解析到不同IP
由于TTL和缓存时间,DNS不能实时更新clusters的更改
DNS方式很难自定义配置balance策略
DNS方式对traffic的balance不准确,对特定地域而言DNS会将特定域名一直路由到一个IP上
DNS方式很难搞redundancy和failover
二、用硬件做Load Balancing
Alteon AS range(application switches)
Citrix Netscalers
Cisco CSS range(content-switching servers)
Foundry Networks ServerIron
商用产品的缺点就是贵
相比DNS方式,用硬件产品做Load Balancing很好的支持failover
三、用软件做Load Balancing
Perlbal
Pound
Nginx
LVS
幸好有免费开源软件
四、Layer 4 Load Balancing
即在OSI7层模型的第4层搞Load Balancing,也就是在Transport这层
最简单的方式是使用Round robin算法来做Load Balancing,Load Balancer捕获请求并分发到backendserver列表中的第一个server,并标记该Server为last used server,下次请求时则分发到下一个backendserver
五、Layer 7 Load Balancing
在Application这层搞Load Balancing,将HTTP请求headers纳入balancing策略考虑
HTTP请求URL本身就是Layer 7 Load Balancing的例子
可以在real server cluster之上搞一个Hash table作为Layer 7 LoadBalancing,访问某一特定的URL时分发到一个特定的realserver,这样对该特定server可以每次都命中特定的缓存而不用在每个real server都建立同样的缓存
Layer 7 Load Balancing对HTTP请求的解析开销很大,所以它的scalability相对Layer 4 Load Balancing而言有限
六,Huge-Scale Balancing
超级大型的应用我们需要GSLB(global server load balancing)来将负载balance到不同的Data Center,将客户端路由到最近的DC以保持最少的latency
Akamai EdgePlatform提供整合的服务
七、Balancing非HTTP的Traffic
例如email,由于SMTP与HTTP很类似,我们可以使用HTTP Load Balancer来balance email traffic,只需创建一个新的service来监听25端口并连接到real backend servers

2008-01-31

【 前言 】

网 站在Web 2.0时代,时常面临迅速增加的访问量(这是好事情),但是我们的应用如何满足用户的访问需求,而且基本上我们看到的情况都是性能瓶颈都是在数据库上,这 个不怪数据库,毕竟要满足很大访问量确实对于任何一款数据库都是很大的压力,不论是商业数据库Oracle、MS SQL Server、DB2之类,还是开源的MySQL、PostgreSQL,都是很大的挑战,解决的方法很简单,就是把数据分散在不同的数据库上(可以是硬 件上的,也可以是逻辑上的),本文就是主要讨论如何数据库分散存储的的问题。
目前主要分布存储的方式都是按照一定的方式进行切分,主要是垂直切分(纵向)和水平切分(横向)两种方式,当然,也有两种结合的方式,达到更到的切分粒度。

1. 垂直切分(纵向)数据是数据库切分按照网站业务、产品进行切分,比如用户数据、博客文章数据、照片数据、标签数据、群组数据等等每个业务一个独立的数据库或者数据库服务器。
2. 水平切分(横向)数据是把所有数据当作一个大产品,但是把所有的平面数据按照某些Key(比如用户名)分散在不同数据库或者数据库服务器上,分散对数据访问的压力,这种方式也是本文主要要探讨的。

本 文主要针对的的 MySQL/PostgreSQL 类的开源数据库,同时平台是在 Linux/FreeBSD,使用 PHP/Perl/Ruby/Python 等脚本语言,搭配 Apache/Lighttpd 等Web服务器 的平台下面的Web应用,不讨论静态文件的存储,比如视频、图片、CSS、JS,那是另外一个话题。

说明:下面将会反复提到的一个名次“节点”(Node),指的是一个数据库节点,可能是物理的一台数据库服务器,也可能是一个数据库,一般情况是指一台数据库服务器,并且是具有 Master/Slave 结构的数据库服务器,我们查看一下图片,了解这样节点的架构:

(图1)

【 一、基于散列的分布方式 】

1. 散列方式介绍
基 于散列(Hash)的分布存储方式,主要是依赖主要Key和散列算法,比如以用户为主的应用主要的角色就是用户,那么做Key的就可以是用户ID或者是用 户名、邮件地址之类(该值必须在站点中随处传递),使用这个唯一值作为Key,通过对这个Key进行散列算法,把不同的用户数据分散在不同的数据库节点 (Node)上。

我们通过简单的实例来描述这个问题:比如有一个应用,Key是用户ID,拥有10个数据库节点,最简单的散列算法是我们 用户ID数模以我们所有节点数,余数就是对应的节点机器,算法:所在节点 = 用户ID % 总节点数,那么,用户ID为125的用户所在节点:125 % 10 = 5,那么应该在名字为5的节点上。同样的,可以构造更为强大合理的Hash算法来更均匀的分配用户到不同的节点上。

我们查看一下采用散列分布方式的数据结构图:

    (图2)

2. 散列分布存储方式的扩容

我们知道既然定义了一个散列算法,那么这些Key就会按部就班的分散到指定节点上,但是如果目前的所有节点不够满足要求怎么办?这就存在一个扩容的问题,扩容首当其冲的就是要修改散列算法,同时数据也要根据散列算法进修迁移或者修改。

(1) 迁移方式扩容:修 改散列算法以后,比如之前是10个节点,现在增加到20个节点,那么Hash算法就是[模20],相应的存在一个以前的节点被分配的数据会比较多,但是新 加入的节点数据少的不平衡的状态,那么可以考虑使用把以前数据中的数据按照Key使用新的Hash算法进行运算出新节点,把数据迁移到新节点,缺点但是这 个成本相应比较大,不稳定性增加;好处是数据比较均匀,并且能够充分利用新旧节点。

(2) 充分利用新节点:增 加新节点以后,Hash算法把新加入的数据全部Hash到新节点上,不再往旧节点上分配数据,这样不存在迁移数据的成本。优点是只需要修改Hash算法, 无须迁移数据就能够简单的增加节点,但是在查询数据的时候,必须使用考虑到旧Key使用旧Hash算法,新增加的Key使用新的Hash算法,不然无法查 找到数据所在节点。缺点很明显,一个是Hash算法复杂度增加,如果频繁的增加新节点,算法将非常复杂,无法维护,另外一个方面是旧节点无法充分利用资源 了,因为旧节点只是单纯的保留旧Key数据,当然了,这个也有合适的解决方案。

总结来说,散列方式分布数据,要新增节点比较困难和繁琐,但是也有很多适合的场合,特别适合能够预计到未来数据量大小的应用,但是普遍 Web2.0 网站都无法预计到数据量。

【 二、基于全局节点分配方式 】

1. 全局节点分配方式介绍

就是把所有Key信息与数据库节点之间的映射关系记录下来,保存到全局表中,当需要访问某个节点的时候,首先去全局表中查找,找到以后再定位到相应节点。全局表的存储方式一般两种:

(1) 采用节点数据库本身(MySQL/PostgreSQL)存储节点信息,能够远程访问,为了保证性能,同时配合使用 Heap(MEMORY) 内存表,或者是使用 Memcached 缓存方式来缓存,加速节点查找

(2) 采用 BDB(BerkeleyDB)、DBM/GDBM/NDBM 这类本地文件数据库,基于 key=>value 哈希数据库,查找性能比较高,同时结合 APC、Memcached 之类的缓存加速。

第 一种存储方式是容易查询(包括远程查询),缺点是性能不太好(这个是所有关系型数据库的通病);第二种方式的有点是本地查询速度很快(特别是hash型数 据库,时间复杂度是O(1),比较快),缺点是无法远程使用,并且无法在多台机器中间同步共享数据,存在数据一致的情况。

我们来描述实施 大概结构:假如我们有10个数据库节点,一个全局数据库用于存储Key到节点的映射信息,假设全局数据库有一个表叫做 AllNode ,包含两个字段,Key 和 NodeID,假设我们继续按照上面的案例,用户ID是Key,并且有一个用户ID为125的用户,它对应的节点,我们查询表获得:

  Key  NodeID
 13         2
 148  5
 22  9
 125  6

可以确认这个用户ID为125的用户,所在的节点是6,那么就可以迅速定位到该节点,进行数据的处理。

我们来查看一下分布存储结构图:

   (图3)

2. 全局节点分布方式的扩容

全局节点分配方式同样存在扩容的问题,不过它早就考虑到这个问题,并且这么设计就是为了便于扩容,主要的扩容方式是两种:

(1) 通过节点自然增加来分配Key到节点的映射扩容
这 种是最典型、最简单、最节约机器资源的扩容方式,大致就是按照每个节点分配指定的数据量,比如一个节点存储10万用户数据,第一个节点存储0-10w用户 数据,第二个节点存储10w-20w用户数据,第三个节点存储20w-30w用户信息,依此类推,用户增加到一定数据量就增加节点服务器,同时把Key分 配到新增加的节点上,映射关系记录到全局表中,这样可以无限的增加节点。存在的问题是,如果早期的节点用户访问频率比较低,而后期增加的节点用户访问频率 比较高,则存在节点服务器负载不均衡的现象,这个也是可以想方案解决的。

(2) 通过概率算法来映射Key到节点的的扩容
这种方式是在既然有的节点基础上,给每个节点设定一个被分配到Key的概率,然后分配Key的时候,按照每个节点被指定的概率进行分配,如果每个节点平均的数据容量超过了指定的百分比,比如50%,那么这时候就考虑增加新节点,那么新节点增加Key的概率要大于旧节点。
一般情况下,对于节点的被分配的概率也是记录在数据库中的,比如我们把所有的概率为100,共有10个节点,那么设定每个节点被分配的数据的概率为10,我们查看数据表结构:

NodeID Weight
1 10
2 10
3 10

现在新加入了一个 节点,新加入的节点,被分配Key的几率要大于旧节点,那么就必须对这个新加入的节点进行概率计算,计算公式:10х+у=100, у>х,得出:у{10…90},х{1…9},x是单个旧节点的概率,旧节点的每个节点的概率是一样的,y是新节点的概率,按照这个计算 公式,推算出新节点y的概率的范围,具体按照具体不同应用的概率公式进行计算。

 
【 三、存在的问题 】

现在我们来分析和解决一下我们上面两种分布存储方式的存在的问题,便于在实际考虑架构的时候能够避免或者是融合一些问题和缺点。

1. 散列和全局分配方式都存在问题

(1) 散列方式扩容不是很方便,必须修改散列算法,同时可能还需要对数据进行迁移,它的优点是从Key定位一个节点非常快,O(1)的时间复杂度,而且基本不需要查询数据库,节约响应时间。
(2) 全局分配方式存在的问题最明显的是单点故障,全局数据库down掉将影响所有应用。另外一个问题是查询量大,对每个Key节点的操作都必须经过全局数据库,压力很大,优点是扩容方便,增加节点简单。

2. 分布存储带来的搜索和统计问题

(1) 一般搜索或统计都是对所有数据进行处理,但因为拆分以后,数据分散在不同节点机器上,无法进行全局查找和统计。解决方案一是对主要的基础数据存储在全局表中,便于查找和统计,但这类数据不宜太多,部分核心数据。
(2) 采用站内搜索引擎来索引和记录全部数据,比如采用 Lucene 等开源索引系统进行所有数据的索引,便于搜索。 对于统计操作可以采用后台非实时统计,可采用遍历所有节点的方式,但效率低下。

3. 性能优化问题

(1) 散列算法,节点概率和分配等为了提高性能都可以使用编译语言开发,做成lib或者是所有php扩展形式。
(2) 对于采用 MySQL 的情况,可以采用自定义的数据库连接池,采用 Apache Module 形式加载,能够自由定制的采用各种连接方式。
(3) 对于全局数据或都频繁访问的数据,可以采用APC、Memcache、DBM、BDB、共享内存、文件系统等各种方式进行缓存,减少数据库的访问压力。
(4) 采用数据本身的强大处理机制,比如 MySQL5 的表分区或者是 MySQL5 的Cluster 。另外建议在实际架构中采用InnoDB表引擎作为主要存储引擎,MyISAM作为一些日志、统计数据等场合,不论在安全、可靠性、速度都有保障。

【 总结 】

本 文泛泛的分析了在网站项目(特别是Web2.0)中关于数据库分布存储的一些方式方法,基本上上面提到的两种分布方案笔者都经过实验或者是使用过类似成型 的项目,所以在实践性方面是有保障的,至于在具体实施过程中,可以按照具体的应用和项目进行选择性处理,这样,让你的网站速度飞快,用户体验一流。同时本 文有些概念和描述不一定准确,如果有不足之处,请谅解并且提出来,不胜感谢。另外,如果有更好的方案或者更完善的解决方式,非常希望能够分享一下,本文更 希望起到抛砖引玉的作用。(转载本文,敬请注明出处为:http://blog.csdn.net/heiyeshuwu,谢谢! :-)

一:硬架构

1:机房的选择:

在选择机房的时候,根据网站用户的地域分布,可以选择网通或电信机房,但更多时候,可能双线机房才是合适的。越大的城市,机房价格越贵,从成本的角 度看可以在一些中小城市托管服务器,比如说北京的公司可以考虑把服务器托管在天津,廊坊等地,不是特别远,但是价格会便宜很多。

2:带宽的大小:

通常老板花钱请我们架构网站的时候,会给我们提出一些目标,诸如网站每天要能承受100万PV的访问量等等。这时我们要预算一下大概需要多大的带宽,计算带宽大小主要涉及两个指标(峰值流量和页面大小),我们不妨在计算前先做出必要的假设:

第一:假设峰值流量是平均流量的5倍。
第二:假设每次访问平均的页面大小是100K字节左右。

如果100万PV的访问量在一天内平均分布的话,折合到每秒大约12次访问,如果按平均每次访问页面的大小是100K字节左右计算的话,这12次访 问总计大约就是1200K字节,字节的单位是Byte,而带宽的单位是bit,它们之间的关系是1Byte = 8bit,所以1200K Byte大致就相当于9600K bit,也就是9Mbps的样子,实际情况中,我们的网站必须能在峰值流量时保持正常访问,所以按照假设的峰值流量算,真实带宽的需求应该在45Mbps 左右。

当然,这个结论是建立在前面提到的两点假设的基础上,如果你的实际情况和这两点假设有出入,那么结果也会有差别。

3:服务器的划分:

先看我们都需要哪些服务器:图片服务器,页面服务器,数据库服务器,应用服务器,日志服务器等等。

对于访问量大点的网站而言,分离单独的图片服务器和页面服务器相当必要,我们可以用lighttpd来跑图片服务器,用apache来跑页面服务 器,当然也可以选择别的,甚至,我们可以扩展成很多台图片服务器和很多台页面服务器,并设置相关域名,如img.domain.com和 www.domain.com,页面里的图片路径都使用绝对路径,如<img src=”http://img.domain.com/abc.gif” />,然后设置DNS轮循,达到最初级的负载均衡。当然,服务器多了就不可避免的涉及一个同步的问题,这个可以使用rsync软件来搞定。

数据库服务器是重中之重,因为网站的瓶颈问题十有八九是出在数据库身上。现在一般的中小网站多使用MySQL数据库,不过它的集群功能似乎还没有达 到stable的阶段,所以这里不做评价。一般而言,使用MySQL数据库的时候,我们应该搞一个主从(一主多从)结构,主数据库服务器使用innodb 表结构,从数据服务器使用myisam表结构,充分发挥它们各自的优势,而且这样的主从结构分离了读写操作,降低了读操作的压力,甚至我们还可以设定一个 专门的从服务器做备份服务器,方便备份。不然如果你只有一台主服务器,在大数据量的情况下,mysqldump基本就没戏了,直接拷贝数据文件的话,还得 先停止数据库服务再拷贝,否则备份文件会出错。但对于很多网站而言,即使数据库服务仅停止了一秒也是不可接受的。如果你有了一台从数据库服务器,在备份数 据的时候,可以先停止服务(slave stop)再备份,再启动服务(slave start)后从服务器会自动从主服务器同步数据,一切都没有影响。但是主从结构也是有致命缺点的,那就是主从结构只是降低了读操作的压力,却不能降低写 操作的压力。为了适应更大的规模,可能只剩下最后这招了:横向/纵向分割数据库。所谓横向分割数据库,就是把不同的表保存到不同的数据库服务器上,比如说 用户表保存在A数据库服务器上,文章表保存在B数据库服务器上,当然这样的分割是有代价的,最基本的就是你没法进行LEFT JOIN之类的操作了。所谓纵向分割数据库,一般是指按照用户标识(user_id)等来划分数据存储的服务器,比如说:我们有5台数据库服务器,那么 “user_id % 5 + 1”等于1的就保存到1号服务器,等于2的就保存到2好服务器,以此类推,纵向分隔的原则有很多种,可以视情况选择。不过和横向分割数据库一样,纵向分割 数据库也是有代价的,最基本的就是我们在进行如COUNT, SUM等汇总操作的时候会麻烦很多。综上所述,数据库服务器的解决方案一般视情况往往是一个混合的方案,以其发挥各种方案的优势,有时候还需要借助 memcached之类的第三方软件,以便适应更大访问量的要求。

如果有专门的应用服务器来跑PHP脚本是最合适不过的了,那样我们的页面服务器只保存静态页面就可以了,可以给应用服务器设置一些诸如 app.domain.com之类的域名来和页面服务器加以区别。对于应用服务器,我还是更倾向于使用prefork模式的apache,配上必要的 xcache之类的PHP缓存软件,加载模块要越少越好,除了mod_rewrite等必要的模块,不必要的东西统统舍弃,尽量减少httpd进程的内存 消耗,而那些图片服务器,页面服务器等静态内容就可以使用lighttpd或者tux来搞,充分发挥各种服务器的特点。

如果条件允许,独立的日志服务器也是必要的,一般小网站的做法都是把页面服务器和日志服务器合二为一了,在凌晨访问量不大的时候cron运行前一天 的日志计算,不过如果你使用awstats之类的日志分析软件,对于百万级访问量而言,即使按天归档,也会消耗很多时间和服务器资源去计算,所以分离单独 的日志服务器还是有好处的,这样不会影响正式服务器的工作状态。

二:软架构

1:框架的选择:

现在的PHP框架有很多选择,比如:CakePHP,Symfony,Zend Framework等等,至于应该使用哪一个并没有唯一的答案,要根据Team里团队成员对各个框架的了解程度而定。很多时候,即使没有使用框架,一样能 写出好的程序来,比如Flickr据说就是用Pear+Smarty这样的类库写出来的,所以是否用框架,用什么框架,一般不是最重要的,重要的是我们 的编程思想里要有框架的意识。

2:逻辑的分层:

网站规模到了一定的程度之后,代码里各种逻辑纠缠在一起,会给维护和扩展带来巨大的障碍,这时我们的解决方式其实很简单,那就是重构,将逻辑进行分层。通常,自上而下可以分为表现层,应用层,领域层,持久层。

所谓表现层,并不仅仅就指模板,它的范围要更广一些,所有和表现相关的逻辑都应该被纳入表现层的范畴。比如说某处的字体要显示为红色,某处的开头要空两格,这些都属于表现层。很多时候,我们容易犯的错误就是把本属于表现层的逻辑放到了其他层面去完成,这里说一个很常见的例子:我们在列表页显示文章标 题的时候,都会设定一个最大字数,一旦标题长度超过了这个限制,就截断,并在后面显示“..”,这就是最典型的表现层逻辑,但是实际情况,有很多程序员都 是在非表现层代码里完成数据的获取和截断,然后赋值给表现层模板,这样的代码最直接的缺点就是同样一段数据,在这个页面我可能想显示前10个字,再另一个 页面我可能想显示前15个字,而一旦我们在程序里固化了这个字数,也就丧失了可移植性。正确的做法是应该做一个视图助手之类的程序来专门处理此类逻辑,比如说:Smarty里的truncate就属于这样的视图助手(不过它那个实现不适合中文)。

所谓应用层,它的主要作用是定义用户可以做什么,并把操作结果反馈给表现层。至于如何做,通常不是它的职责范围(而是领域层的职责范围),它会通过 委派把如何做的工作交给领域层去处理。在使用MVC架构的网站中,我们可以看到类似下面这样的URL: domain.com/articles/view/123,其内部编码实现,一般就是一个Articles控制器类,里面有一个view方法,这就是一 个典型的应用层操作,因为它定义了用户可以做一个查看的动作。在MVC架构中,有一个准则是这么说的:Rich Model Is Good。言外之意,就是Controller要保持“瘦”一些比较好,进而说明应用层要尽量简单,不要包括涉及领域内容的逻辑。

所谓领域层,最直接的解释就是包含领域逻辑的层。它是一个软件的灵魂所在。先来看看什么叫领域逻辑,简单的说,具有明确的领域概念的逻辑就是领域逻 辑,比如我们在ATM机上取钱,过程大致是这样的:插入银联卡,输入密码,输入取款金额,确定,拿钱,然后ATM吐出一个交易凭条。在这个过程中,银联卡 在ATM机器里完成钱从帐户上划拨的过程就是一个领域逻辑,因为取钱在银行中是一个明确的领域概念,而ATM机吐出一个交易凭条则不是领域逻辑,而仅是一 个应用逻辑,因为吐出交易凭条并不是银行中一个明确的领域概念,只是一种技术手段,对应的,我们取钱后不吐交易凭条,而发送一条提醒短信也是可能的,但并 不是一定如此,如果在实际情况中,我们要求取款后必须吐出交易凭条,也就是说吐出交易凭条已经和取款紧密结合,那么你也可以把吐出交易凭条看作是领域逻辑 的一部分,一切都以问题的具体情况而定。在Eric那本经典的领域驱动设计中,把领域层分为了五种基本元素:实体,值对象,服务,工厂,仓储。具体可以参 阅书中的介绍。领域层最常犯的错误就是把本应属于领域层的逻辑泄露到了其他层次,比如说在一个CMS系统,对热门文章的定义是这样的:每天被浏览的次数多 于1000次,被评论的次数多于100次,这样的文章就是热门文章。对于一个CMS来说,热门文章这个词无疑是一个重要的领域概念,那么我们如何实现这个 逻辑的设计的?你可能会给出类似下面的代码:“SELECT … FROM … WHERE 浏览 > 1000 AND 评论 > 100”,没错,这是最简单的实现方式,但是这里需要注意的是“每天被浏览的次数多于1000次,被评论的次数多于100次”这个重要的领域逻辑被隐藏到 了SQL语句中,SQL语句显然不属于领域层的范畴,也就是说,我们的领域逻辑泄露了。

所谓持久层,就是指把我们的领域模型保存到数据库中。因为我们的程序代码是面向对象风格的,而数据库一般是关系型的数据库,所以我们需要把领域模型 碾平,才能保存到数据库中,但是在PHP里,直到目前还没有非常好的ORM出现,所以这方面的解决方案不是特别多,参考Martin的企业应用架构模式一 书,大致可以使用的方法有行数据入口(Row Data Gateway)或者表数据入口(Table Data Gateway),或者把领域层和持久层合二为一变成活动记录(Active Record)的方式。

这篇文章虽然是将ror的,但是对于整个web开发还是非常有意义的,我也总结了下这篇文章,发现web程序还是很有共性的.

1:负载均衡器

大型网站肯定不是单台服务器的,为了做负载均衡,一般用F5,DNS轮询.我们公司所有的静态页面则采用NGINX做代理,后端挂SQUID服务器.NGINX的代理模块能够根据url地址HASH到某组服务器上,NGINX做负载均衡,SQUID组则考虑容灾问题.

2:WEB缓存服务器

原来我们公司使用文件cache,在新版本中使用squid作为页面缓存,squid组根据不同地区做IDC分布,形成了分布式的系统.从实际效果上看,文件cache更容易控制,程序使用比较灵活.考虑到不同的应用ncache可能逐步替代squid.

3:后端服务器

后端服务器就是应用服务器,主要通过F5挂在squid服务集群后面,处理的都是动态请求,每台机器每天50万的请求,cpu负载也不高,并发请求没有超过100,使用的是apache1.3,lamp的组合.

先写到这儿 干活了…………………………………………………….

JavaEye网站的RoR性能优化经验谈

JavaEye网站从2006年9月11日上线基于RoR的2.0版本开始,到现在已经运行了将近一年半了。在这一年半的时间里,JavaEye网站的每日PV从最开始的5万,缓慢增长到了现在的60万。随着网站负载的不断增加,我们也在不断尝试和调整网站的性能,积累了不少第一手RoR应用性能优化的实战经验。虽然我们并不是RoR性能优化的权威专家,我们所积累的经验也许并不是最优实践,但是作为国内最早涉足RoR商业运营的互联网网站之一,我们非常乐意分享和交流我们的实战经验,以帮助后来者节省必要的摸索时间。

RoR惊人的开发速度恐怕是每个互联网创业者都梦寐以求的,但是随着网站流量的不断增大,可能大多数采用RoR的网站或迟或早会遇到RoR的性能瓶颈,我的一个朋友capitian说过一句很有意思的话:“RoR应用做到后来,总有自己修改底层的冲动”。就我所了解和掌握的情况来看,很多RoR网站都过早的遇到了性能瓶颈,一个很普遍的现象就是:RoR应用的CPU负载要远远高于数据库的负载。这是一个有点违背常理的现象,因为我们知道,硬盘IO速度要比内存慢得多,所以一般Web应用的性能瓶颈往往会出现在数据库IO上,因此优化数据库访问,进行对象缓存是非常有效的性能优化手段。但是一旦应用服务器负载比数据库还高的话,单纯的对象缓存就无用武之地了。下面我们从几个方面分别谈一谈如何进行RoR的性能优化:

应用的部署

RoR应用的部署包括操作系统,Web服务器,应用服务器和数据库四个方面:

一、操作系统

1、发行版本

RoR适合于部署在Unix类操作系统上面,通常比较多的人使用RHEL/CentOS/Ubuntu,我们比较偏爱SuSE Linux,对于我们服务器使用的AMD Opteron x86_64的CPU来说,SLES要比RHEL有更多的优化。另外应该尽量使用64位版本操作系统,以充分发挥x86_64 CPU的性能,并且x86_64的Linux很多Kernel参数也大很多,代价就是需要更多的物理内存。

2、文件系统

Linux最常用的文件系统是ext3,但我们使用的是Reiserfs文件系统。Reiserfs在读写大量小文件的目录性能非常高,即使处理目录下面直接存放10万个文件,性能仍然不会下降。我们知道默认情况Rails会对每个浏览器会话在硬盘生成session文件,一个繁忙的网站,临时文件目录下面有上万乃至几万个session文件是很常见的现象。对于这种目录下面几万个小文件的存取,reiserfs要比ext3性能高一个数量级。如果希望对session文件有更好的存取性能,可以把临时目录链接到Linux的内存文件系统/dev/shm目录下面,这样实际上session文件的存取都是直接内存操作了,这种方式唯一的问题在于不能支持群集部署。如果你已经升级到了Rails2.0,可以采取把session保存到Cookie里面的方式,既可以避免服务器处理session的开销,而且还支持群集部署,是大规模网站部署的首选方式。

3、内核的网络参数调整

对于流量很大的网站来说,默认的Linux内核网络参数偏小,因此如果你的网站流量非常大,或者上传下载大文件比较多,可以针对性的调整内核网络参数,扩大内核的TCP接收数据和发送数据的Buffer缓冲区大小,比方说:

引用

net.core.rmem_default=262144
net.core.wmem_default=262144
net.core.rmem_max=262144
net.core.wmem_max=262144
net.ipv4.tcp_rmem=4096 65536 524288
net.ipv4.tcp_wmem=4096 65536 524288
参数具体调整,可以Google相关的Linux内核参数的文档,这里不展开详谈。

二、Web服务器

Web服务器首选Lighttpd,因为Lighttpd在和后端的应用服务器通讯方式上做了足够的优化:当POST大数据量的时候,Lighttpd在完整的接收客户端浏览器的数据之后,才会一次性发送给应用服务器;同样的,Lighttpd也是一次性把应用服务器处理的页面数据全部接收,不设置Buffer Size的限制。因此Lighttpd能够尽最大可能的减轻应用服务器的负担,减少应用服务器用于处理数据传输的延迟,更加有效的利用应用服务器资源。这方面的详细的论述请看:RoR部署方案深度剖析

关于Lighttpd的安装可以参考在Linux平台上安装和配置Ruby on Rails详解,这里仅谈Lighttpd的性能优化的几个要点:

1、网络IO调度方式
Linux Kernel 2.6支持sysepoll方式调度网络IO,能够处理极高的并发连接请求,Lighttpd可以通过配置文件打开sysepoll支持:

引用

server.event-handler = “linux-sysepoll”

2、网络IO传输方式
Linux Kernel 2.6支持sendfile方式传输数据,Lighttpd可以通过配置文件打开sendfile支持:

引用

server.network-backend = “linux-sendfile”

此外Lighttpd还支持应用服务器参与的文件下载控制X-sendfile,详细的论述请看:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

3、文件状态缓存
Lighttpd通过stat()调用获得文件被修改的信息,来决定当请求同一个静态文件资源的时候,是否需要再次读取硬盘文件。但是每次stat()调用也有一定的开销,Lighttpd支持通过Fam Server来减少stat调用。即每次当文件被修改之后,Kernel会发送一个消息通知Fam Server,而Lighttpd会通过进程间通讯连接Fam Server,可以知道文件是否被修改的信息,不必再每次调用stat()。

引用

server.stat-cache-engine = “fam”

4、限定POST Size
为了避免黑客恶意的攻击服务器,伪造超大Post数据包轰炸Web服务器和应用服务器,可以限制Request请求的大小,例如限制为10MB:

引用

server.max-request-size = 10240

5、日志文件
Lighttpd是单进程单线程的服务器,调度网络IO性能是极高的,但是在某些极端情况下,单进程服务器也有风险,即一旦被某操作系统调用挂住,整个服务器就没有办法响应请求了。比方说服务器其他进程导致的IO WAIT很高,操作系统的buffer又不够的时候,Lighttpd在大量的写access log就有被挂住的可能性。因此如果Lighttpd日志对你的参考价值不大,可以考虑关闭掉。像JavaEye网站每天Lighttpd产生430万条log,对硬盘IO也是一个不小的负担,既然已经开着Rais的production.log,那么Lighttpd的access log没什么参考价值了,那就关掉它。

Lighttpd的性能优化请看其作者写的文章:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformance

三、应用服务器

Ruby的应用服务器可以使用FastCGI,或者Mongrel,如果我们使用Lighttpd的话,FastCGI是最好的搭配。

1、FastCGI和Lighttpd的通讯方式

如果FastCGI和Lighttpd是在同一台服务器,那么建议采用Unix Socket通讯,这种通讯方式比TCP要快一些,FastCGI可以通过Lighttpd自带的spawn-fcgi命令行工具启动,创建socket文件,而Lighttpd监听socket文件。如果两者不在同一台服务器,需要群集部署,那就必须采用TCP Socket通讯,方式是一样的。

2、FastCGI进程应该开多少个合适?

Rails是单进程方式运行的,理论上来说,开几个FastCGI进程,就只能并发响应几个请求。对于繁忙的网站来说,峰值期间每秒有几十个动态请求是很正常的事情,但实际上FastCGI进程并不需要开那么多。这是因为前端的Web服务器在处理用户浏览器连接,发送Request请求需要相当长的时间,在FastCGI处理完请求释放该连接以后,Web服务器还需要相当长的时间才能把页面数据完整的发送到客户端浏览器。用户在点击一个链接以后,等待1-2秒,页面内容就显示出来,这对用户的感觉来说已经是非常快的了,而FastCGI用于处理该请求可能只需要0.1秒,那么一个FastCGI进程虽然并不能够真正的并发运行,但实际上的效果是他可以在1秒之内处理10个请求,让10个用户在同时访问网站的过程当中感觉不到明显的延迟。

因此FastCGI需要开多少个,取决于你的网站峰值期间每秒有多少个用户请求过来,而你的FastCGI又能够以多快的速度处理请求。比方说你的网站峰值期间每秒有50个动态请求,FastCGI在峰值期间处理每个请求需要0.2秒,那么实际上你只需要开10个FastCGI进程就足够了,为了应付突发的峰值请求,你可以在这个计算量上面增加一些余量,比方说15-20个进程,肯定是绰绰有余了。

关于FastCGI的性能优化,可以参考Lighttpd作者的文章,虽然他是针对PHP跑FastCGI写的,但对RoR也有参考价值:
http://trac.lighttpd.net/trac/wiki/Docs%3APerformanceFastCGI

四、数据库

JavaEye网站使用MySQL5.0.XX版本,数据库引擎是InnoDB。关于MySQL数据库的调优,推荐大家看MySQL Performance Blog,作者是一个MySQL性能调优方面的专家,并且提供MySQL咨询服务。他的博客上面有很丰富的关于MySQL调优的文章和演讲文稿,特别是关于InnoDB方面,非常深入。JavaEye的数据库调优就是根据他的InnoDB演讲文稿来调整的,一般说来,有几个需要调整的参数:

innodb_buffer_pool_size
这个参数很重要,越大越好,对于专用的数据库服务器一般建议开服务器内存的50%以上。

query_cache_size
查询缓存,对于查询的性能提高有很大帮助,但不宜开得过大,查询缓存的过期可能很频繁,过大查询缓存反而降低性能,增加服务器开销

innodb_flush_method = O_DIRECT
针对InnoDB的数据文件,关闭操作系统的文件缓冲,由于InnoDB自己有巨大的Buffer Pool,操作系统对文件的读写缓冲功能反而会降低MySQL的InnoDB的IO性能。

最后针对数据库的SQL优化来说有两点原则:

1、对数据库表要适当的创建索引
特别是出现在where查询条件当中字段,和关联查询当中的外键,要高度注意。

2、尽量避免大表的全表扫描和数据库的硬盘IO
查询比较慢的SQL要explain一下,看看是否发生了全表扫描,采取各种措施减少或者避免大表的全表扫描问题,例如拆分表等等。

最后针对MySQL数据库运行情况,我们可以用show status; 和 show innodb status\G 来监测。

Rails应用程序的优化

Rails应用程序优化包括ruby解析器的优化,缓存的使用,以及应用代码级别的优化。Stefans Kaes曾经在Railsconf 2006有一个Rails应用程序优化的演讲,他的演讲PPT是极好的Rails性能优化指南,可以在这里下载:http://www.javaeye.com/topic/24508。他还编写了一个用于Rails性能测试的软件包RailsBench,大家可以参考。由于Stefans Kaes的代码优化文档已经写的非常详细了,因此我就不在一一复述,只提出几点对性能影响比较大的方面:

一、ruby解析器的优化

ruby的解析器性能是很糟糕的,ruby早期的主要用途是取代perl写批量处理的脚本的,并不是为服务器应用编写的,因此在内存分配策略上非常不适合服务器应用。Stefans Kaes编写了一个ruby GC的补丁文件,在railsbench下载包里面提供了。虽然当前Railsbench提供的GC补丁只有针对ruby 1.8.4和1.8.5版本的,但是在ruby 18,6上面使用1.8.5的GC补丁也完全没有问题。GC补丁的作用主要是针对Rails应用开大了ruby的内存堆,可以有效提高内存堆的利用率,降低GC的频率。根据Stefans Kaes提供的测试数据,打补丁并且调整参数以后,GC的频率下降到只有原来的1/10还不到。降低GC频率尽管并不能够提高单个请求的执行速度,但是可以增加整体应用的负载能力。

我们在JavaEye的服务器上也使用了GC补丁,并且根据推荐参数进行了调整。在使用GC补丁之后,Web服务器的CPU负载下降了大概15%左右,效果非常显著。当然开大内存堆的代价就是ruby进程会多消耗内存,在我们的服务器上,ruby打补丁之后多消耗了50%左右的物理内存。

二、缓存的使用

1、对象缓存
JavaEye上面关于对象缓存的讨论很多,我们也提供了JavaEye这方面很多数据,因此不展开了。RoR可以使用两个对象缓存,一个是CachedModel,类似Hibernate,比较简单,对Model的CRUD操作自动进行缓存;另外一个是cache_fu,需要自己编码来添加对象缓存,但提供了更多高级机制,目前我们使用的是cache_fu。在使用对象缓存的情况下,应该把查询方法的:include去掉,避免关联查询无法利用缓存的现象。

2、查询缓存
对于统计类耗时查询,如果不要求实时性,那么可以使用memcache-client将查询结果缓存到memcached里面,例如博客排行榜之类。

3、页面局部缓存
对象缓存和查询缓存都是降低数据库访问负载的,但如果RoR的负载很高,那么只能依靠页面局部缓存了。传统的互联网web1.0网站很流行采用动态页面静态化技术来提高网站的负载,但是对于web2.0网站来说,每个页面都带有登陆用户的个人信息,页面的很多部分需要实时更新,例如投票,点击统计,digg,显示用户在线状态等等,动态页面静态化非常困难。当然如果你非要采用动态页面静态化,技术上也不是实现不了,可以通过AJAX请求来处理静态页面的动态部分,但是这种解决方案的开发成本过高,而且性能未必会有明显的改善,大家看看新浪和搜狐博客就知道这种技术被应用的有多糟糕了。

web2.0网站比较常用使用页面局部缓存,一种情况是页面不需要实时更新的,那么只需要设置一个合理的过期时间就行了,这种情况我们目前使用的比较多;另外一种情况是虽然不需要实时更新,但是会在用户执行某些操作后需要缓存过期,比方说博客个人主页的很多页面,这种情况下缓存过期策略会比较复杂,考虑到合理的开发成本,我们尚未对这样的页面使用局部缓存。

此外,Rails的页面局部缓存有一个缺点,就是和页面查询结果对应的Action当中的查询语句要放在View里面,否则每次action里面的查询还是会被执行,但是这样做会破坏程序代码良好的MVC结构。这种情况下,也可以采用另外一个Cache插件: better rails caching,在缓存页面的同时可以缓存Action当中的查询语句。

三、应用代码的优化

Stefans Kaes的文档里面对应用代码的优化进行了非常详细的介绍,因此我这里只提两个比较重要的注意事项:

1、link_to
Rails的link_to是非常慢的,它的代码实现过于复杂,特别是Rails1.2引入了REST以后,大量的命名路由被使用,这些命名路由还需要通过一次method_missing,那就更加缓慢了。因此对于被频繁使用的内部URL地址,一定要自己用字符串拼接方式改写,可以很明显提高View的render性能。此外类似的helper还有很多,例如button_tag,image_tag啥啥的,如非必要,尽量不用他的helper

2、正则表达式
ruby的正则表达式也是极慢,例如auto_fix这个helper的正则表达式就比较复杂,造成的结果就是一但大量使用auto_fix,View的render就明显变慢,类似依赖正则表达式进行字符串过滤的helper有很多,如果需要频繁大量使用,请先自行做benchmark。

Rails应用程序的内存泄漏问题和解决

内存泄漏是服务器端程序经常遇到的,有时候内存泄漏问题会让人很头疼,总体来说,Rails的内存泄漏问题比Java要少得多,这是因为Java内存泄漏最常见的三种情况在Rails当中不存在:

1、HttpSession导致的内存泄漏
Java程序员喜欢往session里面丢很多东西,最糟糕的是竟然有很多框架软件也肆无忌惮往session里面丢状态数据,但Rails的session是不放在内存里面的,所以无此烦恼。

2、数据库连接释放不彻底
Java的数据库连接池释放不彻底,以及查询游标释放不彻底,都必然导致内存泄漏。Rails没有数据库连接池,而是每个进程持有一个长连接,因此不存在这个问题,而且由于持有长连接,也不存在Java里面的OpenSessionInView的烦恼。

3、用静态变量持有全局共享数据
Java程序员很喜欢通过静态全局变量来持有共享数据,但共享数据忘记清理的话,也很容易导致内存泄漏,Ruby是SNA架构,多进程服务器模式,进程间无法共享数据,反而避免了全局共享数据带来的麻烦。

但是Rails应用有一种情况:在Ruby代码中调用C写的第三方ruby类库的时候,很容易导致内存泄漏,但这种内存泄漏反而在Java中极其罕见。Ruby本身有GC来管理内存堆,但是代码一旦调用C写的第三方ruby类库,内存堆的分配权就掌握在第三方C库的实现上面了,如果这个C库的代码质量不够好,内存泄漏就不可避免。由于ruby本身性能很差,因此计算量大的功能往往依赖底层的C库来实现,这下内存泄漏的潘多拉魔盒就打开了!而Java性能比较好,功能都是纯Java编写,基本上看不到需要依赖第三方C库的情况,因此比较安全。

JavaEye也面临着内存泄漏的困扰,这方面困扰主要来自于Rmagic。Rmagick调用ImageMagick的C库来完成图片的操作,从我们的监测来看,RMagick大多数情况下会缓慢的泄漏内存,在某些特定的图片操作上会急剧的泄漏内存。解决办法就是用mini_magick替代Rmagick,mini_magick是直接调用ImageMagick的mogrify命令,另起一个进程来操作图片,操作完进程就结束了,绝无后患,由于Linux的fork进程开销不大,因此也不必担心性能问题。

此外,调用第三方C库的ruby代码编写都需要高度小心,比方说JavaEye使用ferret实现全文检索,根据应用的需要调用ferret的API来编写自己的analyzer,其中在实现token_stream方法上面使用了XXXAnalyzer.new和XXXToken.new,XXXFilter.new,结果内存急剧泄漏,经过检查发现是Analyzer对象不能被反复创建,改成创建后缓存该对象就好了,但是Filter和Token对象却必须每次创建,此外ferret的PerAnalyzerFilter也有内存泄漏问题。由于类库是用C编写的,单纯看API文档或者看源代码片断一般无法判断出里面的内存泄漏陷阱的。

当遇到了难以解决和定位的内存泄漏问题,Ruby也有类似Java的内存Profiler工具:

1、Memory Profiler
一个纯ruby编写的内存探测器,原理很简单,就是用ruby的对象引用计数器ObjectSpace.each_object去遍历内存堆中的每个ruby对象,进行统计和分析。用起来很简单,非常适合于开发环境下侦测内存泄漏问题,但不能用在生产环境下,极度影响Rails性能。

2、Bleak_house
Bleak_house给Ruby解析器打了补丁,插入相关的指令,可以从底层探测整个ruby内存堆中对象的情况,然后你可以定期dump出来完整的内存堆里面的所有对象,再用bleak工具去分析dump文件,他比上面的工具分析的信息要全面,可以在测试环境和预发布环境下使用,但在生产环境下,也会对应用的性能产生很大的影响,要慎用。

JavaEye网站在RoR性能方面的经验就全部分享给大家了,也希望做RoR的朋友都拿出来自己的经验和大家分享,共同学习和促进RoR的应用和普及。

一、LiveJournal发展历程

LiveJournal是99年始于校园中的项目,几个人出于爱好做了这样一个应用,以实现以下功能:

  • 博客,论坛
  • 社会性网络,找到朋友
  • 聚合,把朋友的文章聚合在一起

LiveJournal采用了大量的开源软件,甚至它本身也是一个开源软件。在上线后,LiveJournal实现了非常快速的增长:

  • 2004年4月份:280万注册用户。
  • 2005年4月份:680万注册用户。
  • 2005年8月份:790万注册用户。
  • 达到了每秒钟上千次的页面请求及处理。
  • 使用了大量MySQL服务器。
  • 使用了大量通用组件。

二、LiveJournal架构现状概况

livejournal_backend.png

三、从LiveJournal发展中学习

LiveJournal从1台服务器发展到100台服务器,这其中经历了无数的伤痛,但同时也摸索出了解决这些问题的方法,通过对LiveJournal的学习,可以让我们避免LJ曾经犯过的错误,并且从一开始就对系统进行良好的设计,以避免后期的痛苦。

下面我们一步一步看LJ发展的脚步。

1、一台服务器

一台别人捐助的服务器,LJ最初就跑在上面,就像Google开始时候用的破服务器一样,值得我们尊敬。这个阶段,LJ的人以惊人的速度熟悉的Unix的操作管理,服务器性能出现过问题,不过还好,可以通过一些小修小改应付过去。在这个阶段里LJ把CGI升级到了FastCGI。

最终问题出现了,网站越来越慢,已经无法通过优过化来解决的地步,需要更多的服务器,这时LJ开始提供付费服务,可能是想通过这些钱来购买新的服务器,以解决当时的困境。
毫无疑问,当时LJ存在巨大的单点问题,所有的东西都在那台服务器的铁皮盒子里装着。

LJ-backend-7.png

2、两台服务器

用付费服务赚来的钱LJ买了两台服务器:一台叫做Kenny的Dell 6U机器用于提供Web服务,一台叫做Cartman的Dell 6U服务器用于提供数据库服务。

LJ-backend-8.png

LJ有了更大的磁盘,更多的计算资源。但同时网络结构还是非常简单,每台机器两块网卡,Cartman通过内网为Kenny提供MySQL数据库服务。

暂时解决了负载的问题,新的问题又出现了:

  • 原来的一个单点变成了两个单点。
  • 没有冷备份或热备份。
  • 网站速度慢的问题又开始出现了,没办法,增长太快了。
  • Web服务器上CPU达到上限,需要更多的Web服务器。

3、四台服务器

又买了两台,Kyle和Stan,这次都是1U的,都用于提供Web服务。目前LJ一共有3台Web服务器和一台数据库服务器。这时需要在3台Web服务器上进行负载均横。

LJ-backend-9.png

LJ把Kenny用于外部的网关,使用mod_backhand进行负载均横。

然后问题又出现了:

  • 单点故障。数据库和用于做网关的Web服务器都是单点,一旦任何一台机器出现问题将导致所有服务不可用。虽然用于做网关的Web服务器可以通过保持心跳同步迅速切换,但还是无法解决数据库的单点,LJ当时也没做这个。
  • 网站又变慢了,这次是因为IO和数据库的问题,问题是怎么往应用里面添加数据库呢?

4、五台服务器

又买了一台数据库服务器。在两台数据库服务器上使用了数据库同步(Mysql支持的Master-Slave模式),写操作全部针对主数据库(通过Binlog,主服务器上的写操作可以迅速同步到从服务器上),读操作在两个数据库上同时进行(也算是负载均横的一种吧)。

LJ-backend-10.png

实现同步时要注意几个事项:

  • 读操作数据库选择算法处理,要选一个当前负载轻一点的数据库。
  • 在从数据库服务器上只能进行读操作
  • 准备好应对同步过程中的延迟,处理不好可能会导致数据库同步的中断。只需要对写操作进行判断即可,读操作不存在同步问题。

5、更多服务器

有钱了,当然要多买些服务器。部署后快了没多久,又开始慢了。这次有更多的Web服务器,更多的数据库服务器,存在 IO与CPU争用。于是采用了BIG-IP作为负载均衡解决方案。

LJ-backend-11.png

6、现在我们在哪里:

LJ-backend-1.png

现在服务器基本上够了,但性能还是有问题,原因出在架构上。

数据库的架构是最大的问题。由于增加的数据库都是以Slave模式添加到应用内,这样唯一的好处就是将读操作分布到了多台机器,但这样带来的后果就是写操作被大量分发,每台机器都要执行,服务器越多,浪费就越大,随着写操作的增加,用于服务读操作的资源越来越少。

LJ-backend-2.png

由一台分布到两台

LJ-backend-3.png

最终效果

现在我们发现,我们并不需要把这些数据在如此多的服务器上都保留一份。服务器上已经做了RAID,数据库也进行了备份,这么多的备份完全是对资源的浪费,属于冗余极端过度。那为什么不把数据分布存储呢?

问题发现了,开始考虑如何解决。现在要做的就是把不同用户的数据分布到不同的服务器上进行存储,以实现数据的分布式存储,让每台机器只为相对固定的用户服务,以实现平行的架构和良好的可扩展性。

为了实现用户分组,我们需要为每一个用户分配一个组标记,用于标记此用户的数据存放在哪一组数据库服务器中。每组数据库由一个master及几个slave组成,并且slave的数量在2-3台,以实现系统资源的最合理分配,既保证数据读操作分布,又避免数据过度冗余以及同步操作对系统资源的过度消耗。

LJ-backend-4.png

由一台(一组)中心服务器提供用户分组控制。所有用户的分组信息都存储在这台机器上,所有针对用户的操作需要先查询这台机器得到用户的组号,然后再到相应的数据库组中获取数据。

这样的用户架构与目前LJ的架构已经很相像了。

在具体的实现时需要注意几个问题:

  • 在数据库组内不要使用自增ID,以便于以后在数据库组之间迁移用户,以实现更合理的I/O,磁盘空间及负载分布。
  • 将userid,postid存储在全局服务器上,可以使用自增,数据库组中的相应值必须以全局服务器上的值为准。全局服务器上使用事务型数据库InnoDB。
  • 在数据库组之间迁移用户时要万分小心,当迁移时用户不能有写操作。

7、现在我们在哪里

LJ-backend-5.png

问题:

  • 一个全局主服务器,挂掉的话所有用户注册及写操作就挂掉。
  • 每个数据库组一个主服务器,挂掉的话这组用户的写操作就挂掉。
  • 数据库组从服务器挂掉的话会导致其它服务器负载过大。

对于Master-Slave模式的单点问题,LJ采取了Master-Master模式来解决。所谓Master-Master实际上是人工实现的,并不是由MySQL直接提供的,实际上也就是两台机器同时是Master,也同时是Slave,互相同步。

Master-Master实现时需要注意:

  • 一个Master出错后恢复同步,最好由服务器自动完成。
  • 数字分配,由于同时在两台机器上写,有些ID可能会冲突。

解决方案:

  • 奇偶数分配ID,一台机器上写奇数,一台机器上写偶数
  • 通过全局服务器进行分配(LJ采用的做法)。

Master-Master模式还有一种用法,这种方法与前一种相比,仍然保持两台机器的同步,但只有一台机器提供服务(读和写),在每天晚上的时候进行轮换,或者出现问题的时候进行切换。

8、现在我们在哪里

LJ-backend-6.png

现在插播一条广告,MyISAM VS InnoDB。

使用InnoDB:

  • 支持事务
  • 需要做更多的配置,不过值得,可以更安全的存储数据,以及得到更快的速度。

使用MyISAM:

  • 记录日志(LJ用它来记网络访问日志)
  • 存储只读静态数据,足够快。
  • 并发性很差,无法同时读写数据(添加数据可以)
  • MySQL非正常关闭或死机时会导致索引错误,需要使用myisamchk修复,而且当访问量大时出现非常频繁。

9、缓存

去年我写过一篇文章介绍memcached,它就是由LJ的团队开发的一款缓存工具,以key-value的方式将数据存储到分布的内存中。LJ缓存的数据:

  • 12台独立服务器(不是捐赠的)
  • 28个实例
  • 30GB总容量
  • 90-93%的命中率(用过squid的人可能知道,squid内存加磁盘的命中率大概在70-80%)

如何建立缓存策略?

想缓存所有的东西?那是不可能的,我们只需要缓存已经或者可能导致系统瓶颈的地方,最大程度的提交系统运行效率。通过对MySQL的日志的分析我们可以找到缓存的对象。

缓存的缺点?

  • 没有完美的事物,缓存也有缺点:
  • 增大开发量,需要针对缓存处理编写特殊的代码。
  • 管理难度增加,需要更多人参与系统维护。
  • 当然大内存也需要钱。

10、Web访问负载均衡

在数据包级别使用BIG-IP,但BIG-IP并不知道我们内部的处理机制,无法判断由哪台服务器对这些请求进行处理。反向代理并不能很好的起到作用,不是已经够快了,就是达不到我们想要的效果。

所以,LJ又开发了Perlbal。特点:

  • 快,小,可管理的http web 服务器/代理
  • 可以在内部进行转发
  • 使用Perl开发
  • 单线程,异步,基于事件,使用epoll , kqueue
  • 支持Console管理与http远程管理,支持动态配置加载
  • 多种模式:web服务器,反向代理,插件
  • 支持插件:GIF/PNG互换?

11、MogileFS

LJ使用开源的MogileFS作为分布式文件存储系统。MogileFS使用非常简单,它的主要设计思想是:

  • 文件属于类(类是最小的复制单位)
  • 跟踪文件存储位置
  • 在不同主机上存储
  • 使用MySQL集群统一存储分布信息
  • 大容易廉价磁盘

到目前为止就这么多了,更多文档可以在http://www.danga.com/words/找到。Danga.comLiveJournal.com的同学们拿这个文档参加了两次MySQL Con,两次OS Con,以及众多的其它会议,无私的把他们的经验分享出来,值得我们学习。在web2.0时代快速开发得到大家越来越多的重视,但良好的设计仍是每一个应用的基础,希望web2.0们在成长为Top500网站的路上,不要因为架构阻碍了网站的发展。

参考资料:http://www.danga.com/words/2005_oscon/oscon-2005.pdf

 

高并发高流量网站架构

摘 要

Web2.0的兴起,掀起了互联网新一轮的网络创业大潮。以用户为导向的新网站建设概念,细分了网站功能和用户群,不仅成功的造就了一大批新生的网站,也极大的方便了上网的人们。但Web2.0以用户为导向的理念,使得新生的网站有了新的特点——高并发,高流量,数据量大,逻辑复杂等,对网站建设也提出了新的要求。

本文围绕高并发高流量的网站架构设计问题,主要研究讨论了以下内容:

首先在整个网络的高度讨论了使用镜像网站,CDN内容分发网络等技术对负载均衡带来的便利及各自的优缺点比较。然后在局域网层次对第四层交换技术,包括硬件解决方案F5和软件解决方案LVS,进行了简单的讨论。接下来在单服务器层次,本文着重讨论了单台服务器的Socket优化,硬盘级缓存技术,内存级缓存技术,CPUIO平衡技术(即以运算为主的程序与以数据读写为主的程序搭配部署),读写分离技术等。在应用层,本文介绍了一些大型网站常用的技术,以及选择使用该技术的理由。最后,在架构的高度讨论了网站扩容,容错等问题。

本文以理论与实践相结合的形式,结合作者实际工作中得到的经验,具有较广泛的适用性。

关键词:高并发 高流量 网站架构 网站扩容 容错

Abstract

 

With web2.0 startingraised the Internet new turn of network to start undertaking the flood tide. To be user-oriented concept of the new websites, not only successfully created a large number of new sites, but also greatly facilitate the development of the Internet people. The Web2.0 at the same time take the user as the guidance idea, enabled the newborn website to have the new characteristic - high concurrency, high page views, big data quantity, and complex logic , etc. , also set the new request to the website construction. This article revolves the high concurrent high current capacity the website overhead construction design question, the main research discussed these content: First discussed the useage of mirror sites in the entire network, CDN content distribution network, the convenience and respective good and bad points comparison which brings to the load balancing. Then in the local area network, the fourth level exchange technology, including hardware solution F5 and software solution LVS, has been carried on with a simple discussion. Received in the single server level, this article emphatically discussed the single server socket optimization, the hard disk cache technology, the memory level buffer technology, CPU and the IO balance technology , the read-write separation technology and so on. In the application level, this article introduced some large-scale website commonly used technologies, as well as the reason of choice of these technicals. Finally, highly discussed the website in the overhead construction to expand accommodates, fault-tolerant. This article form which unifies by the theory and the practice, experience which in the author practical work obtains, has amore widespread serviceability.

 

KEY WORDS: high page view, high concurrency, architecture of website site, expansion

目 录

1 引言 9

1.1 互联网的发展 9
1.2 互联网网站建设的新趋势 9
1.3 新浪播客的简介 11

2 网络层架构 12

2.1 镜像网站技术 12