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

网站性能是客观的指标,可以具体体现到响应时间,吞吐量等技术指标,同时也是主观的感受,而感受则是一种与具体参与者相关的微妙的东西,用户的感受和工程师的感受不同,不同的用户感受也不同。 ##4.1 网站性能测试## 性能测试是性能优化的前提和基础,也是性能优化结果的检查和度量标准。不同视角下的网站性能有不同的标准,也有不同的优化手段。 ###4.1.1 不同视角下的网站性能### 1. 用户视角的网站性能 从用户角度,网站性能就是用户在浏览器上直观感受到的网站响应速度快还是慢。主要优化手段:优化页面HTML样式,利用浏览器端的并发和异步特性,调整浏览器缓存策略,使用CDN服务,反向代理等。

2. 开发人员视角的网站性能 从开发人员角度,关注的主要是应用程序本身及其相关子系统的性能,包括响应延迟,系统吞吐量,并发处理能力,系统稳定性等技术指标。主要优化手段:使用缓存加速数据读取,使用集群提高吞吐能力,使用异步消息加快请求响应及实现削峰,使用代码优化手段改善程序性能等。

3. 运维人员视角的网站性能 从运维人员角度,关注基础设施性能和资源利用率,如网络运营商的带宽能力,服务器硬件的配置,数据中心网络架构,服务器和网络带宽的资源利用率等。主要优化手段:建设优化骨干网,使用高性价比定制服务器,利用虚拟化技术优化资源利用等。 ###4.1.2 性能测试指标### 1. 响应时间 指应用执行一个操作需要的时间,包括从发出请求开始到收到最后响应数据所需要的时间。

2. 并发数 指系统能够同时处理请求的数目,也反映了系统的负载特性。

3. 吞吐量 指单位时间内系统处理的请求数量,体现系统的整体处理能力。如:TPS(每秒事务数)是吞吐量的一个常用量化标准,HPS(每秒HTTP请求数),QPS(每秒查询数)等。在系统并发数由小逐渐增大的过程中(这个过程中也伴随着服务器系统资源消耗逐渐增大),系统吞吐量先是逐渐增加,达到一个极限后,随着并发数的增加反而下降,达到系统崩溃点后,系统资源耗尽,吞吐量均为零。

而这个过程中,响应时间则是保持小幅上升,到达吞吐量极限后,快速上升,到到系统崩溃点后,系统失去响应。

4. 性能计数器 描述服务器或操作系统性能的一些数据指标。包括System Load,对象与线程数,内存使用,CPU使用,磁盘与网络IO等指标。

System Load即系统负载,指当前正在被CPU执行和等待被CPU执行的进程数目总和,是反映系统忙闲程度的重要指标。多核CPU的情况下,完美情况是所有CPU都在使用,没有进程在等待处理。所以Load的理想值是CPU的数目。当Load值低于CPU数目的时候,表示CPU有空闲,资源存在浪费;当Load值高于CPU数目的时候,表示进程在排队等候CPU调度,表示系统资源不足,影响应用程序的执行性能。在Linux系统中使用top命令查看。 ###4.1.3 性能测试方法### 性能测试:以系统设计初期规划的性能指标为预期目标,对系统不断施加压力,验证系统在资源可接受范围内,是否能达到性能瓶颈。

负载测试:对系统不断地增加并发请求以增加系统压力,直到系统的某项或多项性能指标达到安全临界值,如某种资源已经呈饱和状态,这是继续对系统施加压力,系统的处理能力不但不能提高,反而会下降。

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

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

性能测试是一个不断对系统增加访问压力,以获得系统性能指标,最大负载能力,最大压力承受能力的过程。所谓的增加访问压力,在系统测试环境中,就是不断增加测试程序的并发请求数。 ##4.2 Web前端性能优化## ###4.2.1 浏览器访问优化### 1. 减少HTTP请求 HTTP协议是无状态的应用层协议,意味着每次HTTP请求都需要建立通信链路,进行数据传输,而在服务器端,每个HTTP都需要启动独立的线程去处理。这些通信和服务的开销都是很昂贵,减少HTTP请求的数目可有效提高访问性能。

