大型网站技术架构:核心原理与案例分析

大型网站软件系统的特色

  1. 高并发,大流量
  2. 高可用:系统24*7小时不间断服务
  3. 海量数据:须要存储,管理海量数据,须要使用大量服务器
  4. 用户分布普遍,网络状况复杂:许多大型互联网都是为全球用户提供服务的,用户分布范围广,各地网络状况千差万别
  5. 安全环境恶劣:因为互联网的开放性,使得互联网更容易受到攻击,大型网站几乎天天都会被黑客攻击
  6. 需求快速变动,发布频繁:和传统软件的版本发布频率不一样,互联网产品为快速适应市场,知足用户需求,其产品的发布频率是极高的
  7. 渐进式发展:与传统软件产品或企业应用系统一开始就规划好所有的功能和非功能需求不一样,几乎全部的大型互联网网站都是从一个小网站开始,渐进的发展起来的。

 大型网站架构演化发展历程

  • 初始阶段的网站架构
  • 应用程序,数据库,文件等全部的资源都在一台服务器上

 

  • 应用服务和数据服务分离
  • 应用服务和数据服务分离
  • 应用服务器:须要处理大量的业务逻辑,所以须要更快更强大的CPU
  • 数据库服务器:须要快速磁盘检索和数据缓存,所以须要更快的硬盘和更大的内存
  • 文件服务器:须要存储大量用户上传的文件,所以须要更大的硬盘

 

  • 使用缓存改善网站性能
  • 网站使用缓存
  • 缓存在应用服务器上的本地缓存:访问速度更快,可是受应用服务器内存限制,其缓存数据量有限,并且会出现和应用程序争内存的状况。
  • 缓存在专门的分布式缓存服务器上的远程缓存:远程分布式缓存可使用集群的方式,部署大内存的服务器做为专门的缓存服务器,能够在理论上作到不受内存容量限制的缓存服务。

 

  • 使用应用服务器集群改善网站的并发处理能力
  • 应用服务器集群部署
  • 负载均衡调度服务器:未来自用户浏览器的访问请求分发到应用服务器集群中的任何一台服务器上。

 

  • 数据库读写分离
  • 数据库读写分离
  • 主从热备功能:经过配置两台数据库主从关系,能够将一台数据库服务器的数据更新同步到另外一台服务器上。
  • 应用服务器在写数据库的时候,访问主数据库,主数据库经过主从复制机制将数据更新同步到从数据库,这样当应用服务器读数据的时候,就能够经过从数据库得到数据。为了便于应用程序访问读写分离后的数据库,一般在应用服务器端使用专门的数据访问模块,使数据库读写分离对应用透明。

 

  • 使用反向代理和CDN加速网站响应
  • 网站使用反向代理和CDN加速访问
  • CDN和反向代理:基本原理都是缓存,区别在于CDN部署在网络提供商的机房,使用户在请求网站服务时,能够从距离本身最近的网络提供商机房获取数据;反向代理则部署在网站的中心机房,当用户的请求到达中心机房后,首先访问的服务器是反向代理服务器,若是反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户。

 

  • 使用分布式文件系统和分布式数据库系统
  • 使用分布式文件系统和分布式数据库系统
  • 分布式数据库:是网站数据库拆分的最后手段,只有再表单数据规模很是庞大的时候才使用。不到不得已时,网站更经常使用的数据库拆分手段是业务分库,将不一样的数据库部署在不一样的物理服务器上。

 

  • 使用NoSQL和搜索引擎
  • 使用NoSQL和搜索引擎
  • NoSQL和搜索引擎:源自互联网的技术手段,对可伸缩的分布式特性具备更好的支持。应用服务器则经过一个统一数据访问模块访问各类数据,减轻应用程序管理诸多数据源的麻烦。

 

  • 业务拆分
  • 业务拆分
  • 业务拆分:根据产品线划分,将一个网站拆分红许多不一样的应用,每一个应用独立部署维护。应用之间能够经过一个超连接创建关系(在首页上的导航连接每一个都指向不一样的应用地址),也能够经过消息队列进行数据分发,固然最多的仍是经过访问同一个数据存储系统来构成一个关联的完整系统。

 

  • 分布式服务
  • 分布式服务
  • 分布式服务:能够将应用系统中共用的业务提取出来,独立部署。这些可复用的业务链接数据库,提供共用业务服务,而应用系统只须要管理用户界面,经过分布式服务调用共用业务服务完成具体业务操做。

 大型网站架构演化的价值观

  1. 大型网站架构技术的核心价值是随网站所需灵活应对
  2. 驱动大型网站技术发展的主要力量是网站的业务发展

网站架构设计误区前端

  1. 一味追随大公司的解决方案算法

  2. 为了技术而技术spring

  3. 企图用技术解决全部问题数据库

 大型网站架构模式编程

  • 模式的关键在于模式的可重复性,问题与场景的可重复性带来解决方案的可重复使用

大型网站架构模式

模式的关键在于模式的可重复性,问题与场景的可重复性带来解决方案的可重复使用。浏览器

网站架构模式缓存

