Java开发2.0: 使用 Hibernate Shards 进行分片–Part.1

当关系数据库企图将TB级的数据存储在单一表中时,整体性能通常都会下降。对所有数据进行索引显然对读写都带来巨大代价。而NoSQL数据存储则特别适用于 大数据存储(想想Google的BigTable)。但NoSQL显然是非关系型的方案。对于偏爱关系数据库的ACID特性和固定结构的开发者。或者面对 不得不使用关系数据库项目时,分片将是一个令人激动的选项。

分片(Sharding)作为数据库分区(Patitioning)的的一个衍生。并非原生的数据库技术。而是在应用层的实现.在各种分片的实现中,Hibernate Shards可能是Java世界中最受欢迎的.假设你的分片化数据集使用POJO映射到逻辑数据库,那么这个乖巧的项目能让你几乎无缝地与其协同工作(“几乎”一次会在后面解释).使用Hibernate Shards时,你不需要明确地将POJO映射到分片中,只需要像对其他关系数据库一样按Hibernate的方式进行映射。Hibernate Shards会自动帮你处理底层的分片工作。

本系列前面的内容中,我已经使用基于模拟赛跑及其选手的简单领域模型来说明各种数据存储技术.这一次,我还会用这个熟悉的例子来介绍特定的分片策略,然后通过 Hibernate Shards来实现它.值得注意的是,分片所带来的工作量影响并不一定是来自Hibernate.实际上,使用Hibernate Shards的编码工作是最简单的部分.真正的难题在于搞清楚该对什么切分,以及如何切分。

分片简介

数据库分区 (Partioning)是一个本质上关系型的处理过程,将一个表的不同列按照数据的某种逻辑片段划分成小块。假设你将一个大表foo按照时间戳进行分区,举例来说,2010年8月之前的数据将存放在分区A,其后的数据将存放在分区B,以此类推。数据库分区能够使读写操作更快,因为数据集被拆分到不同分区中去。

数据库分区并非处处支持(MySQL直到5.1 开始才支持),而且商业系统中实现的代价可能难以承受。其次,大多数数据库分区的实现方方案实际上将数据存储在同一物理机器上,所以你仍然受到硬件的限 制。 可见,数据库分区并未解决对硬件的依赖。所以,许多聪明人开始寻找新的扩展方式。

分片本质上是数据库层的分区:不是将一个表的行拆分为多块数据,而是将数据本身按照逻辑数据单元进行切分(通常横跨多个物理机器)。换句话说,分片不是将表切分为小块,而是将整个数据库切分为小块。

分片的典型案例,是将存放全球客户数据的大型数据库按照地区进行划分:片区A用于美国的客户,B用于亚洲的,而C用于欧洲,以此类推。不同分片存储在不同机器上,每个分片自身包含有所有(客户)相关的数据,如客户喜好和订单历史记录。

分 片(正如数据库分区)的好处在于,使大数据变的小巧:每个分片上的独立表规模更小,提供了更快的读写速度,也就提高了性能。可以想象得到,分片客观上也提 高了可靠性,因为即使一个分片意外失效,其他片仍然可以提供数据服务。另外,由于分片是应用层的实现方案,你也可以将它应用在不支持传统分区的数据库上。 而且,其潜在的经济成本也更低。

分片及策略

正如大多数技术,分片也有其代价。由于分片并非原生的数据库技术--也就是说,你必须在应用层实现它--因此,在开始之前就必须确定好映射策略。主键和跨片区查询在这里都扮演了重要角色,主要是这两者给你带来了约束。

主键

分 片支撑了多个数据库,使它们在互不知晓的情况下自行运作。正因为这样,如果你依赖了数据库序列(如用它来自动产生主键),就可能在多个数据库间产生了 唯一主键。在分布数据库中对序列进行协调并非不可行,但这样就增加了系统复杂性。避免重复主键产生的最安全做法,是让你的应用本身(归根结底是应用在管理 分片)产生主键。

跨片区查询

大 多数分片的实现(包括Hibernate Shards在内)都不允许跨片区的查询,这就意味着如果需要处理来自不同片区的两个数据集,就不得不花额外的功夫。(有趣的是,亚马逊的 SimpleDB也不支持跨域查询。)举例来说,如果你将美国的客户数据存放在片区1,则所有与其相关的数据也必须存放在片区1。如果你想把他们放在片区 2,事情将会复杂化,系统性能也很可能受影响。这一场景也与前面的结论有关--如果你不得不做跨片区的连接,那最好采用能够避免重复可能性的方式来管 理主键。

策略示例

正因为分片将你绑定到一个线性数据模型上(也就是说,你没办法轻易与其他片中的数据进行连接),所以你必须有一幅各个片中数据如何按照逻辑进行组织的清晰蓝图,并以此为基础。

就 客户数据而言,你可以按照地理位置(欧洲,亚洲,非洲等)进行分片, 也可以按照其他维度,这都取决于你。然而,你的分片策略必须将数据在不同片区中均匀分布。分片的理念在于将大数据集划分为小数据集;因此,如果某个特 定的电子商务系统含有大量欧洲客户以及相对少的美国客户,那么按照客户地理位置进行分片恐怕意义不大。

用分片处理赛跑数据!

回 到我的赛跑应用例子(作者在同一系列前几篇文 章使用的一个例子)上来,我可以选择按照赛事或者按照选手来进行分片。在这种情况下,我选择按照赛事切分,因为我留意到域模型是按照参加不同赛事的 选手进行组织的。因此赛事是我的领域模型的根源。我还打算按照赛程进行切分,因为我的赛跑应用包含大量不同赛程的赛事,其中又包含大量参赛的选手。

需 要注意的是,在作出以上种种决策的同时,我也接受了其代价:如果一个参赛选手同时参加了多项赛事,每项赛事又存储在不同分片中呢?Hibernate Shards(正如其他大多数分片实现方案)并不支持跨片区连接。我将不得不接受这一稍微的不便,允许选手们在不同片区中同时存在--也就是说,我会 在该选手参与的赛事存储的所有片区中都重新创建该选手的数据。

为了便于说明,我只创建两个片区:赛程小于10英里的赛事为一个,赛程大于10英里的为另一个。

 

 

英文原文:developerworks,编译:ImportNew——郑玮

译文链接:http://www.importnew.com/3705.html

【如需转载,请在正文中标注并保留原文链接、译文链接和译者等信息,谢谢合作!】

 

关于作者: 郑玮

IT民工,会点英语

查看郑玮的更多文章 >>



相关文章

发表评论

Comment form

(*) 表示必填项

还没有评论。

跳到底部
返回顶部