您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
大规模分布式应用之海量数据和高并发解决方案
 
作者昵称:手撕代码
  2513  次浏览      17
 2020-11-17
 
编辑推荐:
本文主要整理了一些针对海量数据和高并发情况下的解决方案 ,希望对您的学习有所帮助。
来自于CSDN,由火龙果软件Alice编辑、推荐。

一、网站应用背景

开发一个网站的应用程序,当用户规模比较小的时候,使用简单的:一台应用服务器+一台数据库服务器+一台文件服务器,这样的话完全可以解决一部分问题,也可以通过堆硬件的方式来提高网站应用的访问性能,当然,也要考虑成本的问题。

当问题的规模在经济条件下通过堆硬件的方式解决不了的时候,我们应该通过其他的思路去解决问题,互联网发展至今,已经提供了很多成熟的解决方案,但并不是都具有适用性,你把淘宝的技术全部都搬过来也不一定达到现在淘宝的水平,道理很简单。

当然,很多文章都在强调,一个网站的发展水平,是逐渐的演变过来的,并不是一朝一夕的事情。虽然目前的情况互联网的泡沫越来越大,但是整个互联网技术的发展确实为我们提供了方便快捷的上网体验。下边是一张早期的淘宝官网的界面:

二、针对海量数据和高并发的主要解决方案

海量数据的解决方案:

1.使用缓存;

2.页面静态化技术;

3.数据库优化;

4.分离数据库中活跃的数据;

5.批量读取和延迟修改;

6.读写分离;

7.使用NoSQL和Hadoop等技术;

8.分布式部署数据库;

9.应用服务和数据服务分离;

10.使用搜索引擎搜索数据库中的数据;

11.进行业务的拆分;

高并发情况下的解决方案:

1.应用程序和静态资源文件进行分离;

2.页面缓存;

3.集群与分布式;

4.反向代理;

5.CDN;

三、海量数据的解决方案

(1)使用缓存

网站访问数据的特点大多数呈现为“二八定律”:80%的业务访问集中在20%的数据上。

例如:在某一段时间内百度的搜索热词可能集中在少部分的热门词汇上;新浪微博某一时期也可能大家广泛关注的主题也是少部分事件。

总的来说就是用户只用到了总数据条目的一小部分,当网站发展到一定规模,数据库IO操作成为性能瓶颈的时候,使用缓存将这一小部分的热门数据缓存在内存中是一个很不错的选择,不但可以减轻数据库的压力,还可以提高整体网站的数据访问速度。

使用缓存的方式可以通过程序代码将数据直接保存到内存中,例如通过使用Map或者ConcurrentHashMap;另一种,就是使用缓存框架:Redis、Ehcache、Memcache等。

使用缓存框架的时候,我们需要关心的就是什么时候创建缓存和缓存失效策略。

缓存的创建可以通过很多的方式进行创建,具体也需要根据自己的业务进行选择。例如,新闻首页的新闻应该在第一次读取数据的时候就进行缓存;对于点击率比较高的文章,可以将其文章内容进行缓存等。

内存资源有限,选择如何创建缓存是一个值得思考的问题。另外,对于缓存的失效机制也是需要好好研究的,可以通过设置失效时间的方式进行设置;也可以通过对热门数据设置优先级,根据不同的优先级设置不同的失效时间等;

需要注意的是,当我们删除一条数据的时候,我们要考虑到删除该条缓存,还要考虑在删除该条缓存之前该条数据是否已经到达缓存失效时间等各种情况!

使用缓存的时候还要考虑到缓存服务器发生故障时候如何进行容错处理,是使用N多台服务器缓存相同的数据,通过分布式部署的方式对缓存数据进行控制,当一台发生故障的时候自动切换到其他的机器上去;还是通过Hash一致性的方式,等待缓存服务器恢复正常使用的时候重新指定到该缓存服务器。Hash一致性的另一个作用就是在分布式缓存服务器下对数据进行定位,将数据分布在不用缓存服务器上。关于数据缓存的Hash一致性也是一个比较打的问题,这里只能大致描述一下,关于Hash一致性的了解。

(2)页面静态化技术

使用传统的JSP界面,前端界面的显示是通过后台服务器进行渲染后返回给前端游览器进行解析执行,如下图:

当然,现在提倡前后端分离,前端界面基本都是HTML网页代码,通过Angular JS或者NodeJS提供的路由向后端服务器发出请求获取数据,然后在游览器对数据进行渲染,这样在很大程度上降低了后端服务器的压力。

