大型网站技术架构

大型网站的技术挑战主要来自于庞大的用户,高并发的访问和海量的数据,任何简单的业务一旦需要处理数以PB计的数据和面对数以亿计的用户,问题就会变得很棘手。
大型网站架构主要就是解决这类问题。

这个世界没有哪个网站从诞生起就是大型网站;也没有哪个网站第一次发布就拥有庞大的用户,高并发的访问,海量的数据;大型网站都是从小型网站发展而来。网站的价值在于它能为用户提供什么价值,在于网站能做什么,而不在于它是怎么做的、所以在网站还很小的时候就去追求网站的架构是舍本逐末,得不偿失的。小型网站最需要做的就是为用户提供好的服务来创造价值,得到用户的认可,活下去,野蛮生长。

大型网站架构技术的核心价值不是从无到有搭建一个大型网站,而是能够伴随小型网站业务的逐步发展,慢慢地演化成一个大型网站。在这个漫长的技术演化过程中,不需要放弃什么,不需要推翻什么,不需要剧烈的革命,就那么润物细无声地把一个只有一台服务器,几百个用户的小网站演化成一个几十万台服务器,数十亿用户的大网站。今天我们看到的大型网站,Google,Facebook,Taobao,Baidu莫不遵循这样的技术演化路线。

网站技术是为业务而存在的,除此毫无意义。在技术选型和架构设计中,脱离网站业务发展的实际,一味追求时髦的新技术,可能会将网站技术发展引入崎岖小道,架构之路越走越难。

时至今日,大型网站的架构演化方案已经非常成熟,各种技术方案也逐渐产品化。
许多小型网站已经慢慢不需要再经历大型网站经历过的架构演化之路就可以逐步发展壮大,因为现在越来越多的网站从建立之初就是搭建在大型网站提供的云计算服务基础之上,所需要的一切技术资源:计算、存储、网络都可以按需购买,线性伸缩,不需要自己一点一点地拼凑各种资源,综合使用各种技术方案逐步去完善自己的网站架构了。所以能亲身经历一个网站从小到大的架构演化过程的网站架构师越来越少,虽然过去有这种经历的架构师也很少(从小型网站发展成大型网站的机会本来就极少),但是将来可能真就没有了。
但也正因为网站架构技术演化过程难以重现,所以网站架构师更应该对这个过程深刻了解,理解已成熟的网站架构技术方案的来龙去脉和历史渊源,在技术选型和架构决策时才能有的放矢,直击要害。

大型网站软件系统的特点

高并发,大流量 海量数据 用户分布广泛,网络情况复杂 安全环境恶劣 需求快速变更,发布频繁 渐进式发展

核心五要素:性能 可用性 伸缩性 扩展性 安全性

发展路径

哪一部分成为瓶颈了,就对那部分进行修正和提升

  • 在初始阶段,访问量并不大,所以应用程序、数据库、文件等所有的资源都在一台服务器上。
    随着网站业务的发展,一台服务器逐渐不能满足需求:越来越多的用户访问导致性能越来越差,越来越多的数据导致存储空间不足。这时就需要将应用和数据分离
    网站起步往往使用LAMP技术(Linux + Apache+MySQL+PHP),因为LAMP既便宜又简单,而且对付一个中小型网站绰绰有余。

  • 将应用服务器与数据(文件、数据库)服务器分离。三台服务器对硬件资源的要求各不相同:应用服务器需要更快的CPU,文件服务器需要更大的磁盘和带宽,数据库服务器需要更快速的磁盘和更大的内存。分离之后,三个服务器各司其职,也方便针对性的优化。

    网站的并发处理能力和存储空间得到了很大改善,而随着网站用户数增长,此时网站又一次面临挑战:数据库压力太大导致访问延迟,进而影响整个网站的性能

  • 设置缓存

    网站缓存分两种,本地缓存和远程缓存:本地缓存在应用服务器上受应用服务器内存限制,缓存数据量有限;远程缓存可以采用分布式集群的方式,部署大内存的服务器作为专门的缓存服务器(理论上不受内存容量限制)

    网站访问特点和现实世界的财富分配一样遵循二八定律:80%的业务访问集中在20%的数据上。淘宝买家浏览的商品集中在少部分成交数多、评价良好的商品上;百度搜索关键词集中在少部分热门词汇上;只有经常登录的用户才会发微博、看微博,而这部分用户也只占总用户数目的一小部分。
    既然大部分的业务访问集中在一小部分数据上,那么如果把这一小部分数据缓存在内存中,是不是就可以减少数据库的访问压力,提高整个网站的数据访问速度,改善数据库的写入性能了呢?

  • 应用服务器集群 – 可伸缩性
    使用缓存后,数据访问压力得到有效缓解,但是单一应用服务器能够处理的请求连接有限,在网站访问高峰期,应用服务器成为整个网站的瓶颈。
    不要企图更换更强大的服务器:对大型网站而言,不论多强大的服务器,都满足不了网站持续增长的业务需求。更恰当的做法是增加一台服务器以分担原有服务器的访问和存储压力。

    对网站架构而言,只要能通过增加一台服务器的方式改善负载压力,就可以以同样的方式持续增加服务器不断改善系统性能,从而实现系统的可伸缩性

    通过负载均衡来调度服务器集群。如果有更多的用户,就在集群中加入更多的应用服务器,使应用服务器的负载压力不再成为整个网站的瓶颈。

  • 数据库读写分离
    网站在使用缓存后,使绝大部分数据读操作访问都可以不通过数据库就能完成,但是仍有一部分读操作(缓存访问不命中、缓存过期)和全部的写操作需要访问数据库,在网站的用户达到一定规模后,数据库因为负载压力过高而成为网站的瓶颈。
    应用服务器在写数据的时候,访问主数据库,主数据库通过主从复制机制将数据更新同步到从数据库,这样当应用服务器读数据的时候,就可以通过从数据库获得数据。为了便于应用程序访问读写分离后的数据库,通常在应用服务器端使用专门的数据访向模块,使数据库读写分离对应用透明。

  • 加速网站响应:CDN和反向代理

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

    使用CDN和反向代理的目的都是尽早返回数据给用户,一方面加快用户访问速度,另一方面也减轻后端服务器的负载压力。

  • 分布式文件系统 分布式数据库
    和应用服务器类似,业务大规模增长情况下,文件系统和数据库的终极解决方案都是分布式系统。

    但是和应用服务器不同的是,对数据库使用分布式往往不会优先考虑。