减少HTTP的主要手段:合并CSS,合并JavaScript,合并图片。将浏览器一次访问需要的JavaScript,CSS合并成一个文件,这样浏览器只需要一次请求。图片也可以合并,多张图片合并成一张,如果每张图片都有不同的超链接,可通过CSS偏移响应鼠标点击操作,构造不同的URL。

2. 使用浏览器缓存 通过设置HTTP头中Cache-Control和Expires的属性,可设定浏览器缓存,缓存时间可以是数天,甚至是几个月。

在某些时候,静态资源文件变化需要及时应用到客户端浏览器,这种情况,可通过改变文件名实现,即更新JavaScript文件不是更新JavaScript文件内容,而是生成一个新的JS文件并更新HTML文件中的引用。

使用浏览器缓存策略的网站在更新静态资源时,不应采用批量更新的方法,比如需要更新10个图标文件,不宜把10个文件一次全部更新,而是一个文件一个文件逐步更新,并有一定的间隔时间,以免用户浏览器突然大量缓存失效,集中更新缓存,造成服务器负载骤增,网络堵塞的情况。

3. 启用压缩 在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。文本文件的压缩效率可达80%以上,因此HTML,CSS,JavaScript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信带宽良好,而服务器资源不足的情况下要权衡考虑。

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

5. 减少Cookie传输 一方面,Cookie包含在每次请求和响应中,太大的Cookie会严重影响数据传输,因此哪些数据需要写入Cookie需要慎重考虑,尽量减少Cookie中传输的数据量。另一方面,对于某些静态资源的访问,如CSS,JavaScript等,发送Cookie没有意义,可以考虑静态资源使用独立域名,避免请求静态资源时发送Cookie,减少Cookie传输的次数。

###4.2.2 CDN加速### CDN(内容分发网络)的本质仍然是一个缓存,而且将数据缓存在离用户最近的地方,使用户以最快速度获取数据,即所谓网络访问第一跳。

由于CDN部署在网络运营商的机房,这些运营商又是终端用户的网络服务提供商,因此用户请求路由的第一跳就到达了CDN服务器,当CDN中存在浏览器请求的资源时,从CDN直接返回给浏览器,最短路径返回响应,加快用户访问速度,减少数据中心负载压力。

CDN能够缓存的一般是静态资源,如图片,文件,CSS,JavaScript脚本,静态网页等,但是这些文件访问频度很高,将其缓存在CDN可极大改善网页的打开速度。 ###4.2.3 反向代理### 传统代理服务器位于浏览器一侧,代理浏览器将HTTP请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站Web服务器接收HTTP请求。

和传统代理服务器可以保护浏览器安全一样,反向代理服务器也具有保护网站安全的作用,来自互联网的访问请求必须经过代理服务器,相当于在Web服务器和可能的网络攻击之间建立了一个屏障。

除了安全功能,代理服务器也可以通过配置缓存功能加速Web请求。当用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上,这样当其他用户访问该静态内容的时候,就可以直接从反向代理服务器返回,加速Web请求响应速度,减轻Web服务器负载压力。

反向代理也可以实现负载均衡的功能,而通过负载均衡构建的应用集群可以提高系统总体处理能力,进而改善网站高并发情况下的性能。 ##4.3 应用服务器性能优化## ###4.3.1 分布式缓存### 网站性能优化第一定律:优先考虑使用缓存优化性能。 1. 缓存的基本原理 缓存指将数据存储在相对较高访问速度的存储介质中,以供系统处理。缓存的本质是一个内存Hash表,网站应用中,数据缓存以一对Key,Value的形式存储在内存Hash表中。Hash表数据读写的时间复杂度为O(1)。缓存主要用来存放那些读写比很高,很少变化的数据。网站数据访问通常遵循二八定律,即80%的访问落在20%的数据上。