还可以将这些静态的HTML、CSS、JS、图片资源等放置在缓存服务器上或者CDN服务器上,一般使用最多的应该是CDN服务器或者Nginx服务器提供的静态资源功能。

另外,在《高性能网站建设进阶指南-Web开发者性能优化最佳实践(口碑网前端团队 翻译)》这本书中,对网站性能的前端界面提供了一些很宝贵的经验,如下:

因此,在这些静态资源的处理上,选择正确的处理方式还是对整体网站性能还是有很大帮助的!

(3)数据库优化

数据库优化是整个网站性能优化的最基础的一个环节,因为,大多数网站性能的瓶颈都是开在数据库IO操作上,虽然提供了缓存技术,但是对数据库的优化还是一个需要认真的对待。一般公司都有自己的DBA团队,负责数据库的创建,数据模型的确立等问题,不像我们现在几个不懂数据库优化的人只能在网上找一篇篇数据库优化的文章,自己去摸索,并没有形成一个系统的数据库优化思路。

对于数据库的优化来说,是一种用技术换金钱的方式。数据库优化的方式很多,常见的可以分为:数据库表结构优化、SQL语句优化、分区、分表、索引优化、使用存储过程代替直接操作等 。

1、表结构优化

对于数据库的 开发规范与使用技巧以及设计和优化,前边的时候总结了一些文章,这里偷个懒直接放地址,有需要的可以移步看一下:

a) MySQL开发规范与使用技巧总结:http://blog.csdn.net/xlgen157387/article/details/48086607

b) 在一个千万级的数据库查寻中,如何提高查询效率http://blog.csdn.net/xlgen157387/article/details/44156679

另外,再设计数据库表的时候需不需要创建外键,使用外键的好处之一可以方便的进行级联删除操作,但是现在在进行数据业务操作的时候,我们都通过事物的方式来保证数据读取操作的一致性,我感觉相比于使用外键关联MySQL自动帮我们完成级联删除的操作来说,还是自己使用事物进行删除操作来的更放心一些。当然可能也是有适用的场景,大家如有很好的建议,欢迎留言!

2、SQL优化

对于SQL的优化,主要是针对SQL语句处理逻辑的优化,而且还要根据索引进行配合使用。另外,对于SQL语句的优化我们可以针对具体的业务方法进行优化,我们可以将执行业务逻辑操作的数据库执行时间记录下来,来进行有针对性的优化,这样的话效果还是很不错的!例如下图,展示了一条数据库操作执行调用的时间:

关于SQL优化的一些建议,以前整理了一些,还请移步查看:

a) 19个MySQL性能优化要点解析:http://blog.csdn.net/xlgen157387/article/details/50735269

b) MySQL批量SQL插入各种性能优化:http://blog.csdn.net/xlgen157387/article/details/50949930

分表

分表是将一个大表按照一定的规则分解成多张具有独立存储空间的实体表,我们可以称为子表,每个表都对应三个文件,MYD数据文件,.MYI索引文件,.frm表结构文件。这些子表可以分布在同一块磁盘上,也可以在不同的机器上。数据库读写操作的时候根据事先定义好的规则得到对应的子表名,然后去操作它。

例如:用户表

用户的角色有很多种,可以通过枚举类型的方式将用户分为不同类别category:学生、教师、企业等 ,这样的话,我们就可以根据类别category来对数据库进行分表,这样的话每次查询的时候现根据用户的类型锁定一个较小的范围。

不过分表之后,如果需要查询完整的顺序就需要使用多表操作了。

分区

数据库分区是一种物理数据库设计技术,DBA和数据库建模人员对其相当熟悉。虽然分区技术可以实现很多效果,但其主要目的是为了在特定的SQL操作中减少数据读写的总量以缩减响应时间。

分区和分表相似,都是按照规则分解表。不同在于分表将大表分解为若干个独立的实体表,而分区是将数据分段划分在多个位置存放,可以是同一块磁盘也可以在不同的机器。分区后,表面上还是一张表,但数据散列到多个位置了。数据库读写操作的时候操作的还是大表名字,DMS自动去组织分区的数据。