分布式数据库是网站数据库拆分的最后手段,只有在单表数据规模非常庞大的时候才使用。不到不得已时,网站更常用的数据库拆分手段是业务分库,将不同业务的数据库部署在不同的物理服务器上。

  • 业务拆分 – 分治

    大型网站为了应对日益复杂的业务场景,通过使用分而治之的手段将整个网站业务分成不同的产品线,如大型购物交易网站就会将首页、商铺、订单、买家、卖家等拆分成不同的产品线,分归不同的业务团队负责。

  • 分布式服务
    数万台服务器规模的网站!所有应用要和所有数据库系统连接,连接数量是服务器规模的平方,这将导致数据库连接数资源不足,拒绝服务。

    既然每一个应用系统都需要执行许多相同的业务操作,比如用户管理、商品管理等,那么可以将这些共用的业务提取出来,独立部署。由这些可复用的业务连接数据库,提供共用业务服务,而应用系统只需要管理用户界面,通过分布式服务调用共用业务服务完成具体业务操作。

  • 云计算平台
    可以把这些解决方案应用到网站自身以外的业务上去。我们看到目前许多大型网站都开始建设云计算平台,将计算作为一种基础资源出售,中小网站不需要再关心技术架构问题,只需要按需付费,就可以使网站随着业务的增长逐渐获得更大的存储空间和更多的计算资源。

大型网站架构模式

模块化–分治算法的思想。

分层

分层是企业应用系统中最常见的一种架构模式,将系统在横向维度上切分成几个部分,每个部分负责一部分相对比较单一的职责,然后通过上层对下层的依赖和调用组成一个完整的系统。
分层结构在计算机世界中无处不在,网络的7层通信协议是一种分层结构;计算机硬件、操作系统、应用软件也可以看作是一种分层结构。在大型网站架构中也采用分层结构,将网站软件系统分为应用层、服务层、数据层,如表2.1所示。

分块

如果说分层是将软件在横向方面进行切分,那么分割就是在纵向方面对软件进行切分。
网站越大,功能越复杂,服务和数据处理的种类也越多,将这些不同的功能和服务分割开来,包装成高内聚低耦合的模块单元,一方面有助于软件的开发和维护;另一方面,便于不同模块的分布式部署,提高网站的并发处理能力和功能扩展能力。
大型网站分割的粒度可能会很小。比如在应用层,将不同业务进行分割,例如将购物、论坛、搜索、广告分割成不同的应用,由独立的团队负责,部署在不同的服务器上;在同一个应用内部,如果规模庞大业务复杂,会继续进行分割,比如购物业务,可以进一步分割成机票酒店业务、3C业务,小商品业务等更细小的粒度。而即使在这个粒度上.还是可以继续分割成首页、搜索列表、商品详情等模块,这些模块不管在逻辑上还是物理部署上,都可以是独立的。同样在服务层也可以根据需要将服务分割成合适的模块。

分布式