为了解决大型网站面临的高并发访问、海量数据处理、高可靠运行等一系列问题与挑战,大型互联网公司在实践中提出了许多解决方案,以实现高性能、高可用、易伸缩、可扩展、安全等各类技术架构目标。这些解决方案又被更多网站重复使用,从而逐渐造成大型网站架构模式。安全

  • 1. 分层 在实践中,大的分层结构内部还能够继续分层,如:

  • (1)应用层
    • 视图层(美工负责)
    • 业务逻辑层(工程师负责)
  • (2)服务层
    • 数据接口层(适配各类输入和输出的数据格式)
    • 逻辑处理层
  • 2. 分割
    • 若是说分层是将软件在横向方面进行切分,那么分割就是在纵向方面对软件进行切分。
  • 3. 分布式
    • 对于大型网站,分层和分割的一个主要目的是为了切分后的模块便于分布式部署,即将不一样模块部署在不一样的服务器上,经过远程调用协同工做。 分布式解决网站高并发带来问题:
    • (1).分布式意味着服务调用必须经过网络,这可能对性能形成比较严重的影响。
    • (2).服务器越多,服务器宕机的几率也就越大,一台服务器宕机形成的服务器不可用可能会致使不少应用不可访问,使网站可用性下降。
    • (3).数据在分布式环境中保持数据一致性也很是困难。
    • (4)分布式致使网站依赖错综复杂,开发管理维护困难。
    • 在网站应用中,经常使用的分布式方案有如下几种:
    • 1.分布式应用和服务:将分层和分割后的应用和服务模块分布式部署。
    1. 改善网站性能和并发性
    2. 加快开发和发布速度
    3. 减小数据库链接资源消耗
    4. 使不一样应用复用共同的服务
    5. 便于业务功能的扩展
    • 2.分布式静态资源:网站的静态资源独立分布式部署,并采用独立的域名,“动静分离”。
    1. 减轻应用服务器的负载压力
    2. 加快浏览器并发加载的速度
    3. 有利于网站分工合做
    • 3.分布式数据和存储:传统关系数据库和各类NoSQL几乎都是分布式的。
    • 4.分布式计算:目前网站广泛使用Hadoop及其MapReduce分布式计算框架进行此类批处理计算,其特色是移动计算而不是移动数据,将计算程序分发到数据所在位置以加速计算和分布式计算。
    • 5.分布式配置:支持网站线上服务器配置实时更新。
    • 6.分布式锁:分布式环境下实现并发和协同。
    • 7.分布式文件:支持云存储。
  • 4. 集群

使用分布式已经将分层和分割后的模块独立部署,对于用户访问集中的模块(如网站首页),还须要将独立部署的服务器集群化,即多台服务器部署相同应用构成一个集群,经过负载均衡设备共同对外提供服务。性能优化

  • 5. 缓存

缓存就是将数据存放在距离计算最近的位置以加快处理速度。缓存是改善软件性能的第一手段。服务器

    • (1).CDN:即内容分发网络,部署在距离用户最近的网络服务商,用户的网络请求老是先到达网络服务商那里,在这里缓存网站的一些静态资源(较少变化的数据),就能够以最快速度返回给用户。
    • (2).反向代理:属于网站前端架构的一部分,部署在网站的前端,当用户请求到达网站的数据中心时,最早访问到的就是反向代理服务器,这里环迅网站的静态资源,无需将请求继续转发给应用服务器就能返回给用户。
    • (3).本地缓存:在应用服务器本地缓存着热点数据,应用程序能够在本机内存中直接访问数据,而无需访问数据库。
    • (4)分布式缓存:将数据缓存在一个专门的分布式缓存集群中,应用程序经过网络通讯访问缓存数据。

使用缓存两个前提条件:

    • 数据访问热点不均衡,某些数据会被更频繁的访问,这些数据应该放在缓存中。
    • 数据在某个时间段内有效,不会很快过时,不然缓存的数据会因已经失效而产生脏读,影响结果的正确性。
  • 6. 异步

系统解耦的手段除了分层、分割、分布等,还有异步。业务之间的消息传递不是同步调用,二十将一个业务操做分红多个阶段,每一个阶段之间经过共享数据的方式异步执行进行协做。

    • (1)在单一服务器内经过多线程共享内存队列的方式实现异步。
    • (2)在分布式系统中多个服务器集群经过分布式消息队列实现异步,分布式消息队列可看作内存队列的分布式部署。

异步架构是典型的生产者消费者模式,二者不存在直接调用,只要保持数据结构不变,彼此功能实现能够随意变化而不互相影响,这对网站扩展新功能很是便利。除此以外,使用异步消息队列还有以下特性:

    • (3)提升系统可用性:消费者服务器发生故障,数据会在消息队列服务器中存储堆积,生产者服务器能够继续处理业务请求,系统总体表现无端障。消费者服务器回复正常后,继续处理消息队列中的数据。
    • (4)加快网站响应速度:处在业务处理前端的生产者服务器在处理完业务请求后,将数据写入消息队列,不须要等待消费者服务器处理就能够返回,响应延迟减小。

消除并发访问高峰:使用消息队列将忽然增长的访问请求数据放入消息队列中,等待消费者服务器依次处理,就不会对整个网站形成太大压力。

  • 7. 冗余

访问和负载很小的服务也必须部署至少两台服务器构成一个集群,母的是经过冗余实现服务器高可用。数据库除了按期备份,存档保存,实现冷备份外,为了保证在线业务高可用,还须要对数据库进行主从分离,实时同步实现热备份。

  • 8. 自动化
    • 发布过程自动化
    • 自动化代码管理
    • 自动化测试
    • 自动化安全检测
    • 自动化部署
    • 自动化监测
    • 自动化报警
    • 自动化失效转移
    • 自动化失效恢复
    • 自动化降级
    • 自动化分配资源
  • 9. 安全
    • 经过密码和手机校验码进行身份认证
    • 登陆、交易等操做须要对网络通讯进行加密
    • 防止机器人程序攻击网站,使用验证码识别
    • 对于常见的用于攻击网站的XSS攻击、SQL注入等相应处理
    • 对于垃圾信息、敏感信息进行过滤
    • 对交易转帐等重要操做根据交易模式和交易信息进行风险控制

架构模式在新浪微博的应用

新浪微博的系统架构 相关连接

    • 1.基础服务层:提供数据库、缓存、存储、搜索等数据服务,以及其余一些基础技术服务,这些服务支撑了新浪微博的海量数据和高并发访问,是整个系统的技术基础。
    • 2.中间层(平台服务和应用服务层):新浪微博的核心服务是微博、关系和用户,这些服务被分割成为独立的服务模块,经过依赖调用和共享基础数据构成呢个的新浪微博业务基础。
    • 3.API和业务层:各类客户端(包括Web网站)和第三方应用,经过调用API集成到新浪微博的系统中,共同组成一个生态系统。
    • 这些被分层和分割后的业务模块与基础技术模块分布式部署,每一个模块都部署在一组独立的服务器集群上,经过远程调用的方式进行依赖访问。

小结

好的设计绝对不是模仿,不是生搬硬套某个模式,而是对问题深入理解之上的创造与创新。

大型网站核心架构要素

架构:最高层次的规划,难以改变的命运

软件架构:有关软件总体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。 软件架构:性能、可用性、伸缩性、扩展性和安全性。

  • 性能
    • 1.浏览器端:经过浏览器缓存、使用页面压缩、合理布局页面、减小Cookie传输等手段改善性能。
    • 2.CDN:将网站静态内容分发至离用户最近的网络服务商机房,使用户经过最短访问路径获取数据。
    • 3.反向代理服务器:缓存热点文件,加快请求响应速度,减轻应用服务器负载压力。
    • 4.应用服务器端:本地缓存和分布式缓存,经过缓存在内存中的热点数据处理用户请求,加快请求处理过程,减轻数据库负载压力
    • 5.异步操做:将用户请求发送至消息队列等待后续任务处理,而当前请求直接返回响应给客户。
    • 6.集群:将多台服务器组成一个集群共同对外服务,提升总体处理能力,改善性能。
    • 7.代码层面:经过使用多线程、改善内存管理等手段优化性能。
    • 8.数据库服务器端:索引、缓存、SQL优化等性能优化手段已经比较成熟,NoSQL数据库经过优化数据模型、存储结构、伸缩性等手段在性能方面的优点日趋明显。
  • 可用性

网站高可用框架设计的前提是必然会出现服务器宕机,而高可用设计的目标就是当服务器宕机的时候,服务或者应用依然可用。

网站高可用的主要手段是冗余,应用部署在多台服务器上同时提供访问,数据存储在多台服务器上互相备份,任何一台服务器宕机都不会影响应用的总体可用,也不会致使数据丢失。

    • 1. 对应用服务器:多台服务器经过负载均衡设备组成一个集群共同对外提供服务,任何一台服务器宕机,只须要把请求切换到其余服务器就能够实现应用的高可用,可是一个前提条件是应用服务器上不能保存请求的会话信息。
    • 2.对存储服务器:须要对数据进行实时备份,当服务器宕机时须要将数据访问转移到可用的服务器上,并进行数据恢复以保证继续有服务器宕机的时候数据依然可用。
    • 3.对软件质量保证:经过预发布验证、自动化测试、自动化测试、自动化发布、灰度发布等手段,减小将故障引入线上环境的可能,避免故障范围扩大。
  • 伸缩性
    • 伸缩性是指经过不断向集群中加入服务器的手段来缓解不断上升的用户并发访问压力和不断增加的数据存储需求。 衡量架构伸缩性的主要标准就是是否可用多台服务器构建集群,是否容易向集群中添加新的服务器。加入新的服务器后是否能够提供和原来服务器无差异的服务。集群中可容纳的总的服务器数量是否有限制。
    • 1. 对于应用服务器集群:只要服务器上不保存数据,全部的服务器都是对等的,经过使用合适的负载均衡设备就能够向集群中不断加入服务器。
    • 2.对于缓存服务器集群:加入新的服务器可能会致使缓存路由失效,进而致使集群中大部分缓存数据都没法访问。虽然缓存的数据能够经过数据库从新加载,可是若是应用已经严重依赖缓存,可能会致使整个网站崩溃。须要改进缓存路由算法保证缓存数据的可访问性。
    • 3.对于关系数据库:虽然支持数据复制,主从热备等机制,可是很难作到大规模集群的可伸缩性,所以关系数据库的集群伸缩性方案必须在数据库以外实现,经过路由分区等手段将部署有多个数据库的服务器组成一个集群。
    • 4.对于NoSQL数据库:为海量数据而生,所以其对伸缩性的支持一般很是好,能够作到在较少运维参与的状况下实现集群规模的线性伸缩。
  • 扩展性

网站的扩展性架构直接关注网站的功能需求。

衡量网站架构扩展性好坏的主要标准就是在网站增长新的业务产品时,是否能够实现对现有产品透明无影响,不须要任何改动或者不多改动既有业务功能就能够上线新产品。

    • 1. 事件驱动架构:一般利用消息队列实现,将用户请求和其余业务时间构形成消息发布到消息队列,消息的处理者做为消费者从消息队列中获取消息进行处理。经过这种方式将消息产生和消息处理分离开来,能够透明地增长新的消息生产者任务或者新的消息消费者任务。
    • 2.分布式服务:将业务和可复用服务分离开,经过分布式服务框架调用。新增产品能够经过调用可复用的服务实现自身的业务逻辑,而对现有产品没有任何影响。可复用服务升级变动的时候,也能够经过提供多版本服务对应用实现透明升级,不须要强制应用同步变动。
    • 3.开放平台接口:吸引第三方开发者,调用网站服务,使用网站数据开发周边产品,扩展网站业务。
  • 安全性
    • 网站的安全架构就是保护网站不受恶意访问和攻击,保护网站的重要数据不被窃取。

小结

性能、可用性、伸缩性、扩展性和安全性是网站架构最核心的几个要素。

瞬时响应:网站的高性能架构

网站性能是客观指标,能够具体体现到响应时间、吞吐量等技术指标,同时也是主观的感觉,而感觉则是一种与参与者相关的微妙的东西,用户的感觉和工程师的感觉不一样,不一样的用户感觉也不一样。

网站性能测试

不一样视角下的网站性能

1. 用户视角的网站性能

从用户角度,网站性能就是用户在浏览器上直观感觉到的网站响应素的快仍是慢。

用户感觉到的时间,包括用户计算机和网站服务通讯的时间、网站服务器处理的时间、用户计算机浏览器构造请求解析响应数据的时间。

在实践中使用一些前端优化手段:

优化HTML式样 利用浏览器端的并发和异步特性 调整浏览器缓存策略 使用CDN服务 反向代理

2. 开发人员视角的网站性能

开发人员关注的主要是应用程序自己及其相关子系统的性能,包括响应延迟、系统吞吐量、并发处理能力、系统稳定性等技术指标。

主要优化手段:

缓存加速数据读取 使用集群提升吞吐能力 使用异步消息加快请求响应及实现削峰 使用代码优化手段改善程序性能

运维人员视角的网站性能 主要优化手段:

建设优化骨干网 使用高性价比定制服务器 利用虚拟化技术优化资源利用

性能测试指标

1. 响应时间

响应时间是系统最重要的性能指标,直观地反映了系统的“快慢”。

实践中一般采用的办法是重复请求,获得单次请求的响应时间。

2. 并发数

指系统可以同时处理请求的数目,这个数字也反映了系统的负载特性。

网站系统用户数 >> 网站在线用户数 >> 网站并发用户数

测试程序经过多线程模拟并发用户的办法来测试系统的并发处理能力,为了真实模拟用户的行为,测试程序并非启动多线程而后不停地发送请求,而是在两次请求之间加入一个随机等待时间,这个时间被称做思考时间。

3. 吞吐量

指单位时间内系统处理的请求数量,体现系统的总体处理能力。 TPS(每秒事物数)是吞吐量的一个经常使用量化指标,还有HPS(每秒HTTP请求数、QPS(每秒查询数)等。 在系统并发数由小逐渐增大的过程当中(伴随着服务器系统资源消耗逐渐增大),系统吞吐量先是逐渐增长,达到一个极限后,随着并发数的增长范儿降低,达到系统崩溃点后,系统资源耗尽,吞吐量为零。

这个过程当中,响应时间现实小幅度上升,达到吞吐量极限后,快速上升,到达系统崩溃点后,系统失去响应。

4. 性能计数器

性能计数器是描述服务器或操做系统性能的一些数据指标,包括System Load、对象与线程数、内存使用、CPU使用、磁盘与网络I/O等指标 System Load:即系统负载,指当前正在被CPU执行和等待被CPU执行的进程数目总和,是反映系统忙闲程度的重要指标。 性能测试方法

性能测试:以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能预期。

负载测试:对系统不断地增长并发请求以增长系统压力,直到系统的某项或多项性能指标达到安全临界值。

压力测试:查过安全负载的状况下,对系统继续施加压力,直到系统崩溃或不能再处理任何请求,以此得到系统最大压力承受能力。

稳定性测试:被测试系统在特定硬件、软件、网络环境条件下,给系统加载必定业务压力,使系统运行一段较长时间,以此检测系统是否稳定。在不一样生产环境、不一样时间点的请求压力是不均匀的,呈波浪特性,所以为了更好地模拟生产环境,稳定性测试也应不均匀地对系统施加压力。

性能测试遵循如图所示抛物线规律:

性能测试曲线

横坐标表示消耗的系统资源,纵坐标表示系统处理能力(吞吐量)。

a~b段:网站的平常运行区间

c点:系统最大负载点

d点:系统崩溃点

与性能曲线相对应的是用户访问的等待时间(系统响应时间),如:

并发用户访问响应时间曲线

在平常运行区间,能够得到最好的用户响应时间,随着并发用户数的增长,响应延迟愈来愈大,直到系统崩溃,用户失去响应。

性能测试报告

测试报告结果反映上述性能测试曲线规律,简单示例:

性能测试结果报告

性能优化策略

1. 性能分析

检查请求处理的各个环节的日志,分析哪一个环节响应时间不合理、超过预期。

检查监控数据,分析影响性能的主要因素是内存、磁盘、网络、仍是CPU,是代码问题仍是架构设计不合理,或者系统资源确实不足。

2. 性能优化

Web前端性能优化

应用服务器性能优化

存储服务器性能优化

Web前端性能优化

通常说来Web前端指网站业务逻辑以前的部分,包括浏览器加载、网站视图模型、图片服务、CDN服务等,主要优化手段有优化浏览器访问、使用反向代理、CDN等。

浏览器访问优化

1. 减小http请求

主要手段是合并CSS、合并JavaScript、合并图片。 将浏览器一次访问须要的Javascript、CSS合并成一个文件,这样浏览器只须要一次请求。

图片也能够合并,多张图片合并成一张,若是每张图片都有不一样的超连接,可经过CSS偏移响应鼠标点击操做构造不一样的URL。

2. 使用浏览器缓存

将更新频率比较低的、使用频率比较高的文件缓存在浏览器中,能够极好地改善性能。经过设置HTTP头中的Cache-Control和Expires的属性,可设定浏览器缓存,缓存时间能够是数天,甚至是几个月。

某些时候,静态资源文件变化须要及时应用到客户端浏览器,能够经过改变文件名实现,即更新Javascript文件并非更新Javascript文件内容,而是生成一个新的Javascript文件并更新HTML文件中的引用。

使用浏览器缓存策略的网站在更新静态资源时,应采用批量更新的办法,好比须要更新10个图标文件,不宜把10个文件一次所有更新,二十一个文件一个文件逐步更新,并有必定的间隔时间,以避免用户浏览器忽然大量缓存失效,集中更新缓存,形成服务器负载骤增、网络堵塞的状况。

3. 启用压缩

在服务器端对文件进行压缩,在浏览器端对文件进行解压缩,能够有效减小通讯传输的数据量。

压缩对服务器和浏览器产生必定的压力,在通讯带宽良好,而服务器资源不足的状况下要权衡考虑。

4. CSS放在页面最上面、JavaScript放在页面最下面

浏览器会在下载彻底部CSS以后才对整个页面进行渲染,所以最好的作法是将CSS放在页面最上面,让浏览器尽快下载CSS。

JavaScript则相反,浏览器在加载JavaScript后当即执行,有可能会阻塞整个界面,形成页面显示缓慢,所以JavaScript最好放在页面最下面。

5. 减小Cookie传输

太大的Cookie会严重影响数据传输,尽可能减小Cookie中传输数据量。

对于某些静态资源的访问,如CSS、JavaScript等,发送Cookie没有意义,能够考虑静态资源使用独立域名访问,避免请求静态资源时发送Cookie,减小Cookie传输次数。

CDN加速

CDN(Content Distribute Network,内容分发网络)的本质仍然是一个缓存,并且将数据缓存存在离用户最近的地方,使用户以最快的速度获取数据,即网络第一跳。

利用CDN的网站架构

CDN可以缓存的通常是静态资源,可是这些文件访问频度很高。

反向代理

 

利用反向代理的网站架构

反向代理服务器具备保护网站安全的做用。

能够经过配置缓存功能加速Web请求。

反向代理能够实现负载均衡的功能,经过负载均衡构建的应用集群能够提升系统整体处理能力,进而改善网站高并发状况下的性能。

应用服务器性能优化

应用服务器就是处理网站的服务器,网站的业务代码都部署在这里,是网站开发最复杂,变化最多的地方,优化手段主要有缓存、集群、异步等。

分布式缓存

网站性能优化第必定律:优先考虑使用缓存优化性能。

1. 缓存的基本原理

缓存指将数据存储在相对较高访问速度的存储媒介中,以供系统处理。一方面缓存访问速度快,能够减小数据访问的时间,另外一方面若是缓存的数据是通过计算处理获得的,那么被缓存的数据无需重复计算便可直接使用,所以缓存还起到减小计算的做用。 缓存的本质:内存的Hash表,网站应用中,数据缓存以一对Key、Value的形式存储在内存的Hash表中。Hash表数据读写的时间复杂度为O(1)。

Hash表存储例子

缓存主要用来存放那些读写比很高、变化不多的数据。

使用缓存存取数据

2. 合理使用缓存

频繁修改的数据

若是缓存中保存的是频繁修改的数据,就会出现数据写入缓存后,应用还来不及读取缓存,数据就已失效的情形,徒增系统负担。通常来讲,数据的读写比在2:1以上,即写入一次缓存,在数据更新前至少读取两次,缓存才有意义。

没有热点的访问

缓存使用内存做为存储,内存资源宝贵而有限,不可能将全部的数据都缓存起来,只能将最新访问的数据缓存起来,而将历史数据清理出缓存。

数据不一致与脏读

通常会对缓存的数据设置失效时间,一旦超过失效时间,就要从数据库中从新加载。所以应用要容忍必定时间的数据不一致。在互联网应用中,这种延迟一般是能够接受的,可是具体应用仍需慎重对待。还有一种策略是数据更新时当即更新缓存,不过这也会带来更多系统开销和事务一致性问题。

缓存可用性

缓存是为提升数据读取性能的,缓存数据丢失或者缓存不可用不会影响到应用程序的处理,能够从数据库直接获取数据。可是当缓存服务崩溃时,数据库会有可能彻底不能承受如此大的压力而宕机,进而致使整个网站不可用。这种状况被叫作缓存雪崩,发生这种故障,甚至不能简单地重启缓存服务器和数据库服务器来恢复网站访问。

实践中,有的网站经过缓存热备等手段提升缓存可用性:当某台缓存服务器宕机时,将缓存访问切换到热备服务器上。可是这种设计显然有违缓存初衷,缓存不该该被看成可靠的数据源使用。

经过分布式缓存服务器集群,将缓存数据分布到集群多台服务器上可在必定程度上改善缓存的可用性。当一台缓存服务器宕机,只有部分缓存数据丢失,从新从数据库加载这部分数据不会对数据库产生很大影响。

缓存预热

缓存中存放的是热点数据,热点数据又是缓存系统利用LRU(最近最久未用算法)对不断访问的数据筛选淘汰出来的,这个过程须要花费较长的时间。新启动的缓存系统若是没有任何数据,在重建缓存数据的过程当中,系统的性能和数据库负载都不太好,那么最好在缓存系统启动时就把热点数据加载好,这个缓存预加载手段叫作缓存预热。对于一些元数据如城市地名列表、类目信息,能够在启动时加载数据库中所有数据到缓存进行预热。

缓存穿透

若是由于不恰当的业务、或者恶意攻击持续高并发地请求某个不存在的数据,因为缓存没有保存该数据,全部的请求都会落到数据库上,会对数据库形成很大压力,甚至崩溃。一个简单的对策是将不存在的数据也缓存起来(其value值为null)。

3. 分布式缓存架构

分布式缓存指缓存部署在多个服务器组成的集群中,以集群方式提供缓存服务,其架构方式有两种,一种是以JBoss Cache为表明的须要更新同步的分布式缓存,一种是以Memcached为表明的不相互通讯的分布式缓存。 JBoss Cache:JBoss Cache的分布式缓存在集群中全部服务器中保存相同的缓存数据,当某台服务器有缓存数据更新的时候,会通知集群中其余机器更新缓存数据或清除缓存数据。

须要更新同步的JBoss-Cache

JBoss Cache一般将应用程序和缓存部署在同一台服务器上,应用程序可从本地快速获取缓存数据,可是这种方式带来的问题是缓存数据的数量受限于单一服务器的内存空间,并且当集群规模较大时,缓存更新信息须要同步到集群全部的机器,其代价惊人。于是这种方案更多见于企业应用系统中,不多在大型网站使用。

Memcached:之后讲到。

4. Memcached

简单的设计、优异的性能、互不通讯的服务器集群、海量数据可伸缩的架构。 不互相通讯的Memcached

简单的通讯洗衣

远程通讯设计须要考虑两方面的要素:

通讯协议:即选择TCP协议仍是UDP协议,抑或HTTP协议。

通讯序列化协议:数据传输的两端,必须使用彼此可识别的数据序列化方式才能使通讯得以完成,如XML、JSON等文本序列化协议,或者Google Protobuffer等二进制序列化序列化协议。

Memcached使用TCP协议(UDP也支持)通讯,其序列化协议则是一套基于文本的自定义协议,以一个命令关键字开头,后面是一组命令操做数。例如读取一个数据的命令协议是get\。

丰富的客户端程序

Memcached通讯协议很是简单,只要支持该协议的客户端均可以和 Memcached服务器通讯,所以Memcached发展出很是丰富的客户端程序,几乎支持全部主流的网站编程语言。

高性能的网络通讯

Memcached 服务端通讯模块基于Libevent,一个支持事件触发的网络通讯程序库。Libevent的设计和实现有许多值得改善的地方,但它在稳定的长链接方面的表现却正是Memcached须要的。

高效的内存管理

Memcached使用了一个很是简单的办法——固定空间分配。 Memcached将内存空间分为一组slab,每一个slab里又包含一组chunk,同一个slab里的每一个chunk的大小是固定的,拥有相同大小 chunk的slab被组织在一块儿,叫做slab_class。

Memcached内存管理

存储数据时根据数据的Size大小,寻找一个大于Size的最小chunk将数据写入。

这种内存管理方式避免了内存碎片管理的问题,内存的分配和释放都是以chunk为单位的。

Memcached采用LRU算法释放最近最久未被访问的数据占用的空间,释放的chunk被标记为未用,等待下一个合大小数据的写入。

这种方式也会带来内存浪费的问题。

互不通讯的服务器集群架构

正是集群内服务器互不通讯使得集群能够作到几乎无限制的线性伸缩,这也正是目前流行的许多大数据技术的基本架构特色。

异步操做

使用消息队列将调用异步化,可改善网站的扩展性。事实上,使用消息队列还可改善网站系统的性能。

使用消息队列服务器

在不使用消息队列的状况下,用户的请求数据直接写入数据库,在高并发的状况下,会对数据库形成巨大的压力,同时也使得响应延迟加重。

在使用消息队列后,用户请求的数据发送给消息队列后当即返回,再由消息队列的消费者进程(一般状况下,该进程一般独立部署在专门的服务器集群上)从消息队列中获取数据,异步写入数据库。因为消息队列服务器处理速度远快于数据库(消息队列服务器也比数据库具备更好的伸缩性),所以用户的响应延迟可获得有效改善。

消息队列具备很好的削峰做用——即经过异步处理,将短期高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。

因为数据写入消息队列后当即返回给用户,数据在后续的业务校验、 写数据库等操做可能失败, 所以在使用消息队列进行业务异步处理后,须要适当修改业务流程进行配合,如订单提交后,订单数据写入消息队列,不能当即返回用户订单提交成功,须要在消息队列的订单消费者进程真正处理完该订单,甚至商品出库后,再经过电子邮件或 SMS消息通知用户订单成功,以避免交易纠纷。

使用集群

在网站高并发访问的场景下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具备更好的响应延迟特性。

利用负载均衡技术改善性能

代码优化

1. 多线程

从资源利用的角度看,使用多线程的缘由主要有两个:

IO阻塞 多CPU

启动线程数=[任务执行时间/(任务执行时间-IO等待时间)xCPU内核数]

最佳启动线程数和CPU内核数量呈正比,和IO阻塞时间成反比。若是任务都是CPU计算型任务,那么线程数最多不超过CPU内核数。

解决线程安全的主要手段:

将对象设计为无状态对象:无状态对象是指对象自己不存储状态信息(对象无成员变量,或者成员变量也是无状态对象),这样多线程并发访问时候就不会出现状态不一致。从面向对象设计角度看,无状态对象时一种不良设计。

使用局部对象:在方法内部建立对象,这些对象会被每一个进入该方法的线程建立,除非程序有意识地将这些对象传递给其余线程,不然不会出现对象被多线程并发访问的清形。

并发访问资源时使用锁:多线程访问资源的时候,经过锁的方式使多线程并发操做转化为顺序操做,从而避免资源被并发修改。锁致使线程同步顺序执行,可能会对系统性能产生严重影响。

2. 资源复用

系统运行时,要尽可能减小那些开销很大的系统资源的建立和销毁,好比数据库链接、网络通讯链接、线程、复杂对象等。 单例:Java开发经常使用的对象容器spring默认构造的对象都是单例(要注意的是 Spring 的单例是 Spring 容器管理的单例,而不是用单例模式构造的单例)。

对象池:经过复用对象实例,减小对象建立和资源消耗。对于数据库链接对象,每次建立链接,数据库服务端都须要建立专门的资源以应对,所以频繁建立关闭数据库链接,对数据库服务器而言是灾难性的,同时频繁建立关闭链接也须要花费较长的时间。所以在实践中,应用程序的数据库链接基本都使用链接池(Connection Pool) 的方式。

3. 数据结构

目前比较好的字符串 Hash 散列算法有Time33算法, 即对字符串逐字符迭代乘以33,求得 Hash值,算法原型为:

hash(i) = hash(i-1) * 33 + str[i] Time33虽然能够较好地解决冲突,可是有可能类似字符串的HashCode也比较接近,如字符串“AA”的HashCode是2210,字符串“AB”的HashCode是2211。 这在某些应用场景是不能接受的,这种状况下,一个可行的方案是对字符串取信息指纹,再对信息指纹求 HashCode。因为字符串微小的变化就能够引发信息指纹的巨大不一样,所以能够得到较好的随机散列。

经过MD5计算HashCode

4. 垃圾回收

以JVM为例,其内存主要可划分为堆(heap ) 和堆栈(stack)。堆栈用于存储线程上下文信息,如方法参数、局部变量等。堆则是存储对象的内存空间,对象的建立和释放、垃圾回收就在这里进行。经过对对象生命周期的观察,发现大部分对象的生命周期都极其短暂,这部分对象产生的垃圾应该被更快地收集,以释放内存,这就是 JVM 分代垃圾回收。

JVM分带垃圾回收机制

存储性能优化

机械硬盘 VS 固态硬盘

机械硬盘在数据连续访问(要访问的数据存储在连续的磁盘空间上)和随机访问(要访问的数据存储在不连续的磁盘空间)时,因为移动磁头臂的次数相差巨大,性能表现差异也很是大。 能够像内存同样快速随机访问。并且 SSD 具备小的功耗和更少的磁盘震动与噪声。 在网站应用中,大部分应用访问数据都是随机的,这种状况下 SSD 具备更好的性能表现。

B+树 VS LSM树

为了改善数据访问特性,文件系统或数据库系统一般会对数据排序后存储,加快数据检索速度,这就须要保证数据在不断更新、插入、删除后依然有序,传统关系数据库的作法是使用B+树。

B+树原理示意图

B+树是一种专门针对磁盘存储而优化的 N 叉排序树,以树节点为单位存储在磁盘中,从根开始查找所需数据所在的节点编号和磁盘位置,将其加载到内存中而后继续查找,直到找到所需的数据。

目前数据库多采用两级索引的 B+树,树的层次最多三层。所以可能须要 5 次磁盘访问才能更新一条记录(三次磁盘访问得到数据索引及行ID而后再进行一次数据文件读操做及一次数据文件写操做)。

目前许多 NoSQL 产品釆用 LSM 树做为主要数据结构。

LSM树原理示意图

LSM 树能够看做是一个 N 阶合并树。数据写操做(包括插入、修改、删除)都在内存中进行,而且都会建立一个新记录(修改会记录新的数据值,而删除会记录一个删除标志 ),这些数据在内存中仍然仍是一棵排序树,当数据量超过设定的内存阈值后,会将这棵排序树和磁盘上最新的排序树合并。当这棵排序树的数据量也超过设定阈值后,和磁盘上下一级的排序树合并。合并过程当中,会用最新更新的数据覆盖旧的数据(或者记录为不一样版本)。

在须要进行读操做时,老是从内存中的排序树幵始搜索,若是没有找到,就从磁盘上的排序树顺序查找。

在 LSM 树上进行一次数据更新不须要磁盘访问,在内存便可完成,速度远快于 B+树。当数据访问以写操做为主,而读操做则集中在最近写入的数据上时,使用 LSM 树能够极大程度地减小磁盘的访问次数,加快访问速度。

做为存储结构,B+树不是关系数据库所独有的,NoSQL 数据库也可使用 B+树。同理,关系数据库也可使用LSM。

RAID VS HDFS

RAID (廉价磁盘冗余阵列)技术主要是为了改善磁盘的访问延迟,加强磁盘的可用性和容错能力。目前服务器鈒别的计算机都支持插入多块磁盘(8块或者更多 ),经过使用RAID技术,实现数据在多块磁盘上的并发读写和数据备份。

常见的RAID技术:

经常使用RAID技术原理图

RAID0:具备极快的数据读写速度,可是RAID0不作数据备份,由于磁盘中只要有一块损坏,数据完整性就被破坏,全部磁盘的数据都会损坏。

RAID1:任何一块磁盘的损坏都不会致使数据丢失,插入一块新磁盘就能够经过复制数据的方式自动修复,具备极高的可靠性。

RAID10:结合RAID0和RAID1两种方案,提升可靠性改善性能,RAID10磁盘利用率较低,有一半磁盘用来写备份数据。

RAID3:RAID3不多在实践中使用。

RADI5:RAID5被更多的使用,避免RAID3频繁写坏一块磁盘的状况。

RAID6:数据可靠,在出现同时损坏两块磁盘的状况下,仍然能够修复数据。

几种RAID技术比较

RAID 技术能够经过硬件实现,好比专用的RAID卡或者主板直接支持,也能够经过软件实现。RAID技术在传统关系数据库及文件系统中应用比较普遍,可是在大型网站比较喜欢使用的NoSQL以及分布式文件系统中,RAID技术却遭到冷落。 HDFS以块(Block) 为单位管理文件内容,一个文件被分割成若干个Block当应用程序写文件时,每写完一个Block,HDFS就将其自动复制到另外两台机器上,保证每一个Block有三个副本,即便有两台服务器宕机,数据依然能够访问,至关于实现了RAID1的数据复制功能。

当对文件进行处理计算时,经过MapReduce并发计算任务框架,能够启动多个计算子任务(MapReduce Task)同时读取文件的多个Block,并发处理,至关于实现了RAID0的并发访问功能。

HDFS架构原理图

HDFS配合MapReduce等并行计算框架进行大数据处理时,能够在整个集群上并发读写访问全部的磁盘,无需RAID支持。

小结

网站性能优化技术是在网站性能遇到问题时的解决方案。而网站的性能问题不少是在用户高并发访问时产生的,因此网站性能优化的主要工做是改善高并发用户访问状况下的网站响应速度。

网站性能对最终用户而言是一种主观感觉,性能优化的最终目的就是改善用户的体验,使他们感受网站很快。

用户体验的快或是慢,能够经过技术手段改善,也能够经过优化交互体验改善。

相关文章
相关标签/搜索