2. 合理使用缓存 频繁修改的数据:如果缓存中保存的是频繁修改的数据,就会出现数据写入缓存后,应用还来不及读取缓存,数据就已失效的情形,陡增系统负担。一般说来,数据的读写比在2:1以上,即写入一次缓存,在数据更新前至少读取两次,缓存才有意义。实践中,这个读写比通常非常高,比如新浪微博的热门微博,缓存以后可能会被读取数百万次。 没有热点的访问:缓存使用内存作为存储,内存资源宝贵而有限,不可能将所有数据都缓存起来,只能将最新访问的数据缓存起来,而将历史数据清理出缓存。如果应用系统访问数据没有热点,不遵循二八定律,即大部分数据访问并没有集中在小部分数据上,那么缓存就没有意义,因为大部分数据还没有被再次访问就已经被挤出缓存了。 数据不一致与脏读:一般会对缓存的数据设置失效时间,一旦超过失效时间,就要从数据库中重新加载。因此应用要容忍一定时间的数据不一致。 缓存可用性:缓存是为提高数据读取性能的,缓存数据丢失或者缓存不可用不会影响到应用程序的处理——它可以从数据库直接获取数据。但当缓存服务器崩溃时,数据库会因为完全不能承受如此大的压力而宕机,进而导致整个网站不可用。这种情况被称作缓存雪崩缓存根本就不应该被当做一个可靠的数据源来使用。通过分布式缓存服务器集群,将缓存数据分布到集群多台服务器上可在一定程度上改善缓存的可用性。 缓存预热:缓存中存放的是热点数据,热点数据又是缓存系统利用LRU(最近最久未用算法)对不断访问的数据筛选淘汰出来的,这个过程需要花费较长的时间。新启动的缓存系统如果没有任何数据,在重建缓存数据的过程中,系统的性能和数据库负载都不太好,那么最好在缓存系统启动时就把热点数据加载好,这个缓存预加载手段叫作缓存预热。 缓存穿透:缓存没有保存该数据,所有的请求都会落到数据库上,会对数据库造成很大压力,甚至崩溃。一个简单的对策就是将不存在的数据也缓存起来(其value值为null)。

3. 分布式缓存架构 分布式缓存指缓存部署在多个服务器组成的集群中,以集群方式提供缓存服务。其架构方式有两种:(1)以JBoss Cache为代表的需要更新同步的分布式缓存;(2)以Memcached为代表的不互相通信的分布式缓存。

JBoss Cache的分布式缓存在集群中所有服务器中保存相同的缓存数据,当某台服务器有缓存数据更新的时候,会通知集群中其他机器更新缓存数据或清除缓存数据。JBoss Cache通常将应用程序和缓存部署在同一台服务器上,应用程序可以从本地快速获取缓存数据,但是这种方式带来的问题是缓存数据的数量受限于单一服务器的内存空间,而且当集群规模较大时,缓存更新信息需要同步到集群所有机器,其代价惊人。

Memcached采用一种集中式的缓存集群管理,也被称作互不通信的分布式架构方式。缓存和应用分离部署,缓存系统部署在一组专门的服务器上,应用程序通过一致性Hash等路由算法选择缓存服务器远程访问缓存数据,缓存服务器之间不通信,缓存集群的规模可以很容易地实现扩容,具有良好的可伸缩性。

4. Memcached 简单的通信协议:远程通信设计需要考虑两方面的要素,一是通信协议,即选择TCP协议还是UDP协议,抑或HTTP协议;二是通信序列化协议,数据传输的两端,必须使用彼此可识别的数据序列化方式才能使通信得以完成,如XML,JSON等文本序列化协议,或者Google Protobuffer等二进制序列化协议。Memcached使用TCP协议(UDP也支持)通信,其序列化协议则是一套基于文本的自定义协议,非常简单,以一个命令关键字开头,后面是一组命令操作数。

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