对于大型网站,分层和分割的一个主要目的是为了切分后的模块便于分布式部署,即将不同模块部署在不同的服务器上,通过远程调用协同工作。分布式意味着可以使用更多的计算机完成同样的功能,计算机越多,CPU、内存、存储资源也就越多,能够处理的并发访问和数据量就越大,进而能够为更多的用户提供服务。

分布式是非常难的: 但分布式在解决网站高并发问题的同时也带来了其他问题。首先,分布式意味着服务调用必须通过网络,这可能会对性能造成比较严重的影响;其次,服务器越多,服务器宕机的概率也就越大,一台服务器宕机造成的服务不可用可能会导致很多应用不可访问,使网站可用性降低;另外,数据在分布式的环境中保持数据一致性也非常困难,分布式事务也难以保证,这对网站业务正确性和业务流程有可能造成很大影响;分布式还导致网站依赖错综复杂,开发管理维护困难。因此分布式设计要根据具体情况量力而行

集群

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

访问量很小的分布式应用和服务,也至少要部署两台服务器构成一个小的集群,目的就是提高系统的可用性。

缓存

使用缓存有两个前提条件,一是数据访问热点不均衡,某些数据会被更频繁的访问,这些数据应该放在缓存中;二是数据在某个时间段内有效,不会很快过期,否则缓存的数据就会因已经失效而产生脏读,影响结果的正确性。网站应用中,缓存除了可以加快数据访问速度,还可以减轻后端应用和数据存储的负载压力,这一点对网站数据库架构至关重要,网站数据库几乎都是按照有缓存的前提进行负载能力设计的。

CDN 反向代理 本地缓存 分布式缓存

异步

在单一服务器内部可通过多线程共享内存队列的方式实现异步,处在业务操作前面的线程将输出写入到队列,后面的线程从队列中读取数据进行处理;在分布式系统中,多个服务器集群通过分布式消息队列实现异步,分布式消息队列可以看作内存队列的分布式部署。
异步架构是典型的生产者消费者模式,两者不存在直接调用,只要保持数据结构不变,彼此功能实现可以随意变化而不互相影响,这对网站扩展新功能非常便利。除此之外,使用异步消息队列还有如下特性。

  • 提高系统可用性。消费者服务器发生故障,数据会在消息队列服务器中存储堆积,生产者服务器可以继续处理业务请求,系统整体表现无故障。消费者服务器恢复正常后,继续处理消息队列中的数据。
  • 加快网站响应速度。处在业务处理前端的生产者服务器在处理完业务请求后,将数据写入消息队列,不需要等待消费者服务器处理就可以返回,响应延迟减少。
  • 消除并发访问高峰。用户访问网站是随机的,存在访问高峰和低谷,即使网站按照一般访问高峰进行规划和部署,也依然会出现突发事件,比如购物网站的促销活动,微博上的热点事件,都会造成网站并发访问突然增大,这可能会造成整个网站负载过重,响应延迟,严重时甚至会出现服务宕机的情况。使用消息队列将突然增加的访问请求数据放入消息队列中,等待消费者服务器依次处理,就不会对整个网站负载造成太大压力

但需要注意的是,使用异步方式处理业务可能会对用户体验、业务流程造成影响。需要网站产品设计方面的支持。

冗余

高可用性:服务器宕机时,服务仍然继续,数据不丢失。

数据库定期冷备份,主从复制热备份。多个容灾备份数据中心。

安全

互联网的开放特性使得其从诞生起就面对巨大的安全挑战,网站在安全架构方面也积累了许多模式:通过密码和手机校验码进行身份认证;登录、交易等操作需要对网络通信进行加密,网站服务器上存储的敏感数据如用户信息等也进行加密处理;为了防止机器人程序滥用网络资源攻击网站,网站使用验证码进行识别;对于常见的用于攻击网站的xss攻击、SQL注入、进行编码转换等相应处理;对于垃圾信息、敏感信息进行过滤;对交易转账等重要操作根据交易模式和交易信息进行风险控制。

实例:微博的系统架构

值得反复研究。2.1.9 P45

好的设计绝对不是模仿,不是生搬硬套某个模式,而是对问题深刻理解之上的创造与创新,即使是“微创新”,也是让人耳目一新的似曾相识。山寨与创新的最大区别不在于是否抄袭,是否模仿,而在于对问题和需求是否真正理解与把握。

缓存服务器和NoSQL的关系是什么? – 存在较大交集,但并不相互包含。缓存服务器往往使用分布式NoSQL来实现,但也存在其他方案,NoSQL常常用作分布式缓存服务器,但也存在其他用途。

网站优化

网站优化分为3大部分:前端性能优化,应用服务器性能优化和存储性能优化。

0. 缓存介绍

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

缓存把数据存储在相对较高访问速度的存储介质中供系统处理。两个作用:减少数据访问时间,减少计算时间(如果缓存的数据是计算得到的结果)。其本质是内存hash表键值对。

