首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

读书笔记:《分布式JAVA使用 基础与实践》 第七章 构建可伸缩的系统

2012-12-22 
读书笔记:《分布式JAVA应用 基础与实践》 第七章 构建可伸缩的系统通常将通过升级或增加单机机器的硬件来支

读书笔记:《分布式JAVA应用 基础与实践》 第七章 构建可伸缩的系统

通常将通过升级或增加单机机器的硬件来支撑访问量及数据量增长的方式称为垂直伸缩,将通过增加机器来支撑访问量和数据量的增长的方式称为水平伸缩。垂直伸缩实现难度较低,但机器的硬件是无法不断升级和增加,容易达到瓶颈;水平伸缩理论上没有瓶颈,但技术难度较高。两者各有一定的优点,因此在应用中通常可以混合采用。

垂直伸缩前,先要分析系统的瓶颈,针对性地根据瓶颈对硬件进行升级或增加。另外,需要从软件方面保证系统在垂直伸缩后服务能力的线性增长,以下介绍软件方面要作出的努力

通常有以下三种情况会导致增加CPU后系统的服务能力无法线性增长。

锁竞争激烈

解决办法可参考性能调优中降低锁竞争的部分

用于支撑并发请求的线程数是固定的

可适当增加线程数

单线程任务

需要考虑按照CPU数对任务进行合理划分,以启动加多线程并行完成任务

要做到增加内存后系统的服务增长,要求系统能够随着内存的增加,响应速度提升,主要有以下两种情况会造成增加内存后系统的服务能力无法线性增长。

Cache的集合大小是固定的

可根据可用的内存计算出一个比例来控制cache的数据的大小。

JVM堆内存是固定的

相应对堆内存增行调整即可。另外,操作系统位数对可设置的大小有限制,对于要使用超过2G内存的JVM堆而言,操作系统升级到64位是必要的。

为了做到增加机器后系统的服务能力能线性增长,在软件方面要做很多的努力,以下介绍一下软件方面要做的改动。

通常基于Multicast实现。JAVA应用中用于实现广播同步的开源软件主要为JGroups,Jgroups除支持默认的Multicast方式广播外,也可借助TCP/IP实现更加可靠的广播,Jetty和Tomcat的Http Session的信息的同步就基于JGoups实现。

广播同步的方式,由于信息缓存和系统在同一个JVM中,性能较高,但广播同步会有一定的延时,要确保这个延时对于应用场景而言是可接受的。

如果要同步的数据多了后,单台机器会无法容纳,节点增多的情况下,同步消耗的时间会越来越长,最终导致所产生的延时会超过可接受的范围

分面式缓存是指由多台机器来构成一个巨大的缓存池,每台机器缓存一部分数据,其本身也是水平伸缩的。目前开源界中分布式缓存使用最广泛的是memcached,由Facebook开源,多家互联网公司均采用它来实现缓存。

Memcached客户端支持简单的对key hash,然后除以缓存机器的节点数取模的方式来寻找机器,也支持按一致性hash的方法来寻找,在实现时多采用ketama算法来实现。

每个key的数据是在memcached集群中只会保存一份,对于有些缓存高度敏感的应用而言,会产生一定的风险。Facebook采用的方法为构建多个memcached集群,将key进行冗余存储,这样当一个集群中的某台机器出现问题时,并不会影响这个key缓存的值。

?

除以上两种方式外,Terracotta也是一个可以考虑的选择。Terracotta是一个JVM级的集群框架,可实现多台机器的JVM堆对象的共享等;另外用户登录信息还可以直接改造为放入cookie中,那就不要广播同步或引入分布式缓存了,其他的一些不适合放入缓存的状态信息则可基于数据库来统一存储,这样仍然能保证应用是水平可伸缩的。

?

在系统中通常有上传文件这类场景,对于水平伸缩而言,就必须实现在集群中NodeA机器上传文件后,在NodeB也能看到,通常有以下三种办法可实现

指各系统直接与一个集中的存储设备连接,比较简单,程序无需进行改造。但水平伸缩支持得不好,单一存储设备的容易是有限的,且随着需要访问存储设备的节点越来越多,性能明显下降,另一方面,存储设备通常比较贵,且要有主备两台机器来避免单点故障。

网络存储主要有NAS(Network-Attached Storage)和SAN(Storage Area Network)两种方式。

NAS采用网络(TCP/IP、ATM等)技术,通过网络交换机连接存储系统和服务主机,采用标准的文件共享协议(NFS、CIFS等),从而实现异构平台下的文件共享,但当并发访问同一数据时,文件的读写速度会大幅度下降。对使用者而言,NAS提供的是文件系统,只须在机器上mount相应的文件系统即可操作,较为简单。