高效的内存管理:内存管理中一个令人头痛的问题就是内存碎片管理。操作系统,虚拟机垃圾回收在这方面想了许多办法:压缩,复制等。Memcached使用了一个非常简单的办法——固定空间分配。Memcached将内存空间分为一组slab,每个slab里又包含一组chunk,同一个slab里的每个chunk的大小是固定的,拥有相同大小chunk的slab被组织在一起,叫作slab_class。存储数据时根据数据的Size大小,寻找一个大于Size的最小chunk将数据写入。这种内存管理方式避免了内存碎片管理的问题,内存的分配和释放都是以chunk为单位的。和其他缓存一样,Memcached采用LRU算法释放最近最久未被访问的数据占用的空间,释放的chunk被标记为未用,等待下一个合适大小数据的写入。

当然这种方式也会带来内存浪费的问题。数据只能存入一个比它大的chunk里,而一个chunk只能存一个数据,其他空间被浪费了。如果启动参数配置不合理,浪费会更加惊人,发现没有缓存多少数据,内存空间就用尽了。

互不通信的服务器集群架构:其客户端路由算法一致性Hash更成为数据存储伸缩性架构设计的经典范式。事实上,正是集群内服务器互不通信使得集群可以做到几乎无限制的线性伸缩。 ###4.3.2 异步操作### 消息队列具有很好的削峰作用——即通过异步处理,将短时间高并发产生的事务消息存储在消息队列中,从而削平高峰期的并发事务。任何可以晚点做的事情都应该晚点做。 ###4.3.3 使用集群### 在网站高并发的情况下,使用负载均衡技术为一个应用构建一个由多台服务器组成的服务器集群,将并发访问请求分发到多台服务器上处理,避免单一服务器因负载压力过大而响应缓慢,使用户请求具有更好的响应延迟特性。 ###4.3.4 代码优化### 1. 多线程 多用户并发访问是网站的基本要求,大型网站的并发用户数会达到数万,单台服务器的并发用户也会达到数百。CGI编程时代,每个用户请求都会创建一个独立的系统进程去处理。由于线程比进程更轻量,更少占有系统资源,切换代价更小,所以目前主要的Web应用服务器都采用多线程的方式响应并发用户请求,因为网站开发天然就是多线程编程。

从资源利用的角度看,使用多线程的原因主要有两个:IO阻塞与多CPU。当前线程进行IO处理的时候,会被阻塞释放CPU以等待IO操作完成,由于IO操作(不管是磁盘IO还是网络IO)通常都需要较长的时间,这时CPU可以调度其他的线程进行处理。理想的系统Load是既没有进程(线程)等待也没有CPU空闲,利用多线程IO阻塞与执行交替进行,可最大限度地利用CPU资源。使用多线程的另一个原因是服务器有多个CPU,在这个连手机都有四核CPU的时代,除了最低配置的虚拟机,一般数据中心的服务器至少16核CPU,要想最大限度地使用这些CPU,必须启动多线程。

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

最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比。如果任务都是CPU计算型任务,那么线程数最多不超过CPU内核数,因为启动再多线程,CPU也来不及调度;相反如果是任务需要等待磁盘操作,网络响应,那么多启动线程有助于提高任务并发度,提高系统吞吐能力,改善系统性能。

多线程编程上,解决线程安全的主要手段有如下几点: (1)将对象设计为无状态对象;(2)使用局部对象;(3)并发访问资源时使用锁;

2. 资源复用 系统运行时,要尽量减少那些开销很大的系统资源的创建和销毁,比如数据库连接,网络通信连接,线程,复杂对象等。从编程角度,资源复用主要有两种模式:单例(Singleton)和对象池(Object Pool)。

3. 数据结构 在不同场景中合理使用恰当的数据结构,灵活组合各种数据结构改善数据读写和计算特性可极大优化程序的性能。

前面缓存部分已经描述过Hash表的基本原理,Hash表的读写性能在很大程度上依赖HashCode的随机性,即HashCode越随机散列,Hash表的冲突就越少,读写性能也就越高,目前比较好的字符串Hash散列算法有Time33算法,即对字符串逐字符迭代乘以33,求得Hash值,算法原型为:

hash(i) = hash(i - 1) * 33 + str[i];

Time33虽然可以较好地解决冲突,但是有可能相似字符串的HashCode也比较接近,如字符串“AA”的HashCode是2210,字符串“AB”的HashCode是2211。这在某些应用场景是不能接受的,这种情况下,一个可行的方案是对字符串取信息指纹,再对信息指纹求HashCode,由于字符串微小的变化就可以引起信息指纹的巨大不同,因此可以获得较好的随机散列:

原始字符串—MD5—>信息指纹—Hash计算—>HashCode

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

在JVM分代垃圾回收机制中,将应用程序可以的堆空间分为年轻代(Young Generation)和年老代(Old Generation),又将年轻代分为Eden区(Eden Space),From区和To区,新建对象总是在Eden区中被创建,当Eden区空间已满,就触发一次Young GC,将还被使用的对象复制到From区,这样整个Eden区都是未被使用的空间,可供继续创建对象,当Eden区再次用完,再触发一次Young GC,将Eden区和From区还在被使用的对象复制到To区,下一次Young GC则是将Eden区和To区还被使用的对象复制到From区。因此,经过多次Young GC,某些对象会在From区和To区多次复制,如果超过某个阀值对象还未被释放,则将该对象复制到Old Generation。如果Old Generation空间已用完,那么就会触发Full GC,即所谓的全量回收,对系统性能产生较大影响,因此应根据系统业务特点和对象生命周期,合理设置Young Generation和Old Generation大小,尽量减少Full GC。事实上,某些Web应用在整个运行期间可以做到从不进行Full GC。 ##4.4 存储性能优化## 很多时候,磁盘仍然是系统最严重的瓶颈。而且磁盘中存储的数据是网站最重要的资产,磁盘的可用性和容错性也至关重要。 ###4.4.1 机械硬盘 VS 固态硬盘### 机械硬盘:在数据连续访问(要访问的数据存储在连续的磁盘空间上)和随机访问(要访问的数据存储在不连续的磁盘空间上)时,由于移动磁头臂的次数相差巨大,性能表项差别也非常大。(快速顺序访问,慢速随机访问) 固态硬盘:这种硬盘没有机械装置,数据存储在可持久记忆的硅晶体上,因此可以像内存一样快速随机访问。而且SSD具有更小的功耗和更少的磁盘震动与噪声。(快速随机访问) ###4.4.2 B+树 VS LSM树### 磁盘的读写特性对存储结构和算法的选择影响深大。 B+树:是一种专门针对磁盘存储而优化的N叉排序树,以树节点为单位存储在磁盘中,从根开始查找所需数据所在的节点编号和磁盘位置,将其加载到内存中然后继续查找,直到找到所需的数据。

目前数据库多采用二级索引的B+树,树的层次最多三层。因此可能需要5次磁盘访问才能更新一条记录(三次磁盘访问获得数据索引及行ID,然后再进行一次数据文件读操作及一次数据文件写操作)。

但是由于每次磁盘访问都是随机的,而传统机械硬盘在数据随机访问时性能较差,每次数据访问都需要多次访问磁盘影响数据数据访问性能。

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

在需要进行读操作时,总是从内存中的排序树开始搜索,如果没有找到,就从磁盘上的排序树顺序查找。

在LSM树上进行一次数据更新不需要磁盘访问,在内存即可完成,速度远快于B+树。当数据访问以写操作为主,而读操作则集中在最近写入的数据上时,使用LSM树可以极大程序地减少磁盘的访问次数,加快访问速度。 ###4.4.3 RAID VS HDFS### RAID(廉价磁盘冗余阵列)技术主要是为了改善磁盘的访问延迟,增强磁盘的可用性和容错能力。目前服务器级别的计算机都支持插入多块磁盘(8块或者更多),通过使用RAID技术,实现数据在多块磁盘上的并发读写和数据备份。

RAID0:数据在从内存缓冲区写入磁盘时,根据磁盘数量将数据分成N份,这些数据同时并发写入N块磁盘,使得数据整体写入速度是一块磁盘的N倍。读取时也一样,因此RAID0具有极快的数据读取速度,但是RAID0不做备份,N块磁盘中只要有一块损坏,数据完整性就被破坏,所有磁盘的数据都会损坏。