回顾网站架构演化历程,当网站遇到性能瓶颈时,第一个想到的解决方案就是使用缓存。在整个网站应用中,缓存几乎无所不在,既存在于浏览器,也存在于应用服务器和数据库服务器;既可以对数据缓存,也可以对文件缓存,还可以对页面片段缓存。合理使用缓存,对网站性能优化意义重大。

使用缓存有两个前提条件,一是数据访问热点不均衡,某些数据会被更频繁的访问,这些数据应该放在缓存中;二是数据在某个时间段内有效,不会很快过期,否则缓存的数据就会因已经失效而产生脏读,影响结果的正确性。网站应用中,缓存除了可以加快数据访问速度,还可以减轻后端应用和数据存储的负载压力,这一点对网站数据库架构至关重要,网站数据库几乎都是按照有缓存的前提进行负载能力设计的。

缓存主要用来存放那些读写比很高、很少变化的数据,如商品的类目信息,热门词的搜索列表信息,热门商品信息等。应用程序读取数据时,先到缓存中读取,如果读取不到或数据已失效,再访问数据库,并将数据写入缓存。

合理使用缓存

频繁修改的数据不使用缓存

如果缓存中保存的是频繁修改的数据,就会出现数据写入缓存后,应用还来不及读取缓存,数据就已失效的情形,徒增系统负担。一般说来,数据的读写比在2:1以上,即写入一次缓存,在数据更新前至少读取两次,缓存才有意义。实践中,这个读写比通常非常高,比如新浪微博的热门微博,缓存以后可能会被读取数百万次。

没有热点数据不使用缓存

网站数据访问通常遵循二八定律,即80%的访问落在20%的数据上,因此利用Hash表和内存的高速访问特性,将这20%的数据缓存起来,可很好地改善系统性能,提高数据读取速度,降低存储访问压力。如果数据不遵循二八定律,那么使用缓存将没有意义,只是徒占内存空间。

数据不一致/脏读

如卖家已经编辑了商品属性,但是需要过一段时间才能被买家看到。在互联网应用中,这种延迟通常是可以接受的,但是具体应用仍需慎重对待。还有一种策略是数据更新时立即更新缓存,不过这也会带来更多系统开销和事务一致性的问题。

缓存可用性 – 应对缓存雪崩

缓存承担了大部分数据访问的压力,数据库已经习惯了有缓存的日子,所以当缓存服务崩溃时,数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况被称作缓存雪崩,发生这种故障,甚至不能简单地重启缓存服务器和数据库服务器来恢复网站访问。

实践中,有的网站通过缓存热备等手段提高缓存可用性:当某台缓存服务器宕机时,将缓存访问切换到热备服务器上。但是这种设计显然有违缓存的初衷,缓存根本就不应该被当做一个可靠的数据源来使用。

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

缓存预热

缓存系统启动时就把热点数据加载好

缓存穿透

恶意攻击,持续请求一个不存在的数据。由于缓存没有保存该数据,请求将落到数据库上,造成数据库压力/崩溃。

应对:把不存在的数据也缓存起来,其value为null。

分布式缓存 memcached的设计

p70

通信协议tcp,序列化传输协议:基于文本,命令关键字 + 操作数 get

1. 前端优化

主要针对静态资源CSS,JavaScript,图片,静态网页。

浏览器优化

  • 减少http请求数量:合并。合并css,合并JavaScript,合并图片。

  • 浏览器缓存:设置HTTP头中Cache-Control和Expires的属。缓存CSS,JavaScript,图片。

  • 压缩:在服务端压缩,浏览器端解压缩,减少数据传输量。在服务器资源不足时需要权衡。

  • CSS在页面最上面,JavaScript在页面最下面!
    浏览器会在下载完全部Css之后才对整个页面进行渲染,因此最好的做法是将css放在页面最上面,让浏览器尽快下载css,JavaScript则相反,浏览器在加载JavaScript后立即执行,有可能会阻塞整个页面,造成页面显示缓慢,因此JavaScript最好放在页面最下面。但如果页面解析时就需要用到Javascript,这时放在底部就不合适了。

  • 避免请求静态资源时发送Cookie,减少Cookie传输的次数。

cdn

其本质是缓存。使用cdn把静态资源缓存到离用户较近的网络节点。

反向代理服务器缓存

其主要功能是服务端安全。

2. 后端优化

网站优化分为3大部分:前端性能优化,应用服务器性能优化和存储性能优化。

数据库优化


核心五要素:性能 可用性 伸缩性 扩展性 安全性

高可用性

硬件故障和软件升级是常态,如何在这两种情况下保证网站的可用性:数据和服务的冗余备份,失效转移。

集群管理

只要其架构形式为分布式的架构,就需要分布式的管理方法