SAN采用光纤方式连接磁盘阵列和服务器主机,实现将多个磁盘阵列构成一个对外统一的存储区域,一方面可以提升存储空间的利用率,另一方面也有较好的伸缩性。对使用者而言,SAN提供的是块设备(BlockDevice),因此如希望多台机器共享同一Block,则要采用具有同时操作同一block功能的文件系统,例如IBM的TotalStorage SAN文件系统。相对而言,SAN硬件成本及使用成本都更高。

NAS和SAN各有住优缺点,目前已发展为采用NAS+SAN的方式来更好地满足网络存储的需求。

分布式文件系统采用的方法由众多PC Server机器构成的巨大的存储池,每台机器只存储一部分数据,其本身通常可非常好地支持水平伸缩。

典型的分布式文件系统有Google的GFS及Yahoo的HDFS,HDFS遵循GFS实现。

GFS在存储时将文件分割成固定的块,块的大小默认情况下固定为64MB,对于大文件,性能优势明显。但对于小文件,意味着每次只能从一台服务器上读取,当存取大量小文件时,会对主服务器的造成一定的压力,因此GFS不适用于存储大量小文件的系统。

?

在系统建设初期,会采用将各种业务都放在同一个系统的方式,这会导致这个系统日渐庞大,所需的资源越来越多,在进行水平伸缩时要考虑系统里各种业务会造成的资源增加的现象,这种状况会导致水平伸缩很难进行。例如增加机器后就造成了多个数据库连接的增加,对于这样的情况,通常采用拆分应用的方式来解决。如eBay将其业务系统拆分为商品、用户、评价、交易等。

拆分后系统的功能较为单一,在进行水平伸缩时更容易判断其伸缩会带来哪些资源的增加,并且由于之前由众多功能共享的机器变为独享,对于提升系统的响应速度也会起到很好的作用。

?

系统水平伸缩后,对于数据库而言,通常带来的一个问题是数据库的连接池的增加,而由于大多数数据库对水平伸缩支持得不好,因此通常采用如下四种方法解决这个问题:

通过页面静态化、页面片段缓存(通常基于ESI)、对读多写少的数据进行缓存等手段来减少数据查询

分库通常按照业务将一个数据库的数据拆分到多个数据库中,如eBay就按照业务拆分为商品、用户、评价、交易等数据库。分库主要面临两个问题:

已有系统需要作相应修改

对数据库的业务操作较复杂

目前大部分数据库访问仍然采用同步方式,每进行一次数据库操作就要占用一个数据库连接,并且要等到数据库操作执行完毕才会将连接释放。这对于高并发的系统就很容易出现连接不够用,数据库资源竞争激烈的问题,异步数据库访问是解决这种现象的一种方法。

异步数据库访问要将传统的通过阻塞IO访问数据库的方式转变为采用非阻塞或异步IO的方式来访问。目前有不少数据库都有了异步访问的客户端,在JbossNetty的测试报告中,异步的数据库访问方式较之传统的数据库访问带来了极大的性能提升。

DAL是指系统直接提交给数据库的操作转变为能过DAL来进行提交,在这种情况下,可借助DAL来数据库的使用。采用DAL后,无论业务服务器如何水平伸缩,数据库连接都可在DAL上统一控制。但DAL增加了一个中间层,会导致性能有一定的下降,其稳定性也会受到影响。目前DAL开源的有Amoeba,DAL的另一个好处是可透明化分库、分表对于业务服务器带来的影响

?

数据量增长后带来的问题主要是读写性能的下降,可采用一些方法借助机器的增加来提升读写数据的性能,主要有读写分离和多master两种方式。

读写分离适用于读多写少,并允许一定延时的业务中,对于读写比例基本相等的业务而言,采用读写分离反而会带来大幅度复制,造成系统运行缓慢。

为提升数据写的速度,通常可采用的方法是建立多个master,在建立多个master时最理想的状态是多个master没有关联,即各master的数据不相同。另外一种多master的状况则为每个master的数据保持一致,此时一个明显的挑战是数据一致性的问题,另外一个明显的挑战是自增ID的问题。

数据一致性通常采用复制、两阶段提交、三阶段提交或google paxos来解决;自增ID的问题通常要改为由程序来生成ID的方式来解决。

垂直伸缩场景中采取的方法是将计算任务拆分,多线程并行计算后汇总结果。水平伸缩场景中则可演变为将计算任务拆分,然后分派给不同的机器进行处理,最后汇总。可通过MapReduce和MPI实现。

?

热点排行