数据库拆分?

1 数据库拆分的兴起 
在过去几年中,随着商业应用数据库事务量的大幅增加和数据库体积的增大,数据库拆分的概念已日益普及。许多在线服务供应商,软件即服务供应商(SaaS)和社交网站的成功更说明了这一点。 
数据库拆分能够简单定义为针对跨多个服务器的大型数据库设计的一种“零共享”分区方案,这种方案使数据库性能和扩展性提升到一个新的水平变得可行。想象一下碎玻璃,您就能理解什么是sharding(碎片)——将数据库分红较小块所谓的“碎片”,散布在众多分布式服务器上。 
术语“sharding”是谷歌工程师们独创,并经过他们的大表架构的公布获得推广的。然而,“shared-nothing(零分享)”这一数据库分区的思想已经存在了十年以上。在此期间已经产生了许多实例,特别是一些知名的在线服务提供商的著名的内部解决方案,如eBay、Amazon、Digg、Flickr、Skype、YouTube、Friendster和Wikipedia。 
本文的重点是关于数据库拆分的需求、数据库分区的可选方案和成功进行数据库拆分的一些关键考虑因素。 


1 大表:一个结构化数据分布式存储系统,由Fay Chang,Jeffrey Dean及其余Google员工提出。 


2 是什么推进了对数据库拆分的需求? 

数据库拆分是一个高可扩展性的方法,用于提升高度事务化、大型以数据库为中心的商业应用程序的数据吞吐和总体性能。自从关系数据库产生以来,显而易见,商业数据库通常随着时间增加而增加,对此应用工程师和设计师们要求不断地提升数据库的性能和容量。除此以外,网络经济的发展、信息时代的大背景、大量电子商务的普及使得商业数据急剧膨胀,致使了这一趋势更加明显。 
正如任何一位有经验的数据库管理员或应用程序开发人员所深知,当数据层的大小和事务规模呈线性增加的话,响应时间每每呈对数增加,这是不言而喻的。以下图所示: 

图1. 数据库大小和事务数的增加对响应时间有着巨大影响。 
数据库性能和扩展性面临挑战的内在缘由就是数据库管理系统自己的基础设计。任何计算机的数据库主要依赖于其三个部件: 
- CPU 

- 内存 
- 磁盘 
经过进行基准测试,咱们知道,单个服务器上的某个部件只能扩展到必定的限度,而后必须采起其余措施。很明显,磁盘I / O是主要瓶颈,由于即便数据库管理系统获得改善,它依然保持对CPU和内存的高占用率。事实上,咱们已经注意到,正是这三个因素的匹配程度决定了数据库的最大性能。换句话说,你不能经过单纯无限制增长CPU(或处理核心)的数量,而不提升内容容量,也不改善磁盘驱动子系统的性能,来使整个数据库系统总体性能获得相应的提升。显而易见,将资源投入到单个数据库服务器上的回报会逐渐减少。尤为是在混合使用的商业事务系统上,在执行大量读写事务的系统上,以及支持广义的商业报表任务方面,这些因素会更加明显。 
所以,随着商业应用程序日益成熟,对它的需求也持续增加。架构师、开发人员和数据库管理员一直面临着维护关键任务系统的数据库性能的挑战。这一前景推进着对数据库拆分的需求。 