位于应用层的服务器通常为了应对高,发的访问请求,会通过负载均衡设备将一组服务器组成一个集群共同对外提供服务,当负载均衡设备通过心跳检测等手段监控到某台应用服务器不可用时,就将其从集群列表中剔除,并将请求分发到集群中其他可用的服务器上,使整个集群保持可用,从而实现应用高可用。
位于服务层的服务器情况和应用层的服务器类似,也是通过集群方式实现高可用。

应用服务器的Session管理

应用服务器的状态分离: 无状态的应用服务器 + 有状态的Session服务器

应用服务器的高可用架构设计主要基于服务无状态这一特性,但是事实上,业务总是有状态的,在交易类的电子商务网站,需要有购物车记录用户的购买信息,用户每次购买请求都是向购物车中增加商品;在社交类的网站中,需要记录用户的当前登录状态、最新发布的消息及好友状态等,用户每次刷新页面都需要更新这些信息。
Web应用中将这些多次请求修改使用的上下文对象称作会话(Session),单机情况下,Session可由部署在服务器上的Web容器(如JBoss)管理。在使用负载均衡的集群环境中,由于负载均衡服务器可能会将请求分发到集群任何一台应用服务器上,所以保证每次请求依然能够获得正确的Session比单机时要复杂很多。

四种方案。

  1. 同步,每个应用服务器存全部session –- 小服务规模可用

  2. 负载均衡,根据客户端的IP地址,让其访问固定的服务器 – 可用性较差,宕机服务器中的session丢失

  3. 把Session转Cookie – 常用,小Session适用

  4. Session服务器集群 – 常用,应用服务器每次读写Session时,都访问Session服务器
    应用服务器的状态分离: 无状态的应用服务器 + 有状态的Session服务器

    对于有状态的Session服务器,一种比较简单的方法是利用分布式缓存、数据库等,在这些产品的基础上进行包装,使其符合Session的存储和访问要求。如果业务场景对Session管理有比较高的要求,比如利用Session服务集成单点登录(SSO)、用户服务等功能,则需要开发专门的Session服务管理平台。

其他高可用方案

  1. 分级管理
    核心应用和服务,优先使用更好的硬件。

  2. 超时设置
    在应用程序中设置服务调用的超时时间,一旦超时,通信框架就抛出异常,应用程序根据服务调度策略,可选择继续重试或将请求转移到提供相同服务的其他服务器上。

  3. 异步调用
    应用对服务的调用通过消息队列等异步方式完成,避免一个服务失败导致整个应用请求失败的情况。

    当然不是所有服务调用都可以异步调用,对于获取用户信息这类调用,采用异步方式会延长响应时间,得不偿失。对于那些必须确认服务调用成功才能继续下一步操作白应用也不合适使用异步调用。

  4. 服务降级
    访问高峰期,只保证核心应用和服务的正常运行。
    两种手段:拒绝服务 + 关闭功能

    拒绝服务:拒绝低优先级应用的调用,减少服务调用并发数,确保核心应用正常使用;或者随机拒绝部分请求调用,节约资源,让另一部分请求得以成功,避免要死大家一起死的惨剧。貌似Twittr比较喜欢使用随机拒绝请求的策略,经常有用户看到请求失败的故障页面,但是问下身边的人,其他人都正常使用,自己再刷新页面,也好了。
    关闭功能:关闭部分不重要的服务,或者服务内部关闭部分不重要的功能,以节约系统开销,为重要的服务和功能让出资源。淘宝在每年的“双十一”促销中就使用这种方法,在系统最繁忙的时段关闭“评价”、“确认收货”等非核心服务,以保证核心交易服务的顺利完成。

  5. 交易编号
    对于转账交易等操作,可能出现服务重复调用(应用服务器需要重试到成功为止,但可能出现虚假的失败),需要对其交易进行编号操作。

数据高可用

数据一致性

CAP原理:CAP原理认为,一个提供数据服务的存储系统无法同时满足数据一致性(Consistency)、数据可用性(Availibility)、分区耐受性(Patition Tolerance,系统具有跨网络分区的伸缩性)这三个条件。

对于大网站来说,伸缩性和可用性必不可少。大型网站中,通常会选择强化分布式存储系统的可用性(A)和伸缩性(P),而在某种程度上牺牲一定的一致性(C).

数据一致性的三种级别:

  • 数据强一致
    各个副本的数据在物理存储中总是一致的;数据更新操作结果和操作响应总是一致的,即操作响应通知更新失败,那么数据一定没有被更新,而不是处于不确定状态。(类似数据库的表锁,锁的串行状态)
  • 数据用户一致
    即数据在物理存储中的各个副本的数据可能是不一致的,但是终端用户访问时,通过纠错和校验机制,可以确定一个一致的且正确的数据返回给用户。
  • 数据最终一致
    这是数据一致性中较弱的一种,即物理存储的数据可能是不一致的,终端用户访问到的数据可能也是不一致的(同一用户连续访问,结果不同;或者不同用户同时访问.
    结果不同),但系统经过一段时间(通常是一个比较短的时间段)的自我恢复和修正,数据最终会达到一致。