当一张表中的数据变得很大的时候,读取数据,查询数据的效率非常低下,很容易的就是讲数据分到不同的数据表中进行保存,但是这样分表之后会使得操作起来比较麻烦,因为,将同类的数据分别放在不同的表中的话,在搜索数据的时候需要便利查询这些表中的数据。想进行CRUD操作还需要先找到对应的所有表,如果涉及到不同的表的话还要进行跨表操作,这样操作起来还是很麻烦的。

使用分区的方式可以解决这个问题,分区是将一张表中的数据按照一定的规则分到不同的区中进行保存,这样进行数据查询的时候如果数据的范围在同一个区域内那么就可以支队一个区中的数据进行操作,这样的话操作起来数据量更少,操作速度更快,而且该方法是对程序透明的,程序不需要进行任何的修改。

索引优化

索引的大致原理是在数据发生变化的时候就预先按指定字段的顺序排列后保存到一个类似表的结构中,这样在查找索引字段为条件记录时就可以很快地从索引中找到对应记录的指针并从表中获取到相应的数据,这样速度是很快地。

不过,虽然查询的效率大大提高了,但是在进行增删改的时候,因为数据的变化都需要更新相应的索引,也是一种资源的浪费。

关于使用索引的问题,对待不同的问题,还是需要进行不同的讨论,根据具体的业务需求选择合适的索引对性能的提高效果是很明显的一个举措!

推荐文章阅读:

a) 数据库索引的作用和优点缺点以及索引的11中用法:http://blog.csdn.net/xlgen157387/article/details/45030829

b) 数据库索引原理:http://blog.csdn.net/kennyrose/article/details/7532032

使用存储过程代替直接操作

存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。

在操作过程比较复杂并且调用频率比较高的业务中,可以将编写好的sql语句用存储过程的方式来代替,使用存储过程只需要进行一次变异,而且可以在一个存储过程里做一些复杂的操作。

(4)分离数据库中活跃的数据

正如前边提到的“二八定律”一样,网站的数据虽然很多,但是经常被访问的数据还是有限的,因此可以讲这些相对活跃的数据进行分离出来单独进行保存来提高处理效率。

其实前边使用缓存的思想就是一个很明显的分离数据库中活跃的数据的使用案例,将热门数据缓存在内存中。

还有一种场景就是,例如一个网站的所用注册用户量很大千万级别,但是经常登录的用户只有百万级别,剩下的基本都是很长时间都没有进行登录操作,如果不把这些“僵尸用户”单独分离出去,那么我们每次查询其他登录用户的时候,就白白浪费了这些僵尸用户的查询操作。

(5)批量读取和延迟修改

批量读取和延迟修改的原理是通过减少操作数据库的操作来提高效率。

批量读取是将多次查询合并到一次中进行读取,因为每一个数据库的请求操作都需要链接的建立和链接的释放,还是占用一部分资源的,批量读取可以通过异步的方式进行读取。

延迟修改是对于一些高并发的并且修改频繁修改的数据,在每次修改的时候首先将数据保存到缓存中,然后定时将缓存中的数据保存到数据库中,程序可以在读取数据时可以同时读取数据库中和缓存中的数据。

例如:我现在在编写这份博客,我一开始写了一写内容然后点击发布了,在次回到Markdown进行修改操作,我有一个习惯,没写一些东西总是按一下上边的 “保存”按钮,然后我在另一个页面打开这篇博客查看,我的修改已经被更新,但是我还在 编辑!

不知道CSDN的技术是不是在我没有点击发布之前,这些数据都是先放到缓存里边的。

(6) 读写分离

读写分离的实质是将应用程序对数据库的读写操作分配到多个数据库服务器上,从而降低单台数据库的访问压力。

读写分离一般通过配置主从数据库的方式,数据的读取来自从库,对数据库增加修改删除操作主库。

相关文章请移步观看:

a) MySQL5.6 数据库主从(Master/Slave)同步安装与配置详解:http://blog.csdn.net/xlgen157387/article/details/51331244

b) MySQL主从复制的常见拓扑、原理分析以及如何提高主从复制的效率总结:http://blog.csdn.net/xlgen157387/article/details/52451613

(7)使用NoSQL和Hadoop等技术

NoSQL是一种非结构化的非关系型数据库,由于其灵活性,突破了关系型数据库的条条框框,可以灵活的进行操作,另外,因为NoSQL通过多个块存储数据的特点,其操作大数据的速度也是相当快的。

(8)分布式部署数据库