3 数据库分区的可选项 
人们早就知道数据库分区可以改善关系数据库的性能和扩展性。演变至今的技术包括: 
- 主/从服务器:这是被许多组织使用的最简单的一个选择。使用一个主服务器处理全部的写(建立、更新或删除,或增删改查)操做,同时使用一个或多个从服务器处理只读操做。主服务器使用标准地、近似实时的复制功能将数据复制到各个从服务器。主/从模式能够将数据库总体性能提高到必定程度,容许读密集型的操做被分离到从服务器进行处理,但此种方法也有以下局限性: 
l 单个主服务器处理写操做,在扩展性上有明显的局限性,而且会很快产生瓶颈。 
l 主/从服务器的复制机制是“近于实时”的,这意味着从服务器不能保证得到主服务器上的即时快照。这种机制对于某些应用来讲是可行的,但若是您的应用须要的是最新数据,这种方法是不可取的。 
l 许多组织一样采用主/从服务器的方法来实现高可用性,但一样受限于主从服务器并不彻底同步。若是主服务器发生灾难性故障时,任何事务都将在复制以前丢失,这种状况是大多商业事务应用所不能接受的。 
- 集群运算:利用多台服务器同组集群计算,服务器之间经过群集的节点共享信息。大多数状况下这要依赖于一个集中的共享磁盘设备,一般是一个存储区域网络(SAN)。集群中的每一个节点运行数据库服务器的单一实例,且以不一样的模式工做: 
l 对于高可用性,集群中的多个节点可用于读取,但只有一个处理写(增删改查)操做。这虽然可使读取速度更快,而写操做却得不到任何改善。若是一个节点失败时,则群集中的另外一个节点接替它,继续在共享磁盘设备上进行工做。因为一个增删改查操做瓶颈,这种作法限制了其扩展性。即便是读取操做也最终会达到一个性能极限,由于集中共享的磁盘设备在性能增幅递减以前只能分担这么大的负载。当一个应用程序须要复杂的联接或包含未优化的SQL语句时,其读操做所受的限制就是一个有力的证实。 
l 更先进的集群技术依靠节点之间实时内存复制,该技术经过一种实时信息系统来保持在集群节点的内存镜像是实时的。这样使得每一个节点具有既可工做在读取模式也可工做在写入模式,但最终仍是会被通讯节点之间能够传输的流量大小所限制(采用一个典型的网络或其余高速通讯机制)。所以,随着节点的增长,通信和内存复制的开销呈几何级数倍增,从而严重限制了扩展性,一般只好采用相对较少的节点数。此方案遇到了和传统集群同样的共享磁盘的限制,即不断增大的单一的大型数据库会产生愈来愈密集的磁盘读写。 
- 表分区: 许多数据库管理系统支持表分区,如在一个大表中的数据能够跨多个磁盘以提升磁盘I / O利用率。这种分区一般是作横向(跨磁盘分区分行),但某些系统也能够垂直分区(在不一样的分区上放置不一样的列)。这种方法能够帮助减小对于某个特定表的磁盘I / O瓶颈,但每每使联接和其余操做变慢。此外,因为这种方法依赖于数据库管理系统下的单个数据库实例,全部其余对于CPU和内存的争夺所形成的限制进一步限制了其扩展性。 
- Federated表:表分区技术的一个分支就是Federated表方法。使用这种方法,表能够在跨多个服务器被访问。这种作法管理起来很是复杂,且因为Federated表必须经过网络访问,效率也不高。这种作法可能适合某些报道性或分析性工做,但对于通常的读/写事务来讲并不是一个很好的选择。 
这些方法的共同缺点是依赖于共享设备和资源。不管是依赖于共享内存,集中磁盘,仍是处理器,扩展性都会受到限制,更不用提其余缺点了,包括复杂的管理,缺少对关键业务需求的支持以及高可用性方面的限制。 


4 数据库拆分,一种“零共享”的方法 
数据库拆分提供了一个跨多个独立的服务器实现可扩展性的方法。每一个服务器有本身的CPU,内存和磁盘。与传统的加强数据库性能的方法相比,它没有其余方法所遇到的典型限制。对于“零共享”数据库如何实现的研究和探讨已超过15年之久,但直到最近几年由于应用数据量的大增,才在商业领域找到较为普遍的市场需求。 
数据库拆分的基本概念很是直白:将一个大的数据库,跨服务器分解成许多更小的数据库。以下图所示: 



图2:数据库拆分就是将大数据库拆分红若干个小数据库。 
很明显,“零共享”数据库拆分的优点就是大大提升扩展性。当更多的服务器被添加到网络中时,扩展性以近线性的方式增加。不过,在考虑一个拆分方案时,拆分红若干小数据库的方式还有其余几个优势不容忽视: 
l 较小的数据库更易于管理。生产数据库必须进行全面的管理:按期备份、数据库优化和其余常规任务。使用一个大数据库的话,若是仅就完成操做所需的时间而言,实现这些平常任务很是困难。常规表与索引优化能够持续到几小时或几天,某些状况下会致使按期维护变得不那么灵活。经过拆分的方法,每一个单独的“子库”能够单独维护。这样,管理更为简单,能够并行执行多个维护任务。 
l 较小的数据库速度更快。拆分的扩展性是显而易见的,它经过在网络中跨子库和服务器的分布式处理得以实现。还有一个较不明显的事实是,每一个子库库因其较小的尺寸从而在性能上赛过单个大的数据库。每一个子库都有本身的服务器,这样内存和磁盘之间比率大为提升,从而减小磁盘的I/O。这样带来的后果是更少的资源争夺,更优秀的联接操做的性能,更快的索引搜索,以及更少的数据库锁定。所以,不只拆分后的系统能够扩展到更高级别的容量,并且单个事务的性能也获得了提升。 
l 数据库拆分可以下降成本。大多数数据库拆分方案能够从成本较低的开源数据库中受益,甚至能够从“工做组”版的商业数据库中受益。此外,拆分数据库在商用多核心服务器硬件上工做的很好,而这种硬件的花费远低于昂贵的高端多处理器服务器和昂贵的存储区域网络(SAN)。在许可证、软件维护和硬件投资上节约的综合成本是很是可观的,相比其余解决方案,有时能够节约70%或者更多。毫无疑问,数据库拆分对许多组织而言是一个可行的方案,这已由很多大型在线销售商和软件即服务(SaaS)供应商的实践证实过了(巨头如亚马逊,易趣,固然还有谷歌)。 


5 数据库拆分的实用性 
若是数据库拆分具备高扩展性,花费更低的成本,而且提升了性能,为何该技术还没被普遍采用?它是否适合你的组织? 
事实上,数据库拆分是一项很是有用的技术,但像其余方案同样,要成功实施须要考虑不少因素。此外,还存在一些限制,而且数据库拆分并不能在全部类型的商业应用上良好运行。本章讨论了这些关键因素以及它们如何能获得解决。 
5.1 数据库拆分面临的挑战 
鉴于单个数据库分布的性质,一些关键因素必须加以考虑: 
- 可靠性。首先,任何生产经营性的商业应用都必须是可靠、容错的,且不能遭受频繁的断电。数据层一般是任一可靠性设计方案中最为关键的因素,数据库拆分的实施也不例外。事实上,鉴于多个拆分数据库分布的性质,一个设计优秀的方案显得尤其重要。为确保可靠性和容错性,须要具有如下几点: 
n 单个子库的自动备份 
n 子库冗余,确保每一个子库至少有2个实时的备份可在断电或服务器发生故障时接替其工做。这就须要一个高性能、高效率、可靠的复制机制。 
n 经济的硬件冗余,无论是服务器内部的硬件,仍是跨服务器的硬件。 
n 断电或服务器发生故障时自动故障切换。 
n 灾难恢复的站点管理 
- 分布式查询。 若是使用分布式查询并行处理模式,每一个子库单独进行查询,再将每一个子库的处理结果进行合并,那么许多类型的查询的处理速度会快上不少。这种技术使数据库性能得到数量级的提高,在不少状况下性能提升都在10倍或者更多。为了在应用程序上无缝地进行分布式查询,很重要的一点是须要一个设备对每一个子库的查询进行处理,而后将结果合并成一个结果集返回到应用层。能从这种分布式处理模式中受益的常见查询有: 
n 统计汇总,须要对整个系统的数据进行全面扫描。例如产品销售量计算一般要对整个数据库进行评估。 
n 支持复杂报表的查询,如给出某一指定商品的前一天、前一周或前一月的全部顾客的列表。 
- 避免跨子库的联接。在拆分系统中,跨子库使用内联的查询或其余语句效率很低,执行起来也很困难。在大多数状况下,若是采用的方法正确,实际上并不须要使用内联。主要技巧就是复制全局表,即那些相对不变化,一般用来与大型主表进行联接的对照表。那些包含状态代码、国家、类型甚至产品的表都属此类。咱们须要的是一个自动化的复制机制,以确保在全局表中的值在全部子库中是同步的,尽可能减小或消除跨子库联接。 
- 自增加键管理。数据库管理系统所提供的典型的自增加功能对每一条插入数据库的新行生成一个序号键。这对一个单数据库的应用程序来讲没有问题,但当使用数据库拆分技术时,必须对这些键值进行跨子库的协调管理。对此,咱们须要为应用程序提供一个跨子库运行的、无缝的、自动的方法来生成键值,以确保整个系统的键值都是惟一的。 
- 支持多个拆分方案。有一点很重要,就是据库拆分技术之因此有效,是由于它提供了一个面向应用的大规模扩展和性能改进技术。事实上,能够说拆分效果与拆分算法自己和应用程序面临的问题有多贴切是直接挂钩的。咱们须要的是一套多样、灵活的、的拆分方案,其中每个方案针对一个应用程序面临的特定问题。每个方案都具有固有的性能以及针对应用程序的特质和优点,或者其中之一。事实上,使用错误的拆分方案会限制性能,达不到预期效果。单个应用采用多个拆分方案,每一个方案用于应用程序的特定部分,从而得到优化的状况并不常见。如下列出了一些常见的拆分方案: 
n 基于会话的拆分。若是单个用户或进程在整个用户或进程的会话期间内,与一个具体的子库进行交互,则采用这种方案。这是最容易实现的拆分技术,对总体性能来讲几乎没有额外的开销,这是由于每一会话期只作一次拆分。从中受益的应用一般是以客户为中心的商业应用,每一个客户相关的全部数据都放在一个子库上。 
n 基于事务的拆分。断定子库的依据是检查给定事务的第一个SQL语句。这一般是经过评估语句中 “拆分键”的键值来完成(如订单号)。而后,将事务中其余全部的语句直接导向同一子库。 
n 基于语句的拆分。以语句为基础的拆分是全部拆分类型中最为进程密集型的一种,它评估每个SQL语句来肯定这条语句应该导入哪一个正确的子库。一样的,它一样须要对“拆分键”键值进行评估。这种拆分方案适合于数量大粒度小的事务,如记录通话记录。 
- 决定如何拆分数据的最佳方法。这是另外一领域,变化繁多,不一样的应用有不一样的选择。这与上述几种拆分方案的选择有很大的关系。有不少方法能够肯定如何拆分您的数据,但重要的是要知道您的事务频率,表的大小量,键值如何分布,以及您的应用的其余特性。知道了这些数据就能够肯定最优化的拆分策略: 
n 根据表的主键进行拆分。这是最直截了当的选择,也是映射到一个应用的最容易的方法。不过,只有当您的数据分布合理才会有效。例如,若是您按客户ID(这是一个顺序的数字型值)拆分数据库,而大多数事务是针对新客户的,那么拆分效果只是微乎其微。另外一方面,若是您选择一个能将用来合理天然的分发事务的键,则能够得到巨大的收益。 
n 按一个键的键值的模数拆分。这种方法应用很是普遍,它对键值取模,并根据模数分发事务。实际上,您能够预先设定任意数量的子库,而后取模函数会基于“循环”规则处理键值,使得新键值可以很是均衡地分布于整个数据库。 
n 维护子库索引主表。此项技术使用一个单独的主表,给不一样的子库分配不一样的值。这种方法很是灵活,适用面很广。可是,这种方法常常致使数据库性能不高,由于它须要对每个拆分后的SQL语句进行额外查询。 
由上可知,有不少因素须要考虑,也须要知足许多条件,才能确保数据库拆分可以成功并且有效,以达到提供经济的、更高级别的扩展能力和性能的目标。 
5.2 何时进行数据库拆分合适 
数据库拆分对许多类型的、有常规的数据库需求的商业应用来讲很是合适。它一样能够有效地应用于数据仓库应用,不过由于有不少产品和技术能够实现这方面应用,咱们就不在此详细讨论了。 
适合对数据库进行拆分的常规数据库需求以下: 
- 高度事务化的数据库应用 
- 混合任务的数据库应用 
n 频繁的读操做,包括复杂的查询和联接 
n 写操做密集型的事务(增删改查语句,包括插入、更新、删除) 
n 对于公共表和公共行,或者二者之一的资源争夺 
- 常规商业报表 
n 典型的“重复分段”报表的生成 
n 一些数据分析(混合了其余任务) 
要肯定数据库拆分是否适合您特定应用或环境,最重要的事情是评估您的数据库结构能拆分的多好。从本质上讲,数据库拆分是一种“横向”分区的方法,即单个表的行集(与列相反)分布在多个子库上。为了搞清楚针对于特定状况下断定拆分的好坏的依据,如下一些事情很是重要: 
- 找出您的数据库结构中全部事务密集型的表 
- 确认您的数据库目前处理的事务数量(或者是预期须要处理的事务数量) 
- 找出全部公用的SQL语句(选择、插入、更新、删除),确认每一个语句的使用量 
- 理解您的数据库结构的“表层次”,换句话说就是表之间的从属关系。 
- 肯定基于大容量表的事务的“键分布”状况,以肯定他们是否均匀地分布仍是集中于狭窄的区域内。 
有了以上信息,您能够对拆分您的应用的价值和适用性作一个快速的评估。举一个例子,这有一个简单的书店系统的数据库结构,显示了数据是如何进行拆分的: 



图3. 图例 书店系统数据库结构,显示了数据是如何进行拆分的 
在书店系统这个例子当中,主拆分表是“顾客”表。这是用来拆分数据的表。“顾客”表是子库的父表,“顾客订单”表和“订单书目详情”表是其子表。这些数据根据“顾客ID”属性进行拆分,全部子表中与指定“顾客ID”的行集都拆分的很好。那些全局表是公用的对照表,它们相对来讲操做较少,并被复制给全部的子库,以免跨子库的联接操做。 
虽然这个例子很是简单,但它提供了在决定如何对一个指定的数据库应用进行拆分时,应该考虑的基本因素。经过这样的评估方式,您就能够肯定拆分是否适用于您的特定环境,以及数据库拆分后所能带来的好处。 


6 结束语 
本文对数据库拆分作了一个概述,包括对数据拆分所面临挑战的讨论,以及完成一个数据拆分方案的基本方法。数据库拆分已经在许多大型组织中获得了证实,也会很好的适用于您的应用中所碰到的具体问题。只要正确使用,数据库拆分必定会帮助大量的商业事务应用实现得到低成本的、近于线性的扩展性能的目标。算法

相关文章
相关标签/搜索