因为难以满足数据强一致性,网站通常会综合成本、技术、业务场景等条件,结合应用服务和其他的数据监控与纠错功能,使存储系统达到用户一致,保证最终用户访问数据的正确性。

备份

冷备份,技术简单易操作,但是备份点之后的数据丢失,单使用冷备份可能丢失重要数据;实时网站需要在定期冷备份的基础上,进行热备份

热备份:异步、同步两种方案

关系数据库热备份:异步,Master - Slave同步机制。读写分离:写操作只访问Master数据库,读操作只访问Slave数据库

伸缩性

应用服务器 – 负载均衡

负载均衡是基础技术,可用于任意的无状态服务器集群

两层多叉树结构:第一层,DNS负载均衡指向一堆内部负载均衡服务器;第二层,由这些负载均衡服务器来指向实际的服务器。

分布式缓存服务器集群的扩容 – 一致性Hash算法

p127

使用余数hash,会在扩容时出现大规模缓存不能命中,导致数据库宕机!

一致性hash算法的hash环会引入负载不均衡问题。解决:添加一层虚拟层:加入新节点时,是将一组虚拟节点(150个)加入hash环中。

关系数据库的伸缩性

Cobar:添加负载均衡层 – 路由模块

Cobar被称为数据库中间件,常用于分库分表。MySQL主流中间件:Atlas,cobar(继承者MyCAT),TDDL等。

Cobar:

阿里巴巴B2B开发的关系型分布式系统,管理将近3000个MySQL实例。 在阿里经受住了考验,后面由于作者的走开的原因cobar没有人维护 了,阿里也开发了tddl替代cobar。

MyCAT:

社区爱好者在阿里cobar基础上进行二次开发,解决了cobar当时存 在的一些问题,并且加入了许多新的功能在其中。目前MyCAT社区活 跃度很高,目前已经有一些公司在使用MyCAT。

访问流程:

前端通信模块负责和应用程序通信,接收到SQL请求(select from users where useric in(12,22,23)后转交给SQL解析模块,SQL解析模块解析获得SQL中的路由规则查询条件(userid in(12,22,23)再转交给SQL路由模块,SQL路由模块根据路由规则配置userid为偶数路由至数据库A,userid为奇数路由至数据库B)将应用程序提交的SQL分解成两条SQL(selectfrom users where userid in(12,22);selectfrom users where userid in(23);)转交给SQL执行代理模块,发送至数据库A和数据库B分别执行。数据库A和数据库B的执行结果返回至SQL执行模块,通过结果合并模块将两个返回结果集合并成一个结果集,最终返回给应用程序,完成在分布式数据库中的一次访问请求。

Cobar的伸缩有两种:Cobar服务器集群的伸缩和MySQL服务器集群的伸缩。
Cobar服务器可以看作是无状态的应用服务器,因此其集群伸缩可以简单使用负载均衡的手段实现。而MySQL中存储着数据,要想保证集群扩容后数据一致负载均衡,必须要做数据迁移,将集群中原来机器中的数据迁移到新添加的机器中。(拆迁)

在路由模块使用一致性hash算法以决定具体迁移哪些数据(可使迁移量最少)。

使用MySQL的数据同步功能进行数据迁移,以Scheme为单位。

取舍:

相比关系数据库本身功能上的优雅强大,目前各类分布式关系数据库解决方案都显得非常简陋,限制了关系数据库某些功能的使用。但是当网站业务面临不停增长的海量业务数据存储压力时,又不得不利用分布式关系数据库的集群伸缩能力,这时就必须从业务上回避分布式关系数据库的各种缺点:避免事务或利用事务补偿机制代替数据库事务;分解数据访问逻辑避免JOIN操作等。

NoSQL的伸缩性

业界为了解决关系数据库的不足,提出了诸多方案,比较有名的是对象数据库,但是这些数据库的出现只是进一步证明关系数据库的优越而已。直到大型网站遇到了关系数据库难以克服的缺陷–糟糕的海量数据处理能力及僵硬的设计约束,局面才有所改善。为了解决上述问题,NoSQL这一概念被提了出来,以弥补关系数据库的不足。
NoSQL,主要指非关系的、分布式的数据库设计模式。也有许多专家将NosSQL解读为Not Only SQL.表示NoSQL只是关系数据库的补充,而不是替代方案。一般而言,NosQL数据库产品都放弃了关系数据库的两大重要基础:以关系代数为基础的结构化查询语言(SQL)和事务一致性保证(ACID),而强化其他一些大型网站更关注的特性:高可用性和可伸缩性。

可扩展性

如此轻易地就可以开发一个新产品,如此快速地就可以实现一个新功能,他们是如何做到的?

为什么有的网站必须规定系统发布日,一到发布日就如临大敌,整个技术部加班通宵达旦;而有的网站就可以随时发布,新功能可以随时快速上线。

这些都有赖于网站的扩展性架构设计,就是在对现有系统影响最小的情况下,系统功能可持续扩展及提升的能力

设计网站可扩展架构的核心思想模块化,并在此基础上,降低模块间的耦合性,提高模块的复用性。

扩展性(Extensibility)

keyword: 低耦合 开闭原则

指对现有系统影响最小的情况下,系统功能可持续扩展或提升的能力。表现在系统基础设施稳定不需要经常变更,应用之间较少依赖和耦合,对需求变更可以敏捷响应。它是系统架构设计层面的开闭原则(对扩展开放,对修改关闭),架构设计考虑未来功能扩展,当系统增加新功能时,不需要对现有系统的结构和代码进行修改。

笔者认为,软件架构师最大的价值不在于掌握多少先进的技术,而在于具有将一个大系统切分成N个低耦合的子模块的能力。

伸缩性容易和扩展性混淆,一并描述。

伸缩性(Scalability)

keyword: 集群,热插拔

指系统能够通过增加(减少)自身资源规模的方式增强(减少)自己计算处理事务的能力。如果这种增减是成比例的,就被称作线性伸缩性。在网站架构中,通常指利用集群的方式增加服务器数量、提高系统的整体事务吞吐能力。

消息队列

其本质是利用生产者消费者设计模式对通信双方进行解耦合。

事件驱动架构(Event Driven Architecture):通过在低耦合的模块之间传输事件消息,以保持模块的松散耦合,并借助事件消息的通信完成模块间合作,典型的EDA架构就是操作系统中常见的生产者消费者模式。在大型网站架构中,具体实现手段有很多,最常用的是分布式消息队列。

发布 - 订阅模式,消息发送者将消息发送至分布式消息队列即结束对消息的处理,而消息接受者只需要从分布式消息队列获取消息后进行处理,不需要知道该消息从何而来。对新增业务,只要对该类消息感兴趣,即可订阅该消息,对原系统和业务没有任何影响。

由于消息发送者不需要等待消息接受者处理数据就可以返回,系统具有更好的响应延迟;同时,在网站访问高峰,消息可以暂时存储在消息队列中等待消息接受者根据自身负载处理能力控制消息处理速度,减轻数据库等后端存储的负载压力。

阿里巴巴开源框架,Dubbo --生产者消费者模式,NIO。服务自动注册与发现。

消息队列 命名格式为xx - MQ的产品

安全性

XSS攻击

JavaScript脚本,通过输入转义进行跳转执行脚本窃取Cookie等信息

防御

消毒

用户输入不可信,限制转义字符的使用,关闭不使用的,常用的严格限制匹配再转义

HttpOnly

浏览器禁止页面JavaScript访问带有HttpOnly属性的Cookie。对Cookie添加HttpOnly属性,避免被攻击脚本窃取

注入攻击

防御

消毒

和防XSS攻击一样,请求参数消毒是一种比较简单粗暴又有效的手段。通过正则匹配,过滤请求数据中可能注入的SQL,如"drop table"、"b(?:updateb.*?bset Ideletebiw?bfrom)b"等。

参数绑定

使用预编译手段,绑定参数是最好的防SQL注入方法。目前许多数据访问层框架。如IBatis,Hibernate等,都实现SQL预编译和参数绑定,攻击者的恶意SQL会被当做SQL的参数,而不是SQL命令被执行。
除了SQL注入,攻击者还根据具体应用,注入Os命令、编程语言代码等,利用程序漏洞,达到攻击目的。

CSRF攻击

CSRF(Cross Site Request Forgery,跨站点请求伪造),攻击者通过跨站请求,以合法用户的身份进行非法操作,如转账交易、发表评论等,如图8.4所示。CSRF的主要手法是利用跨站请求,在用户不知情的情况下,以用户的身份伪造请求。其核心是利用了浏览器Cookie或服务器Session策略,盗取用户身份。

其防御手段主要是识别用户身份。

《大型网站技术架构》学习笔记相关推荐

  1. 第二行代码学习笔记——第六章:数据储存全方案——详解持久化技术

    本章要点 任何一个应用程序,总是不停的和数据打交道. 瞬时数据:指储存在内存当中,有可能因为程序关闭或其他原因导致内存被回收而丢失的数据. 数据持久化技术,为了解决关键性数据的丢失. 6.1 持久化技 ...

  2. 第一行代码学习笔记第二章——探究活动

    知识点目录 2.1 活动是什么 2.2 活动的基本用法 2.2.1 手动创建活动 2.2.2 创建和加载布局 2.2.3 在AndroidManifest文件中注册 2.2.4 在活动中使用Toast ...

  3. 第一行代码学习笔记第八章——运用手机多媒体

    知识点目录 8.1 将程序运行到手机上 8.2 使用通知 * 8.2.1 通知的基本使用 * 8.2.2 通知的进阶技巧 * 8.2.3 通知的高级功能 8.3 调用摄像头和相册 * 8.3.1 调用 ...

  4. 第一行代码学习笔记第六章——详解持久化技术

    知识点目录 6.1 持久化技术简介 6.2 文件存储 * 6.2.1 将数据存储到文件中 * 6.2.2 从文件中读取数据 6.3 SharedPreferences存储 * 6.3.1 将数据存储到 ...

  5. 第一行代码学习笔记第三章——UI开发的点点滴滴

    知识点目录 3.1 如何编写程序界面 3.2 常用控件的使用方法 * 3.2.1 TextView * 3.2.2 Button * 3.2.3 EditText * 3.2.4 ImageView ...

  6. 第一行代码学习笔记第十章——探究服务

    知识点目录 10.1 服务是什么 10.2 Android多线程编程 * 10.2.1 线程的基本用法 * 10.2.2 在子线程中更新UI * 10.2.3 解析异步消息处理机制 * 10.2.4 ...

  7. 第一行代码学习笔记第七章——探究内容提供器

    知识点目录 7.1 内容提供器简介 7.2 运行权限 * 7.2.1 Android权限机制详解 * 7.2.2 在程序运行时申请权限 7.3 访问其他程序中的数据 * 7.3.1 ContentRe ...

  8. 第一行代码学习笔记第五章——详解广播机制

    知识点目录 5.1 广播机制 5.2 接收系统广播 * 5.2.1 动态注册监听网络变化 * 5.2.2 静态注册实现开机广播 5.3 发送自定义广播 * 5.3.1 发送标准广播 * 5.3.2 发 ...

  9. 第一行代码学习笔记第九章——使用网络技术

    知识点目录 9.1 WebView的用法 9.2 使用HTTP协议访问网络 * 9.2.1 使用HttpURLConnection * 9.2.2 使用OkHttp 9.3 解析XML格式数据 * 9 ...

  10. 安卓教程----第一行代码学习笔记

    安卓概述 系统架构 Linux内核层,还包括各种底层驱动,如相机驱动.电源驱动等 系统运行库层,包含一些c/c++的库,如浏览器内核webkit.SQLlite.3D绘图openGL.用于java运行 ...

最新文章

  1. 使用ASP.NET操作IIS7中使用应用程序
  2. 解决navicat 导出excel数字为科学计数法问题
  3. IT-标准化-系列-6.关闭事件跟踪程序
  4. c++中有表示正无穷的数吗_简单的数
  5. ant 路径_在Ant中显示路径
  6. django学习随笔:ManagementUtility
  7. 解决办法:一切都正确,Python3执行PyImport_Import()一直返回NULL
  8. 计算机套题库c版,计算机二级C语言上机题库100套(最新版)
  9. 视频教程-CCNA视频----从零开始学CCNA实验视频课程(加强版)-思科认证
  10. latex 编译缺少STXingkai字体
  11. java取万位的值,excel表格数值如何取万位整数,来研究下吧
  12. VBox 快照备份虚拟机
  13. 细数银行7大手续费 这些冤枉钱别再交了
  14. 图像处理的数学模型与高性能算法——介绍
  15. 5月10日云栖精选夜读:阿里专家直击前端盛会JSConf2017 Day2:见证Moment.js精彩分享...
  16. 使用SQLite的感想
  17. [Previous line repeated 995 more times]RecursionError: maximum recursion depth exceeded
  18. 修复登录接口仿抽奖助手微信小程序源码下载
  19. 安卓手机投屏软件_手机投屏软件,居然支持所有网址......
  20. 日语星期的来历和快速记忆法

热门文章

  1. 计算机专业职业规划范文800字,计算机专业学生职业生涯规划书
  2. 云时代操作系统路在何方?麒麟信安的踏雪寻梅之道
  3. ArcGIS教程:按单个值进行重分类
  4. DSP入门必看(非常好的DSP扫盲文章)
  5. Python制作某电商平台商品竞拍脚本,能自动定时、抢拍、购买
  6. linux安装RarLinux
  7. JUnit 单元测试多线程测试解决方法
  8. Hownbsp;tonbsp;Modifynbsp;anbsp;ATInbsp;Switchablenbsp;G…
  9. w ndows7安不上HP1020,1020打印机驱动
  10. onlyoffice毕升office