任何强大的单一服务器都满足不了大型网站持续增长的业务需求。数据库通过读写分离之后将一台数据库服务器拆分为两台或者多台数据库服务器,但是仍然满足不了持续增长的业务需求。分布式部署数据库是将网站数据库拆分的最后手段,只有在单表数据规模非常庞大的时候才使用。

分布式部署数据库是一种很理想的情况,分布式数据库是将表存放在不同的数据库中然后再放到不同的数据库中,这样在处理请求的时候,如果需要调用多个表,则可以让多台服务器同时处理,从而提高处理效率。

分布式数据库简单的架构图如下:

(9)应用服务和数据服务分离

应用服务器和数据库服务器进行分离的目的是为了根据应用服务器的特点和数据库服务器的特点进行底层的优化,这样的话能够更好的发挥每一台服务器的特性,数据库服务器当然是有一定的磁盘空间,而应用服务器相对不需要太大的磁盘空间,这样的话进行分离是有好处的,也能防止一台服务器出现问题连带的其他服务也不可以使用。

(10)使用搜索引擎搜索数据库中的数据

使用搜索引擎这种非数据库查询技术对网站应用的可伸缩分布式特性具有更好的支持。

常见的搜索引擎如Solr通过一种反向索引的方式,维护关键字到文档的映射关系,类似于我们使用《新华字典》进行搜索一个关键字,首先应该是看字典的目录进行查找然后定位到具体的位置。

搜索引擎通过维护一定的关键字到文档的映射关系,能够快速的定位到需要查找的数据,相比于传统的数据库搜索的方式,效率还是很高的。

目前一种比较火的ELK stack技术,还是值得学习的。

一篇关于Solr与MySQL查询性能对比文章

Solr与MySQL查询性能对比

(11) 进行业务的拆分

为什么进行业务的拆分,归根结底上还是使用的还是讲不通的业务数据表部署到不用的服务器上,分别查找对应的数据以满足网站的需求。各个应用之间用过指定的URL连接获取不同的服务,

例如一个大型的购物网站就会将首页、商铺、订单、买家、卖家等拆分为不通的子业务,一方面将业务模块分归为不同的团队进行开发,另外一方面不同的业务使用的数据库表部署到不通的服务器上,体现到拆分的思想,当一个业务模块使用的数据库服务器发生故障也不会影响其他业务模块的数据库正常使用。另外,当其中一个模块的访问量激增的时候还可以动态的扩展这个模块使用到的数据库的数量从而满足业务的需求。

四、高并发情况下的解决方案

(1)应用程序和静态资源文件进行分离

所谓的静态资源就是我们网站中用到的Html、Css、Js、Image、Video、Gif等静态资源。应用程序和静态资源文件进行分离也是常见的前后端分离的解决方案,应用服务只提供相应的数据服务,静态资源部署在指定的服务器上(Nginx服务器或者是CDN服务器上),前端界面通过Angular JS或者Node JS提供的路由技术访问应用服务器的具体服务获取相应的数据在前端游览器上进行渲染。这样可以在很大程度上减轻后端服务器的压力。

例如,百度主页使用的图片就是单独的一个域名服务器上进行部署的

(2)页面缓存

页面缓存是将应用生成的很少发生数据变化的页面缓存起来,这样就不需要每次都重新生成页面了,从而节省大量CPU资源,如果将缓存的页面放到内存中速度就更快。

可以使用Nginx提供的缓存功能,或者可以使用专门的页面缓存服务器Squid。

(3)集群与分布式

(4)反向代理

参考文章

(5)CDN

CDN服务器其实是一种集群页面缓存服务器,其目的就是尽早的返回用户所需要的数据,一方面加速用户访问速度,另一方面也减轻后端服务器的负载压力。

CDN的全称是Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。

CDN通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。

也就是说CDN服务器是部署在网络运行商的机房,提供的离用户最近的一层数据访问服务,用户在请求网站服务的时候,可以从距离用户最近的网络提供商机房获取数据。电信的用户会分配电信的节点,联通的会分配联通的节点。

CDN分配请求的方式是特殊的,不是普通的负载均衡服务器来分配的那种,而是用专门的CDN域名解析服务器在解析与名的时候就分配好的。

CDN结构图如下所示:

五、总结

文章提到的几点并没有详细的介绍,如需要对其中的一种方式进行研究,可以自行去找资源学习研究,这里只起到抛砖引玉的作用。当然对于大型网站应用之海量数据和高并发解决方案不局限于这些技巧或技术,还有很多成熟的解决方案,有需要的可以自行了解。