RAID1:数据在写入磁盘时,将一份数据同时写入两块磁盘,这样任何一块磁盘损坏都不会导致数据丢失,插入一块新磁盘就可以通过复制数据的方式自动修复,具有极高的可靠性。

RAID10:结合RAID0和RAID1两种方案,将所有磁盘平均分成两份,数据同时在两份磁盘写入,相当于RAID1,但是在每一份磁盘里面的N/2块磁盘上,利用RAID0技术并发读写,既提高可靠性又改善性能,不过RAID10的磁盘利用率较低,有一半的磁盘用来写备份数据。

RAID3:一般情况下,一台服务器上不会出现同时损坏两块磁盘的情况,在只损坏一块磁盘的情况下,如果能利用其他磁盘的数据恢复损坏磁盘的数据,这样在保证可靠性和性能的同时,磁盘利用率也得到大幅提升。

在数据写入磁盘的时候,将数据分成N-1份,并发写入N-1块磁盘,并在第N块磁盘记录校验数据,任何一块磁盘损坏(包括校验数据磁盘),都可以利用其他N-1块磁盘的数据修复。

但是在数据修改较多的场景中,修改任何磁盘数据都会导致第N块磁盘重写校验数据,频繁写入的后果是第N块磁盘比其他磁盘容易损坏,需要频繁更换,所以RAID3很少在实践中使用。

RAID5:RAID5和RAID3很相似,但是校验数据不是写入第N块磁盘,而是螺旋式地写入所有磁盘中。这样校验数据的修改也被平均到所有磁盘上,避免RAID3频繁写坏一块磁盘。

RAID6:如果数据需要很高的可靠性,在出现同时损坏两块磁盘的情况下,仍然需要修复数据,这时候可以使用RAID6。RAID6和RAID5非常类似,但是数据只写入N-2块磁盘,并螺旋式地在两块磁盘中写入校验信息(使用不同算法生成)。

RAID技术可以通过硬件实现,比如专用的RAID卡或者主板直接支持,也可以通过软件实现。RAID技术在传统关系数据库及文件系统中应用比较广泛,但是在大型网站比较喜欢使用的NoSQL,以及分布式文件系统中,RAID技术却遭到冷落。

HDFS(Hadoop分布式文件系统):系统在整个存储集群的多台服务器上进行数据并发读写和备份,可以看作在服务器集群规模上实现了类似RAID的功能,因此不需要磁盘RAID。

HDFS以块(Block)为单位管理文件内容,一个文件被分割成若干个Block,当应用程序写文件时,每写完一个Block,HDFS就将其自动复制到另外两台机器上,保证每个Block有三个副本,即使有两台服务器宕机,数据依然可以访问,相当于实现了RAID1的数据复制功能。

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

在HDFS中有两种重要的服务器角色:NameNode(名字服务节点)和DataNode(数据存储节点)。NameNode在整个HDFS中只部署一个实例,提供元数据服务,相当于操作系统中的文件分配表(FAT),管理文件名Block的分配,维护整个文件系统的目录树结构。DataNode则部署在HDFS集群中其他所有服务器上,提供真正的数据存储服务。

和操作系统一样,HDFS对数据存储空间的管理以数据块(Block)为单位,只是比操作系统中的数据块(512字节)要大得多,默认为64MB。HDFS将DataNode上的磁盘空间分成N个这样的块,供应用程序使用。

应用程序(Client)需要写文件时,首先访问NameNode,请求分配数据块,NameNode根据管理的DataNode服务器的磁盘空间,按照一定的负载均衡策略,分配若干数据块供Client使用。

当Client写完一个数据块时,HDFS会将这个数据块再复制两份存储在其他DataNode服务器上,HDFS默认同一份数据有三个副本,保证数据可靠性。因此在HDFS中,即使DataNode服务器有多块磁盘,也不需要使用RAID进行数据备份,而是在整个集群上进行数据复制,而且系统一旦发现某台服务器宕机,会自动利用其他机器上的数据将这台服务器上存储的数据块自动再备份一份,从而获得更高的数据可靠性。

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

转载于:https://my.oschina.net/xianggao/blog/387317

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值