20 数据存储服务器集群的伸缩性设计
在这种架构中,虽然多台服务器部署 MySQL 实例,但是它们的角色有主从之分,数据写操作都在主服务器上,由主服务器将数据同步到集群中其他从服务器,数据读操作 及数据分析等离线操作在从服务器上进行。
除了数据库主从读写分离,前面提到的业务分割模式也可以用在数据库,不同业务数据表部署在不同的数据库集群上,即俗称的数据分库。这种方式的制约条件是跨库的 表不能进行 Join 操作。
在大型网站的实际应用中,即使进行了分库和主从复制,对一些单表数据仍然很大的表,比如 Facebook 的用户数据库,淘宝的商品数据库,还需要进行分片,将一张表拆 开分别存储在多个数据库中。
目前网站在线业务应用中比较成熟的支持数据分片的分布式关系数据库产品主要有 开源的 Amoeba ( http://sourcefbrge.net/projects/amoeba/ )和 Cobar ( http://code.alibabatech. com/wiki/display/cobar/Home)。这 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 两个产品有相似的架构设计,以 Cobar 为例,部署模型 如图 6.15 所示。

Cobar 是一个分布式关系数据库访问代理,介于应用服务器和数据库服务器之间 (Cobar 也支持非独立部署,以 lib 的方式和应用程序部署在一起)。应用程序通过 JDBC 驱动访问 Cobar 集群,Cobar 服务器根据 SQL 和分库规则分解 SQL,分发到 MySQL 集群 不同的数据库实例上执行(每个 MySQL 实例都部署为主/从结构,保证数据高可用)。

前端通信模块负责和应用程序通信,接收到 SQL 请求(select * from users where userid in (12,22,23))后转交给 SQL 解析模块,SQL 解析模块解析获得 SQL 中的路由规则查询 条供 userid in( 12,22,23)博转交给 SQL 路由模块,SQL 路由模块根据路由规则配置(userid 为偶数路由至数据库 A, userid 为奇数路由至数据库 B )将应用程序提交的 SQL 分解成两 条 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 中存储着数据,要想保证集群扩容后数据一致负载均衡,必须 要做数据迁移,将集群中原来机器中的数据迁移到新添加的机器中,如图 6.17 所示。

具体迁移哪些数据可以利用一致性 Hash 算法(即路由模块使用一致性 Hash 算法进
行路由),尽量使需要迁移的数据最少。但是迁移数据需要遍历数据库中每条记录(的索 引),重新进行路由计算确定其是否需要迁移,这会对数据库访问造成一定压力。并且需 要解决迁移过程中数据的一致性、可访问性、迁移过程中服务器宕机时的可用性等诸多
问题。
实践中,Cobar 利用了 MySQL 的数据同步功能进行数据迁移。数据迁移不是以数据 为单位,而是以 Schema 为单位。在 Cobar 集群初始化时,在每个 MySQL 实例创建多个 Schema (根据业务远景规划未来集群规模,如集群最大规模为 1000 台数据库服务器,那 么总的初始 Schema 数 N 1000 )o 集群扩容的时候,从每个服务器中迁移部分 Schema 到新机器中,由于迁移以 Schema 为单位,迁移过程可以使用 MySQL 的同步机制,如图 6.18 所示。

同步完成时,即新机器中 Schema 数据和原机器中 Schema 数据一致的时候,修改 Cobar 服务器的路由配置,将这些 Schema 的 IP 修改为新机器的 IP,然后删除原机器中的相关 Schema,完成 MySQL 集群扩容。
在整个分布式关系数据库的访问请求过程中,Cobar 服务器处理消耗的时间是很少 的,时间花费主要还是在 MySQL 数据库端,因此应用程序通过 Cobar 访问分布式关系数 据库,性能基本和直接访问关系数据库相当,可以满足网站在线业务的实时处理需求。 事实上由于 Cobar 代替应用程序连接数据库,数据库只需要维护更少的连接,减少不必要 的资源消耗,改善性能。
但由于 Cobar 路由后只能在单一数据库实例上处理查询请求,因此无法执行跨库的 JOIN 操作,当然更不能执行跨库的事务处理。
相比关系数据库本身功能上的优雅强大,目前各类分布式关系数据库解决方案都显得非常简陋,限制了关系数据库某些功能的使用。但是当网站业务面临不停增长的海量 业务数据存储压力时,又不得不利用分布式关系数据库的集群伸缩能力,这时就必须从 业务上回避分布式关系数据库的各种缺点:避免事务或利用事务补偿机制代替数据库事 务;分解数据访问逻辑避免 JOIN 操作等。
除了上面提到的分布式数据库,还有一类分布式数据库可以支持 JOIN 操作执行复杂 的 SQL 查询,如 GreenPlum。但是这类数据库的访问延退比较大(可以想象,JOIN 操作 需要在服务器间传输大量的数据),因此一般使用在数据仓库等非实时业务中。
[](()2 NoSQL 数据库的伸缩性设计
在计算机数据存储领域,一直是关系数据库(Relation Database )的天下,以至传统企业应用领域,许多应用系统设计都是面向数据库设计一先设计数据库然后设计程序, 从而导致关系模型绑架对象模型,并由此引申出旷日持久的业务对象贫血模型与充血模 型之争。业界为了解决关系数据库的不足,提出了诸多方案,比较有名的是对象数据库, 但是这些数据库的出现只是进一步证明关系数据库的优越而已。直到大型网站遇到了关系数据库难以克服的缺陷一一糟糕的海量数据处理能力及僵硬的设计约束,局面才有所 改善。为了解决上述问题,NoSQL 这一概念被提了出来,以弥补关系数据库的不足。
NoSQL,主要指非关系的、分布式的数据库设计模式。也有许多专家将 NoSQL 解读为 Not Only SQL,表示 NoSQL 只是关系数据库的补充,而不是替代方案。一般而言,NoSQL 数据库产品都放弃了关系数据库的两大重要基础:以关系代数为基础的结构化查询语言(SQL )和事务一致性保证(ACID )o 而强化其他一些大型网站更关注的特性:高可用性和可伸缩性。
开源社区有各种 NoSQL 产品,其支持的数据结构和伸缩特性也各不相同,目前看来, 应用最广泛的是 Apache HBaseo
评论