特此说明:本文的配图来自《网站架构及其演变过程–韩路彪》,多谢原作者提供的精美配图,并且文章的结构大致也参考了作者的思路,只不过内容是自己的一些经验和学习到的东西进行整理的。

现在无论是企业的业务系统还是互联网上的网站程序都面临着数据量大的问题,这个问题如果解决不好将严重的影响系统的运行速度,下面就针对这个问题的各种解决解决方案进行介绍。

1. 缓存和页面静态化

1.1 缓存

数据量大这个问题最直接的解决方案就是使用缓存,缓存就是将数据库中获取的结果暂时保存起来在,在下次使用的时候无需从数据库中提取,这样可以大大降低数据库压力。常用的缓存框架有Ehcache、Memcache 和 Redis等。

不过缓存也不是什么情况都适用,它主要用于数据变化不是很频繁的情况。而且如果是定期失效(数据修改时不失效)的失效机制,实时性要求也不能太高,因为这样缓存中的数据和真实数据可能会不一致。

2.1 页面静态化

页面静态化是将程序最后生成的页面保存起来,以后就不用每次都调用重新生成页面了。页面静态化同时对数据量大和并发量高两大问题都有好处。

页面静态化可以在程序中使用模版技术生成,如常用的Freemarker 和 Velocity 都可以根据模版生成静态页面。另外也可以使用缓存服务器在应用服务器的上一层生成页面,如可以使用Squid,另外Nginx 也提供了响应的功能。

2. 数据库优化

要解决数据量大的问题,是避不开数据库优化的。数据库优化是不增加硬件的情况下提高处理效率,是一种用技术换金钱的方式。以下是常用的数据库优化方法。

2.1 表结构优化

表结构优化是数据库中最基础也是最重要的,如果表结构优化得不合理,就可能导致严重的性能问题,具体怎么设计更合理也没有固定不变的准则,需要根据实际情况具体处理。

2.2 SQL 语句优化

sql语句优化也是非常重要的,基础的sql 优化是语法层面的优化,不过更重要的是处理逻辑的优化,这也需要根据实际情况具体处理,而且要和索引缓存等配合食用。sql 优化有一个通用的做法就是,首先要将涉及大数据业务的sql 语句,通过仔细分析日志信息,和不同条件的执行时间,找出需要优化的语句和其中的问题,然后再有的放矢地优化。而不是不分重点的对每条语句都花同样的事件和精力优化。

2.3 分区

当一张表中的数据量变多的时候操作速度就变慢了,容易想到的解决方法就是分表,但是分表操作起来就比较麻烦。其实在常用数据库中可以不分表而达到跟分表类似的效果,那就是分区。

分区就是将一张表中的数据按照一定的规则分到不同的区进行保存,在查询数据时如果范围在同一个区内哪么可以只对一个区的数据进行操作。这样操作的数据量更少,速度更快。

2.4 分表

如果一张表中的数据可以分为几种固定不变的类型,而且如果同时对多种类型共同操作的情况不多,哪么都可以通过分表来处理。

分表方法分为两种,横切 和纵切。

横切:

假设数据库表中的数据有三个状态,处理、解决、关闭。由于数据量非常的大所以就可以将数据分别存在三个表中。第一个表中保存处理状态的数据,第二个表保存 解决状态的数据,第三个表保存关闭状态的数据,并且对每个表进行分区。由于报表一般都是按月份、季度、半年、和年来做的,所以分区也按月份,每一个月做一个分区。这样就可以大大的提高处理和统计速度哦

竖切:

如果一个表的操作频率很高们在增删改其中一部分字段数据的同时另一部分字段也可能被操作,而且(主要指查询)用不到被增删改的字段,哪么就可以吧不同类型的地段分别保存到不同的表中,这样可以减少操作时锁定数据的范围。不过这样分表后需要查询完整数据就得多表操作了。

2.5 索引优化

索引的大致原理是在数据发生变化(增删改)的时候就预先指定字段排序后保存到一个类似表的结构中,这样在查询索引字段为条件的记录时就可以很快的从索引中找到对应记录的指针并从表中获取到记录,这样速度就快多了。不过索引也是一把双刃剑,它在提高查询速度的同时也降低了增删改查的速度,因为每次数据的表话都需要更新相应的索引。

2.6 使用存储过程代替操作

在操作过程复杂而且调用频率高的业务中,可以通过使用存储过程代替直接操作来提高效率,因为存储过程主需要编译一次,而且可以在一个存储过程里面做一些复杂的操作。

3. 分离活跃数据

有些数据总数据量非常大,但是活跃数据并不多,这种情况就可以将活跃数据单独保存起来从而提高处理效率。

比如说网站的用户,将经常登录的一部分活跃用户信息存在一张表,将不活跃的用户存在另外一张表。(可以跑一个定时任务将不经常登录的用户转移到不活跃用户表)当用户登录时先从活跃用户的表中查询。查询不到后再去不活跃用户的表中查询。这样就可以提高查询的效率。

4. 批量读取和延迟修改

批量读取和延迟修改的原理是通过减少操作的次数来提高效率,如果使用的恰当,效率将呈数量级提升。

批量读取是将多次的查询合并到一次中进行。

延迟修改主要针对高并发而且频繁修改(包括新增)的数据,如一些统计数据。可以先将需要修改的数据暂时保存到缓存中,然后定时将缓存中的数据保存到数据库中,程序读取数据可以同时读取数据库中的数据和缓存的数据。(这种方式下如果保存缓存的机器出现了故障可能会丢失数据。)所以如果是重要数据就需要做一些特殊处理。

5. 读写分离

读写分离的本质是对数据库进行集群,这样就可以在高并发的情况下将数据库的操作分配到多个数据库服务器去处理从而降低了单台服务器的压力。不过由于数据库的特殊性--每台服务器所保存的数据都需要一致,所以数据同步就成了数据库集群中最核心的问题了。

一般的解决方案是:将写操作交给专门的一台服务器,这台专门负责写操作的服务器叫做主服务器。当主服务器写入(增删改)数据后从底层同步到别的服务器(从服务器),读取数据的时候到从服务器读取,从服务器可以有多台,这样就可以实现读写分离了。并且将请求分配到多个服务器处理。如果从服务器太多,主服务器同步数据时,先同步到一部分从服务器,同步过数据的从服务器再将数据同步到另外一部分没有同步数据的从服务器。

简单的数据同步方式可以采用数据库的热备份功能,不过读取到的数据可能会存在一定的滞后性。既然是集群就会涉及到负载均衡问题,负载均衡和读写分离操作一般采用专门的程序处理,而且对应用系统来说是透明的。

6. 分布式数据库

分布式数据库是将不同的表放到不同的数据库中然后放到不同的服务器。这样需要调用多个表,则可以让多台服务器同时处理,从而提高处理速度。

分布式数据库是解决单个请求本身就非常复杂的问题,它可以将单个请求分配到多个服务器,使用分布式后的每个节点还可以同时使用读写分离,从来组成多个节群。

使用分布式数据库有很多的问题需要解决,如分布式事务处理、多表查询等。

分布式的另外一种使用思路是将不同的业务数据表保存到不同的节点,让不同的业务调用不同的数据库,这样的做法其实就是和集群一样起分流作用,不过这种做法就不用同步数据了。

7. Nosql 和 hadoop

Nosql 是近年来发展非常迅速的一项技术,他的核心是非结构化。Nosql 通过多个块存储数据,操作大数据的速度非常快。

关于hadoop 请看:

hadoop 初识

摘引自:看透spring mvc 源代码分析与实战

高并发的解决方案

除了数据量大,另外一个常见的问题就是并发量高,很多架构就是针对这个问题设计出来的。

1.应用和静态资源分离

刚开始的时候应用和静态资源是保存在一起的,当并发量达到一定程度的时候就需要将静态资源保存到专门的服务器中,静态资源主要包括图片、视频、js、css和一些资源文件等,这些文件因为没有状态所以分离比较简单,直接存放到响应的服务器就可以了,一般会使用专门的域名去访问。

通过不同的域名可以让浏览器直接访问资源服务器而不需要再访问应用服务器了。架构图如下:

2.页面缓存

页面缓存是将应用生成的页面缓存起来,这样就不需要每次都生成页面了,从而可以节省大量的CPU资源,如果将缓存的页面放到内存中速度就更快了。如果使用Nginx服务器就可以使用它自带的缓存功能,当然也可以使用专门的Squid 服务器。页面缓存的默认失效机制一班都是按缓存时间处理的,当然也可以在修改数据之后手动让相应的缓存失效。

