`
z_jianxin
  • 浏览: 2059 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

谈谈大型网站架构之系列

 
阅读更多
纵观历史演变(我也要谈谈大型网站架构之系列(1)——上)


我们知道一个网站都是随着业务的发展,逐渐演变成几万服务器,几亿用户数的大型网站,经历了若干年,甚至上十年的,发展成为大型网站,然而真正亲身经历这个发展过程的人已经不多了,这种人也是拿着公司股票,赶都赶不走的人,所以正因为很多人没有亲身经历过,所以对架构的演变没有深刻的了解,包括我自己在内,不过没吃过猪肉,也看过猪跑。。。


一:第一代架构

  这年头创业大多都是从穷屌丝开始的,奔着 “快好省”的原则建立网站,将“应用程序”,“文件”,“数据库”通通放在一台服务器上,匆匆的就走上了网站架构之路。我们知道业务的发展对技术会有更高的要求,业务的创新会触动技术的创新,当业务逐渐发展起来的时候,最容易出现的问题就是”存储空间“和通用的”性能低下“,这个时候就需要做到”应用程序“和”数据“的分离。


二:第二代架构

   随着业务规模的扩大,需要将”应用程序“,”文件“,”数据库“进行分离,用更强大的cpu处理服务器来承载应用程序,记得在上一家用的cpu就是16核,”文件“的话则需要更大的磁盘空间的服务器,”数据库“的话需要更大的磁盘和超大内存的服务器,我们知道sqlserver还是很吃内存的,记得用过最大的是120g的内存。


    随着业务规模不断扩大,访问人数逐渐增多,我们也开心了,起码挣到钱了,然后我们会发现数据库开始出现瓶颈了,大量的读写操作让数据库出现访问延迟以及死锁现象的发生,继而影响用户体验。


三:第三代架构

     既然大量的读写操作让数据库出现瓶颈了,这个时候就要从两个方面优化读写操作

1. 读操作

 

    我们知道任何东西都是遵守二八原则,也就是网站上经常访问的东西也就那么多,对于这种命中率非常高的东西就需要用缓存来处理,减少读的次数,在携程里面的memcache就做了“数据热度”的操作,对于热度低的数据会自动从缓存中踢掉。



2. 写操作

    这个有分及时写和非及时写,对于非及时写的数据,我们可以采用 “消息队列”来对写操作节流,从而缓解数据库写入时的瞬时压力。这时候数据库的读写操作得到了很大的缓解,随着业务规模的继续扩大,用户人数的再次暴增,我们会发现”应用程序服务器“的CPU经常高烧不退,被玩爆的次数越来越多。



四:第四代架构

      既然被爆表了,这时候必须再拉一个应用程序服务器来分摊前端访问带来的压力,做了集群之后,需要再配一台”负载均衡调度器“,不过屌丝公司用的比较多的还是nginx,高大上的公司都是动辄几十万的硬件负载均衡,比如携程用的就是A10,还有市场上几十万F5等等产品。



纵观历史演变(我也要谈谈大型网站架构之系列(2)——下)


  这篇文章本来准备前几天就得写的,谁也没想到这段时间公司的RC太多了,含酸苦逼的加班,加班。。。所以在大一点的公司上班,写代码的责任心一定要强,或许就因为你的一些小bug,给公司带来不少损失。。。这在以前公司真的没多大体会的。

  好了,继续说说架构的演变,从第四代架构中可以看到,我们通过做应用程序层的负载均衡可以比较完美的解决了在整个架构中让应用程序层不再成为瓶颈,通过A10,我们可以让用户的访问请求分发到集群中的任何一台服务器上,当访问量继续膨胀的时候,我们就可以继续在集群中增加服务器来解决负载的压力,达到系统的可伸缩性,现在我们的业务规模像滚雪球一样越来越大,用户数暴增。。。这时候我们缓存中的数据也越来越多,虽然我们用了缓存,但是大量的“缓存过期重新读取”和“缓存不命中",导致数据库压力非常大,这时候数据库的压力成为了我们架构中的瓶颈。



五: 第五代架构

   既然数据库成为了我们第四代架构的瓶颈,这时候必须解决数据库的压力问题,最常见的做法也就是“读写分离”,将写和读的库进行拆分来缓解数据库的压力。

     现在我们做了多个库,写的时候进主库,然后数据库分发到从库中,然后应用程序在从库中读取,这里为了让数据库对应用程序更加透明,我们通常加一个“数据访问层”,在携程里面就是在企业库上进行了一层封装以及安全性采用了all in one 模式,可以看到第五代架构对数据库的压力有了很大的缓解。

   经过几个月业务喷井式的发展之后,我们会发现数据库检索越来越慢,单表数据量已经差不多爆炸了。。。已经严重影响到系统性能,用户抱怨不断,这时候“数据检索”成为了我们系统的严重瓶颈。



六:第六代架构

  既然检索成了瓶颈,我们必须对数据库进行拆分,尽可能的减少检索中的数据量规模以及尽可能的优化算法。

  1:业务分库

      我们将不同的业务分摊到不同的业务服务器上,而不是将其耦合在一个数据库里面,从而建立起数据库集群,分流应用层对数据库的压力。

  2:分表

  可以采用时间划分,将三个月之后的数据放入到历史表里面,当前表只保存三个月之内的数据,而从极大提供单表的检索能力。

  3:采用nosql

   nosql就是为了web而生,分词,系统日志等等,一样都让不少nosql,而且nosql有其天生的负载均衡。

  4:优化算法

     栈,队列,二叉树,哈希 等等变换和非变换的数据结构在这种大数据的场景下可以得到灵活运用,这也是区分高级程序员和低等码农的一条参考标准。

    当你的架构到这个程度的时候,差不到公司的人数也过千了,这时候我们的业务会分成很多产品线的,比如:票事业部,酒店事业部,旅游度假事业部,攻略社区事业部,每个事业部只会负责自己的产品架构,从而将我们的架构再次细分,从技术角度看,这些事业部又可以提炼出公共的部门,比如登录模块,订单处理等等这些可复用的模块,可以相应的成立公共平台事业部和框架架构部,当这个架构继续往下发展的话,就有了现在的各种云,也就成了各种变钱的工具了,就比如现在的博客园托管在阿里云之上。。。


     终于在今天,结束了高层重视的IVR项目的所有事情,最后祭奠一下,自从猪猪侠拿到那些所谓的数据,导致我们连续加班的日日夜夜。

我也要谈谈大型网站架构之系列(3)——死了都要说的缓存


  说到缓存,我想大家跟我一样都很兴奋,当我们遭遇网站性能瓶颈的时候,缓存是一剂强心针,也是一粒紧急妈富隆,从而在优化网站性能方面冠上了第一定律的帽子,我们前年在做淘应用的时候,就遭遇了性能瓶颈,短时间内采用缓存紧急优化,给我们大优化之前争取了宝贵的时间。



一:缓存的种类

     要说缓存有多少种,太多了,比如浏览器缓存,文件缓存,片段缓存,数据库缓存等等,合理利用这些缓存则能大幅度的提高系统性能,利用不好反而会偷鸡不成蚀把米,给服务器造成巨大的压力,所以这里就存在一个缓存的使用原则的问题。



二:合理的使用缓存

1.  读写小于10:1的情况下,不适合用缓存,我们用缓存的目的就是想分摊下数据库的压力以及利用内存来提速性能,如果读写差不多,或者压根就没读过,这样的死数据就会造成内存资源的浪费。

2.  既然是缓存,就注定了它的资源是有限的,宝贵的,也就注定了我们必须合理利用它的内存空间,也就被迫的让我们清楚的认识到热点数据,不易修改的应该放在缓存,反之不宜放。

3.  大公司在缓存方面做的好的地方就是在一个“控”字上,他们会为缓存专门做一套“缓存系统”,当系统预加载的时候,同时也充当内存数据库使用,将这些元数据加载到缓存系统中,比如“县市区”,“分类信息”等等作为预热数据。



三:分布式缓存

   一般情况下,会有两种形式,第一种就是主从复制的模式,第二种就是分片的模式。

1:主从复制模式

  这种模式曾今在项目中也用过,就是一份内存,多处备份,当其中某一个缓存内容中的数据有变化时,会及时通知其他机器进行缓存更新或清除,这种模式的缺点在于比较容易受制于单台机器的内存限制,优点在于用心跳机制及时用另一台缓存机器顶替,那个时候我们使用120G的大内存,得益于项目业务规模的限制,否则当机器内存爆满的时候就比较尴尬了,所以做大型网站还是谨慎使用吧,毕竟这个也是我们曾今做了一些为了提升性能的尝试。



2:分片的模式

    这种模式在大型网站中还是被大量使用的,它的特点就是可以把一大坨数据通过一定的算法和配置分摊到集群中的若干台机器上,如果集群中的某一台机器挂了,没关系,只会影响到该台机器中的数据,对数据库不会造成很大的影响。一个典型的应用就是memcache,memcache是一个非常简单,实用,高效的分布式缓存架构,其实memcache最值得一提的就是“路由算法的一致性hash”技术使得我们的memcache集群可以自由伸缩,不过现在已经有很多的nosql产品,比如redis,couchdb,mongodb等等,让我们在这个世界上有了更多的选择吧。

     最近看到园子里面有很多抱怨声,没关系,如果觉得自己屈才了,欢迎来携程试一试,只有你达不到的能力,没有给不起你的薪资。

我也要谈谈大型网站架构之系列(4)——分布式中的异步通信 - 一线码农
时间 2014-05-08 01:25:10 博客园_一线码农
原文  http://www.cnblogs.com/huangxincheng/p/3715293.html
主题 分布式系统
我们知道在面向对象编程中,总会想着各种办法来实现代码的解耦,从而让项目中的各种人员面对自己熟悉的业务进行开发,做到术业有专攻,比如大家非常熟悉的三层架构,MVC,MVP以及MVVM模式,让前端设计专注于html的制作,让后端开发人员更加专注于业务逻辑的编写,可以看到,我们这么做的目的就是想最大程度的做到系统的可扩展和可维护性,那么我们的大型网站是不是也要遵守这种模式呢?

一:分层和分割

1:分层

    对于分层,我们可能非常熟知了,数据访问层,业务逻辑层,缓存层,应用层,层层专注于自己的业务,然后根据需要建立起各自的集群,各自分离部署,而从达到系统的扩展性和维护性。

2:分割

    如果说前面是横向切割,那分割就是纵向切割,我们可以把网站的整体业务切分成很多的小业务,比如博客园的导航栏,我们都可以认为是一个独立的网站,配上各自的二级域名,建立各自的集群来实现系统的扩展性,当然这个粒度可大可小。如果说这些子网站不存在相互调用,那么我们新增模块或者修改模块基本上都不会对其他模块造成影响,这也是我们做扩展性的终极目标,现在既然都做到解耦了,下面的目标就是做如何通信了,通信可以分为“同步”和“异步”,这篇主要是讨论下异步操作,在分布式系统中做到"异步操作“,当然少不了强大的消息队列。

二:消息队列

    在分布式的系统中使用消息队列后,我们的生产者只管向消息队列中甩完数据后立即返回,而不管是哪个消费者来消费,可以看到其实消息队列有如下三个优点。

1.  加快网站的相应速度

  这个刚才也说了,应用层直接把消息给消息队列然后直接返回调用端,这样就避免了处理复杂的业务逻辑然后同步的插入到数据库后再返回造成的响应延迟,在很多网站上用户提交订单就是这么处理的,应用层生成一个订单号之后,将订单丢给消息队列,然后
直接到订单成功页面,此时后端消费者对订单还没有处理完毕,因为后面会有比较多的数据操作,比如减库存,数据库同步等等,而用户如果想要看到订单详情,需要点击“订单号”才能进入到订单详情页,这种处理也是因为消息队列的非及时性,所以需要得到网站设计方改进和支持 。

2. 提供系统的可用性

    既然是异步操作,就造成了生产者不知道消费者的存在,而反过来消费者不知道生产者的存在,如果消费者挂了就不会影响到生产者,
生产者还会照常无误的向消息队列甩消息,当消费者恢复正常后就会继续消费消息队列,系统的表现可能就是email或者短信延迟收到,不会对系统造成太大的影响。

3. 并发削峰

   既然是大型网站就免不了高并发的读写操作,很典型的一个例子就是电商中的秒杀,这种高并发的写操作,如果一下子都涌入到数据库里面去了,会导致数据库的压力非常大,从而导致客户端的访问延迟,就是不挂也容易造成数据库的死锁从而造成很多灵异事件,遇到这种
一拥而入的情况,我们就必须进行线性化操作,在代码层面上我们可以用lock机制来串行化,在分布式中我们用“消息队列”来串行化,而且还可以通过逻辑操作来对消息队列进行动态的防洪,控洪。在消息队列的选择上,微软有自己的MSMQ,但是在大型网站中,我们的消息队列同样需要集群,并且希望能跑在内存中,并且支持序列化硬盘,同时在“伸缩性”和“可靠性”上要有好的作为,所以推荐大家用用开源的RabbitMQ,网址:http://www.rabbitmq.com/
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics