大数据与高并发解决方案

1.海量数据

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 初识

高并发的解决方案


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

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和静态资源分离。理解了整个思路之后就抓住了架构演变的本质,而且自己可能还可以设计出更好的架构。

原文:https://blog.csdn.net/u012373815/article/details/71435926 

展开阅读全文

没有更多推荐了,返回首页