前言
最近一直在拜读两本书:
1、李智慧老师的《大型网站技术架构 核心原理与案例分析》 http://www.linuxidc.com/Linux/2015-11/125137.htm
2、曾宪杰老师的《大型网站系统与Java中间件实践》 http://www.linuxidc.com/Linux/2015-11/125138.htm
看了并结合自己目前的工作进行了思考,感觉获益匪浅、受益良多,自己对大型网站的理解又有了不少的加深,下面分享一下自己的学习笔记。
学习笔记
1、大型网站架构的发展史(红字就是每一步发展历程的关键)
(1)从一个小网站发展起来,一台服务器,应用程序、数据库、文件等所有资源都在一台服务器上
(2)网站业务的发展,一台服务器逐渐不能满足需求,因此要将应用和数据分离,应用和数据分离后使用三台服务器:应用服务器、文件服务器和数据库服务器
(3)网站进一步发展,数据库压力太大导致访问延迟,因此使用缓存该改善网站性能(记住,使用缓存是改善网站性能的第一步),网站使用的缓存分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存
(4)使用缓存,数据库访问压力得到有效缓解,但是在网站访问高峰期应用服务器还是成为了整个网站的瓶颈。这种时候要理解,不要企图去更换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求,因此可以通过增加服务器的方式改善负载压力,再通过负载均衡调度服务器,将来自用户浏览器的访问请求分发到应用服务器集群中的某台服务器上
(5)虽然使用缓存可以使大部分数据不走数据库,但是缓存没有命中、缓存过期的数据还是会走数据库,网站达到一定规模之后,数据库读写压力还是会很大,成为网站的瓶颈。此时可以使用数据库读写分离来改善数据库负载压力,应用服务器写数据走写库,应用服务器读数据走读库,目前大部分主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上
(6)随着网站业务继续发展,用户规模不断增大,由于中国复杂的网络环境,不同地区用户访问网站时,速度差别也极大。因此可以使用反向代理和CDN,一方面加快用户访问速度,另一方面减轻后端服务器的负载压力,因为反向代理和CDN的基本原理都是缓存
(7)数据库经过读写分离后,由一台服务器拆分为两台服务器,但还是不能满足网站业务量的需求,因此可以使用分布式数据库,主要拆分手段是业务分库,将不同的业务数据部署在不同的物理服务器上
(8)大型网站为了应对日益复杂的业务场景,可以使用分而治之的手段将整个网站的业务拆分成不同的应用,每个应用独立部署,可以通过超级链建立关系,也可以通过消息队列进行数据分发
大型网站发展到这里,基本上大多数的技术问题都得以解决
2、高性能网站的关键:控制住并发的量。只要能做到这点,很多棘手的数据问题也就不是什么问题了
3、不要企图通过技术解决所有问题,业务的问题也可以通过业务手段去解决
比如12306建立之初,0点售票,网站一下子要承受几千万的访问量,直接导致12306这个网站崩溃,各路专业人士和分专业人士众说纷纭、出谋划策。但这仅仅通过技术能解决问题吗?所以,针对这个需求,12306不仅要改善它的技术架构,也要调整它的业务架构,不要0点售票,在售票方式上引入排队机制、整点售票改为分时段售票,并发量控制住了,整个网站的性能就改善了
4、计算机软件发展的 一个重要目标和驱动力是降低软件的耦合性,事物之间关系越少,就越少彼此影响,越可以独立发展
5、异步架构是典型的生产者消费者模式
6、使用异步队列有几个好处
(1)提高系统的可用性
(2)加快网站的访问速度
(3)消除并发访问高峰
7、网站伸缩性就是指通过不断向集群中加入服务器的手段来缓解不断上升的用户并发访问压力和不断增长的数据存储需求
8、衡量架构伸缩性的指标
(1)是否可用多台服务器架构集群
(2)是否容易向服务器中添加新的服务器
(3)加入的服务器是否可以提供和原服务器无差别的服务
(4)集群中容纳的总服务器是否有限制
9、反应系统忙闲的重要指标Load
System Load也称为Load,即系统负载,指当前正在被CPU执行和等待被CPU执行的线程数之和,,是反映系统忙闲程度的重要指标。多核CPU下,完美情况应该是所有CPU都在用,没有线程等待处理。Load值低于CPU数目,表示CPU有空闲,资源存在浪费;Load值高于CPU数据,表示进程在等待CPU调度,资源存在浪费
10、浏览器访问优化手段
(1)减少http请求,和并CSS、JS、图片,不要发起多次http请求去拿这些数据
(2)使用浏览器缓存,存储静态资源,Cache-Control、Expires、Pragma、Last_Modified都是和缓存的HTTP HEADER
(3)启用压缩,有效减低通信传输的数据量
(4)CSS放在上面、JS放在下面,因为JS下载会立即执行,可能阻塞页面加载速度
(5)减少Cookie传输
11、缓存使用的几点细节
(1)频繁修改的数据不要写缓存,一般读写比例至少2:1以上才会做缓存,即一次写入至少有两次以上的读取,像新浪微博这种,热门微博,一次写入可能会被读取数百万次,那是大大地合算
(2)如果访问没有热点,大部分数据的访问没有集中在小部分数据上,那么做缓存就没有意义,因为缓存有失效机制,大部分数据还没有被再次访问就被挤出缓存了
(3)容忍一定时间的数据不一致,除非数据更新时立刻通知缓存,不过这也会带来开销与事物一致性的问题
(4)使用分布式缓存集群以提高缓存可用性
(5)新启动的缓存没有任何数据,在重建缓存的过程中,系统性能与数据库负载都不太好,因此要根据项目、根据业务,将一部分数据在启动时就加载好,这就是缓存预热
(6)对缓存做无效参数并设置失效时间,避免不恰当的业务或恶意攻击频繁调用接口查询数据库,一旦某一个Key值数据库里面查不到数据就进入无效缓存,一段时间内再次访问这个Key值无数据返回
12、消息队列具有很好的削峰作用(前面提过),不过注意需要适当修改业务流程进行配合
通过异步处理,将短时间高并发产生的事物消息存储在消息队列中,从而可以削平高峰期的并发事物。不过要注意点,由于数据写入消息队列后立即返回给用户,数据在后续的业务校验、写数据库等操作可能失败,因此在使用消息队列进行业务异步处理后,,需要适当修改业务流程进行配合,如订单提交之后,订单数据写入消息队列,不能立即返回给用户订单提交成功,需要在消息队列的订单消费者进程真正处理完该订单的,甚至商品出库后,再通过电子邮件或者SMS消息通知用户订单成功,避免交易纠纷。