所谓网站的伸缩性是指不需要改变网站的软硬件设计, 仅仅通过改变部署的服务器数量就可以扩大或者缩小网站的服务处理能力。
一般说来,网站的伸缩性设计可分成两类
一类是根据功能进行物理分离实现伸缩,一类是单一功能通过集群实现伸缩。前者是不同的服务器部署不同的服务,提供不同的功能;后者是集群内的多台服务器部署相同的服务,提供相同的功能。
网站架构的伸缩性设计
第一种:不同功能根据物理分离实现伸缩
一般在网站发展的早期,新增的服务器总是会从现有的服务器中分离出部分功能和服务。
每次分离都会有更多的服务器加入网站,使用新增的服务器处理某种特定服务。
具体又可分成如下两种情况。
横向分离
横向分离(业务分割后分离):将不同的业务模块分离部署,实现系统伸缩性。横向分离的粒度可以非常小,甚至可以一个关键网页部署一 个独立服务,比如对于电商网站非常重要的产品详情页面,商铺页面,搜索列表页面,每个页面都可以独立部署,专门维护。
第二种:单一功能通过集群规模实现伸缩
将不同功能分离部署可以实现一 定程度的伸缩性,但是随着网站访问量的逐步增加,即使分离到最小粒度的独立部署,单一的服务器也不能满足业务规模的要求。因此必须使用服务器集群,即将相同服务部署在多台服务器上构成一个集群整体对外提供服务。
应用服务器集群的伸缩性设计
应用服务器如果是无状态的话,也就是说不具备上下文信息存储,每次请求转发到任意一台机器处理的结果都是一样的。我们只需要通过请求转发器按照负载均衡策略进行请求转发的话,每个请求就可以落在不同服务器上。如果HTTP请求分发装置可以感知或者可以配置集群的服务器数量,可以及时发现集群中新上线或下线的服务器,并能向新上线的服务器分发请求,停止向巳下线的服务器分发请求,那么就实现了应用服务器集群的伸缩性。
这个HTTP请求分发装置被称作负载均衡服务器。我们可以根据负载均衡去实现网站的伸缩性,也能改善网站的整体可用性。
具体实现的技术有很多种,但基本都包括以下几个方面:
1.HTTP重定向负载均衡
利用 HTTP 重定向协议实现负载均衡。
HTTP 重定向服务器是一台普通的应用服务器,其唯一 的功能就是根据用户的HTTP请求计算一台真实的 W eb 服务器地址,并将该W eb 服务器地址写入H TTP 重定向响应中(响应状态码 302 ) 返回给用户浏览器。
在图 6.5 中 ,浏览器请求访间域 名www.mysite.com, DNS服务器解析得到 IP 地址是 114.100.80.10, 即HTTP 重定向服务器的 IP 地址。然后浏览器通过 IP 地址 114.100.80.10 访间HTTP 重定向负载均衡服务器后,服务器根据某种负载均衡算法计算获得一 台实际物理服务器的地址 (114.100.80.3),构造一个包含该实际物理服务器地址的重定向响应返回给浏览器,浏览器自动重新请求实际物理服务器的IP地址114.100.80.3, 完成访问。
优缺点:
这种负载均衡方案的优点是比较简单。
缺点:
浏览器需要两次请求服务器才能完成一次访问,性能较差;
重定向服务器自身的处理能力有可能成为瓶颈,
整个集群的伸缩性规模有限;
使用HTTP302响应码重定向,有可能使搜索引擎判断为SEO作弊,降低搜索排名。
很少使用。。。
2 DNS域名解析负载均衡
利用DNS处理域名解析请求的同时进行负载均衡处理的一种方案。
每次域名解析请求都会根据负载均衡算法计算一个不同的1P地址返回 ,这样 A 记录中配置的多个服务器就构成一 个集群,并可以实现负载均衡。
优点:
DNS域名解析负载均衡的优点是将负载均衡的工作转交给DNS,省掉了网站管理维护负载均衡服务器的麻烦,
同时许多DNS还支持基于地理位置的域名解析,即会将域名解析成距离用户地理最近的一个服务器地址,这样可加快用户访间速度,改善性能。
缺点:
目前的DNS是多级解析,每一级DNS都可能缓存A记录,当下线某台服务器后,即使修改了DNS的A记录,要使其生效也需要较长时间,这段时间,DNS依然会将域名解析到巳经下线的服务器,导致用户访间失败;而且DNS负载均衡的控制权在域名服务商那里,网站无法对其做更多改善和更强大的管理。
事实上,大型网站总是部分使用DNS域名解析,利用域名解析作为第一级负载均衡手段,即域名解析得到的一组服务器并不是实际提供Web服务的物理服务器,而是同样提供负载均衡服务的内部服务器,这组内部负载均衡服务器再进行负载均衡,将请求分发到真实的Web服务器上。
3.反向代理负载均衡
利用反向代理服务器进行负载均衡.
利用反向代理缓存资源,以改善网站性能。实际上,在部署位置上,反向代理服务器处于 W eb 服务器前面 (这样才可能缓存 W eb 响应,加速访问),这个位置也正好是负载均衡服务器的位置,所以大多数反向代理服务器同时提供负载均衡的功能,管理一 组W eb 服务器,将请求根据负载均衡算法转发到不同Web服务器上。Web服务器处理完成的响应也需要通过反向代理服务器返回给用户。由于 Web 服务器不直接对外提供访间,因此Web服务器不需要使用外部IP地址,而反向代理服务器则需要配置双网卡和内部外部两套 IP地址。
图6.7中,浏览器访问请求的地址是反向代理服务器的地址114.100.80.10,反向代理服务器收到请求后,根据负载均衡算法计算得到一台真实物理服务器的地址 10.0.0.3,并将请求转发给服务器。10.0.0.3处理完请求后将响应返回给反向代理服务器,反向代理服务器再将该响应返回给用户。
优点是和反向代理服务器功能集成在一起,部署简单。
缺点是反向代理服务器是所有请求和响应的中转站,其性能可能会成为瓶颈。
类似的还有IP负载均衡、数据链路负载均衡我就一一概述了。
我们接下来继续介绍其他方面的伸缩性架构设计
分布式缓存集群的伸缩性架构设计
关于分布式缓存,相信大家都有接触过,当然基本是互联网型的公司,不同于我们的服务器集群的伸缩性设计,分布式缓存集群的伸缩性不能仅仅使用简单的负载均衡来实现。
我们还需要考虑数据一致性和数据同步数据可用性等问题。
分布式缓存服务器集群中不同服务器中缓存的数据各不相同,缓存访问请求不可以在缓存服务器集群中的任意一台处理,必须先找到缓存有需要数据的服务器,然后才能访问。这个特点会严重制约分布式缓存集群的伸缩性设计,因为新上线的缓存服务器没有缓存任何数据,而巳下线的缓存服务器还缓存着网站的许多热点数据。
必须让新上线的缓存服务器对整个分布式缓存集群影响最小,也就是说新加入缓存服务器后应使整个缓存服务器集群中已经缓存的数据尽可能还被访问到,这是分布式缓存集群伸缩性设计的最主要目标。
我们以memcached分布式缓存集群的设计为例:
应用程序通过Memcached客户端访问Memcached服务器集群,Memcached客户端主要由一组API、Memcached服务器集群路由算法、Memcached服务器集群列表及通信模块构成。
其中路由算法负责根据应用程序输入的缓存数据KEY计算得到应该将数据写入到Memcached的哪台服务器(写缓存)或者应该从哪台服务器读数据(读缓存)。
一个典的型缓存写操作如图6.10中箭头所示路径。应用程序输入需要写缓存的数据<'BEIJING',DATA>, API将KEY('BEIJING')输入路由算法模块,路由算法根据KEY和Memcached集群服务器列表计算得到一台服务编号(NODEl),进而得到该机器的IP地址和端口(10.0.0.0:91000)。API调用通信模块和编号为NODEl的服务器通信,将数据<'BEIJING',DATA>写入该服务器。完成一次分布式缓存的写操作。
读缓存的过程和写缓存一样,由于使用同样的路由算法和服务器列表,只要应用程序提供相同的KEY('BElnNG'),
Memcached客户端总是访问相同的服务器(NODEl)去读取数据。只要服务器还缓存着该数据,就能保证缓存命中。
memcached分布式缓存集群的伸缩性挑战
正常的路由算法使用余数hash,使用服务器下标作为编号,由于hashCode具备随机性,这时候key的存储,在整个集群中是比较均衡分布的,当布式缓存集群需要扩容的时候,就比较麻烦了。
简单来说,就是比如原来有三台服务器,由于业务需要,新增加一台,更改服务器列表,仍旧使用余数Hash,用4除以key为'BEIJING'的Hash值49080643,余数为2,对应服务器NODE2。由于数据<'BEIJING'J)ATA>缓存在NODEl, 对NODE2的读缓存操作失败,缓存没有命中。
我们可以得出新加入一台,会导致大概百分之75的缓存不能命中。这时候回去数据库中读取,如果大量缓存都没有命中,这时候会发生缓存穿透,导致大量读请求去数据库读,严重的会导致数据库宕机。
分布式缓存伸缩性设计解决的方法
一致性hash算法
一致性Hash算法通过一个叫作一致性Hash环的数据结构实现KEY到缓存服务器的Hash映射,如图6.11所示。具体算法过程为:先构造一个长度为0-2的32次方的整数环(这个环被称作一致性 Hash 环 ),根据节点名称的Hash值(其分布范围同样为0-2的32次方 )将缓存服务器节点放置在这个 Hash环上。然后根据需要缓存的数据的KEY值计算得到其Hash值(其分布范围也同样为0-2的32次方 ), 然后在Hash环上顺时针查找距离这个KEY的Hash值最近的缓存服务器节点,完成KEY到服务器的Hash映射查找。
假设NODEI的Hash值为3,594,963,423,NODE2的Hash值为
加入新节点NODE3后,原来的KEY大部分还能继续计算到原来的节点,只有KEY3、KEYO从原来的NODEl重新计算到NODE3。这样就能保证大部分被缓存的数据还可以继续命中。3台服务器扩容至4台服务器,可以继续命中原有缓存数据的概率是75%, 远高于余数Hash的25%, 而且随着集群规模越大,继续命中原有缓存数据的概率也逐渐增大,100台服务器扩容增加1台服务器,继续命中的概率是99%。虽然仍有小部分数据缓存在服务器中不能被读到,但是这个比例足够小,通过访问数据库获取也不会对数据库造成致命的负载压力。
实现
具体应用中,这个长度为2的32次方的一致性Hash环通常使用二叉查找树实现,Hash查找过程实际上是在二叉查找树中查找不小于查找数的最小数值。当然这个二叉树的最右边叶子节点和最左边的叶子节点相连接,构成环。
但是,上面描述的算法过程还存在一 个小小的问题?
新加入的节点NODE3只影响了原来的节点NODEl, 也就是说一 部分原来需要访间NODEl的缓存数据现在需要访间NODE3 (概率上是50%)。但是原来的节点NODEO和NODE2不受影响,这就意味着NODEO和NODE2缓存数据量和负载压力是NODEl与NODE3的两倍。如果4台机器的性能是一 样的,那么这种结果显然不是我们需要的。
计算机领域有句话:计算机的任何问题都可以通过增加— 个虚拟层来解决。计算机硬件、计算机网络、计算机软件都莫不如此。计算机网络的7层协议,每一层都可以看作是下一 层的虚拟层;计算机操作系统可以看作是计算机硬件的虚拟层;Java虚拟机可以看作是操作系统的虚拟层;分层的计算机软件架构事实上也是利用虚拟层的概念。
解决上述一 致性Hash 算法带来的负载不均衡问题,也可以通过使用虚拟层的手段:将每台物理缓存服务器虚拟为一 组虚拟缓存服务器,将虚拟服务器的Hash值放置在Hash环上,KEY在环上先找到虚拟服务器节点,再得到物理服务器的信息。
这样新加入物理服务器节点时,是将一 组虚拟节点加入环中,如果虚拟节点的数目足够多,这组虚拟节点将会影响同样多数目的已经在环上存在的虚拟节点,这些已经存在的虚拟节点又对应不同的物理节点。最终的结果是:新加入一 台缓存服务器,将会较为均匀地影响原来集群中已经存在的所有服务器,也就是说分摊原有缓存服务器集群中所有服务器的一 小部分负载,其总的影响范围和上面讨论过的相同。
可以得出结论哈,每个物理节点对应的虚拟节点越多,各个物理节点之间的负载越均衡,新加入物理服务器对原有的物理服务器的影响保持一致(这就是一致性hash这个名称的由来)
在实践中,一般部署一台物理服务器对应150台左右的虚拟服务器节点比较合适。
数据库存储服务器集群的伸缩性设计
和缓存服务器集群的伸缩性不同的是,数据存储服务器的集群的伸缩性对数据的持久性和可用性会有更高的要求。
缓存的目的是加速数据读取并减轻数据存储服务的负载压力。因此部分缓存数据的丢失不影响业务的正常处理,因为数据还可以从数据库等存储服务器上处理。
而数据存储服务器则必须保证数据的可靠存储。任何情况下都必须保证数据的可用性和正确性。具体又可以分为关系型数据库集群的伸缩性设计和NoSQL数据库的伸缩性设计。
关系型数据库集群伸缩性设计
市场上主要的关系数据都支持数据复制功能,使用这个功能可以对数据库进行简伸缩。
读写分离
在这种架构中 ,虽然多台服务器部署MySQL实例,但是它们的角色有主从之分,数据写操作都在主服务器上,由主服务器将数据同步到集群中其他从服务器,数据读操作及数据分析等离线操作在从服务器上进行。
分库分表
不同业务数据表部署在不同的数据库集群上,即俗称的数据分库。这种方式的制约条件是跨库的表不能进行 Join 操作。
分片,将一张表拆开分别存储在多个数据库中。
目前网站在线业务应用中比较成熟的支持数据分片的分布式关系数据库产品主要有开源的 Amoeba 和Cobar(http://code.alibabatech.com/wiki/display/cobar/Home) 。这两个产品有相似的架构设计,以Cobar为例,部署模型如图 xQ
Cobar是一个分布式关系型数据访问代理,介于应用服务器和数据库服务器之间,也支持非独立部署,以lib的方式和应用程序部署在一起。
应用程序通过JDKC驱动访问集群,Cobar服务器根据sql和sql分库规则分解sql,然后分发到MySQL集群上不同的数据库实例上进行(每个Mysql实例都部署为主/从结构,保证数据高可用)
如何执行??
前端通信模块负责和应用程序通信,接收到SQL请求
(select * from users where userid in (12,22,23))
后转交给SQL解析模块,SQL解析模块解析获得SQL中的路由规则查询条件(useridin(12,22,23) 转交给SQL路由模块,SQL路由模块根据路由规则配置(userid为偶数路由至数据库A, userid为奇数路由至数据库B)将应用程序提交的SQL分解成两条
select* from users where userid in (12,22);
select* from users where userid in (23);
转交给SQL执行代理模块,发送至数据库A和数据库B分别执行。
数据库A和数据库B的执行结果返回至SQL执行模块,通过结果合并模块将两个返回结果集合并成一个结果集,最终返回给应用程序,完成在分布式数据库中的一次访间请求。
那么Cobar如何做集群的伸缩呢?
Cobar的伸缩有两种: Cobar服务器集群的伸缩和MySQL服务器集群的伸缩。
Cobar服务器可以看作是无状态的应用服务器,因此其集群伸缩可以简单使用负载均衡的手段实现。而MySQL中存储着数据,要想保证集群扩容后数据一 致负载均衡,必须要做数据迁移,将集群中原来机器中的数据迁移到新添加的机器中: 具体迁移哪些数据可以利用一致性Hash算法 (即路由模块使用一致性Hash 算法进行路由),尽量使需要迁移的数据最少。但是迁移数据需要遍历数据库中每条记录(的索引),重新进行路由计算确定其是否需要迁移,这会对数据库访问造成一定压力。并且需要解决迁移过程中数据的一致性、可访问性、迁移过程中服务器宕机时的可用性等诸多问题。同步完成时,即新机器中Schem a数据和原机器中Schem a数据一 致的时候,修改Cobar服务器的路由配置,将这些 Schem a 的 IP 修改为新机器的 IP, 然后删除原机器中的相关Schema, 完成 MySQL 集群扩容。
在整个分布式关系数据库的访问请求过程中,Cobar服务器处理消耗的时间是很少的,时间花费主要还是在MySQL数据库端,因此应用程序通过Cobar访间分布式关系数据库,性能基本和直接访问关系数据库相当,可以满足网站在线业务的实时处理需求。事实上由于Cobar代替应用程序连接数据库,数据库只需要维护更少的连接,减少不必要的资源消耗,改善性能。
缺点:但由于 Cobar 路由后只能在单一 数据库实例上处理查询请求,因此无法执行跨库的JOIN操作,当然更不能执行跨库的事务处理。
目前各类分布式关系数据库解决方案都显得非常简陋,限制了关系数据库某些功能的使用。但是当网站业务面临不停增长的海量业务数据存储压力时, 又不得不利用分布式关系数据库的集群伸缩能力,这时就必须从业务上回避分布式关系数据库的各种缺点:避免事务或利用事务补偿机制代替数据库事务;分解数据访问逻辑避免 JO IN 操作等。
NoSQL数据库的伸缩性设计
NoSQL, 主要指非关系型的 、分布式的数据库设计模式。也有许多专家将NoSQL解读为NotOnlySQL,表示NoSQL只是关系数据库的补充,而不是替代方案。一般而言,NoSQL数据库产品都放弃了关系数据库的两大重要基础:以关系代数为基础的结构化查询语言(SQL)和事务一致性保证 (A CID )。而强化其他一 些大型网站更关注的特性:高可用性和可伸缩性。
开源社区有各种 NoSQ L 产品,其支持的数据结构和伸缩特性也各不相同,目前看来,应用最广泛的是 Apache HBase 。
HBase为例
HBase 为可伸缩海量数据储存而设计,实现面向在线业务的实时数据访问延迟。HBase的伸缩性主要依赖其可分裂的 HRegion 及可伸缩的分布式文件系统HDFS 实现。
HBase 的整体架构如图
HBase 中, 数据以 HRegion 为单位进行管理,也就是说应用程序如果想要访问一个数据,必须先找到HRegion,然后将数据读写操作提交给 HRegion, 由HRegion完成存储层面的数据操作。每个HRegion中存储一段Key值区间[key1_,key2)的数据.
HRegionServer 是物理服务器,每个HRegionServer上可以启动多个HRegion实例。当一个HRegion中写入的数据太多,达到配置的阑值时,HRegion 会分裂成两个 HRegion, 并将 HRegion 在整个集群中进行迁移,以使 HregionServer的负载均衡。
所有HRegion 的信息 (存储的 Key 值区间、所在 HRegion Server地址、访问端口号等)都记录在 HMaser 服务器上,为了保证高可用,HBase 启动多个 HMaser, 并通过Zookeeper (一 个支持分布式一 致性的数据管理服务)选举出一 个主服务器,应用程序通过Zookeeper 获得主 HMaser的地址,输入 Key 值获得这个Key 所在的HRegion Server地址,然后请求 HRegionServer上的HRegion, 获得需要的数据。数据的写入如下:
数据写入过程也是一样,需要先得到HRegion才能继续操作,HRegion会把数据存储在若干个叫作HFile格式的文件中,这些文件使用HDFS分布式文件系统存储,在整个集群内分布并高可用。当一个 HRegion 中数据量太多时,HRegion (连同HFile)会分裂成两个 HRegion, 并根据集群中服务器负载进行迁移,如果集群中有新加入的服务器,也就是说有了新的 HRegion Server, 由于其负载较低,也会把 HRegion 迁移过去并记录到 HMaster, 从而实现 HBase 的线性伸缩。
伸缩性架构设计能力是网站架构师必须具备的能力。
一个具有良好伸缩性架构设计的网站,其设计总是走在业务发展的前面,在业务需要处理更多访问和服务之前,就巳经做好充足准备,当业务需要时,只需要购买或者租用服务器简单部署实施就可以了
网友评论