页面缓存主要是使用在数据很少发生变化的页面,但是很多页面是大部分数据都很少发生变化,而其中很少一部分数据变化频率却非常高,比如说一个显示文章的页面,正常来说完全可以静态化,但是如果文章后面有“顶”和“踩”的功能而且显示的有响应的数量,这个数据的变化频率就比较高了,这就会影响静态化。这个问题可以用先生成静态页面然后使用Ajax来读取并修改响应的数据,这样就可以一举两得来,既可以使用页面缓存也可以实时显示一些变化频率高的数据来。

3.集群与分布式

集群是每台服务器都具有相同的功能,处理请求时调用那台服务器都可以,主要起分流作用。

分布式是将不同的业务放到不同的服务器中,处理一个请求可能需要用到多台服务器,这样就可以提高一个请求的处理速度,而且集群和分布式也可以同时使用。

集群有两个方式:一种是在静态资源集群。另一种是应用程序集群。静态资源集群比较简单。应用程序集群在处理过程中最核心的问题就是Session 同步问题。

Session 同步有两种处理方式:一种是在Session 发生变化后自动同步到其他服务器,另一种就是用个程序统一管理Session。所有集群的服务器都使用同一个Session,Tomcat 默认使用就是第一种方式,通过简单的配置就可以实现,第二种方式可以使用专门的服务器安装Mencached等高效的缓存程序统一来管理session,然后再应用程序中通过重写Request并覆盖getSession 方法来获取制定服务器中的Session。

对于集群来说还有一个核心的问题就是负载均衡,也就是接收到一个请求后具体分配到那个服务器去处理的问题,这个问题可以通过软件处理也可以使用专门的硬件(如:F5)解决。

4. 反向代理

反向代理指的是客户端直接访问的服务器并不真正提供服务,它从别的服务器获取资源然后将结果返回给用户。

图:

4.1 反向代理服务器和代理服务器的区别

代理服务器的作用是代我门获取想要的资源然后将结果返回给我们,所要获取的资源是我门主动告诉代理服务器的,比如,我门想访问Facebook,但是直接访问不了,这时就可以让代理服务器访问,然后将结果返回给我们。

反向代理服务器是我门正常访问一台服务器的时候,服务器自己去调用了别的服务器资源并将结果返回给我们,我门自己并不知道。

代理服务器是我们主动使用的,是为我们服务的,他不需要有自己的域名;反向代理服务器是服务器自己试用的,我门并不知道,它有自己的域名,我门访问它和访问正常的网址没有任何区别。

反向代理服务器主要有三个作用:

1. 可以作为前端服务器跟实际处理请求的服务器集成;

2. 可以做负载均衡

3. 转发请求,比如说可以将不同类型的资源请求转发到不同的服务器去处理。

5. CDN

cdn其实是一种特殊的集群页面缓存服务器,他和普通集群的多台页面缓存服务器相比,主要是它存放的位置和分配请求的方式有点特殊。CDN 服务器是分布在全国各地的,当接收到用户请求后会将请求分配到最合适的CDN服务器节点获取数据。比如联通的用户分配到联通的节点,上海的用户分配到上海的节点。

CDN的每个节点其实就是一个页面缓存服务器,如果没有请求资源的缓存就会从主服务器获取,否则直接返回缓存的页面。

CDN分配请求(负载均衡)的方式是用专门的CDN域名解析服务器在解析域名的时候就分配好的。一般的做法是在ISP哪里试用CNAME将域名解析到一个特定的域名,然后再将解析到的那个域名用专门的CDN服务器解析道相应的CDN节点。如图。

第二步访问CDN的DNS服务器是应为CNAME记录的目标域名使用NS记录指向了CDN的DNS服务器。CDN的每个节点可能也是集群了多台服务器。

6. 底层的优化

前面说的所有都是架构都是建立在最前面介绍的基础结构之上的。很多地方都需要通过网络传输数据,如果可以加快网络传输的速度,那将会让整个系统得到改善。

7. 小结

网站架构的整个演变过程主要是围绕大数据和高并发这两个问题展开的,解决方案主要分为使用缓存和多资源两种类型。多资源主要指多存储(包括多内存)、多CPU和多网络,对于多资源来说又可以分为单个资源处理一个完整的请求和多个资源合作处理一个请求两种类型,如多存储和多CPU中的集群和分布式,多网络中的CDN和静态资源分离。理解了整个思路之后就抓住了架构演变的本质,而且自己可能还可以设计出更好的架构。

 

   
2513 次浏览       17
相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践