***部分:分库分库实现策略图1.数据库分库分表(分库)实现策略图1.分库中的分库准备阶段在分表(sharding)之前,开发者需要充分了解系统的业务逻辑和数据库架构。一个好的建议是画一个数据库ER图或者领域模型图,根据这个图来划分分片,直观易实现,保证开发者始终保持清醒的头脑。是选择数据库ER图还是领域模型图,要根据项目自身情况来选择。如果项目采用了数据驱动的开发方式,团队使用数据库ER图作为业务沟通的基础,自然会选择数据库ER图。如果项目采用领域驱动的开发方式,通过OR-Mapping模型构建好领域,那么领域模型图无疑是最好的选择。个人更喜欢使用领域模型图,因为切分更多的是基于业务的分析判断,而领域模型无疑更清晰直观。2.分析阶段1)。垂直分裂。垂直拆分的原则是将业务紧密、表与表之间关系密切的表进行拆分,比如同一模块的表。结合准备好的数据库ER图或者领域模型图,模仿活动图中的swimlane概念,一个swimlane代表一个shard,将所有表划分到不同的swimlane中。下面的分析示例演示了这种方法。当然你也可以直接在打印出来的ER图或者模型图上用铅笔画圈,一切看你自己的喜好。2).水平分片和垂直分片之后,还需要进一步分析分片中表的数据量和增长速度,来决定是否需要水平分片。2.1如果分在一起的表数据增长缓慢,产品上线后可以由一个数据库承载足够长的周期,则不需要水平切分,所有表都驻留在同一个shard上,所有表都是相关的会最大程度的保留,同时保证了写SQL的自由度,不容易被join、groupby、orderby等子句限制。2.2如果一起划分的表数据量巨大,增长速度很快,需要进一步水平划分。进一步水平分割是这样进行的:2.2.1.结合业务逻辑和表之间的关系,将当前分片划分为多个更小的分片。通常,这些较小的分片中的每一个都只包含一个主表(将使用此表ID进行哈希处理的表)和与其关联或间接关联的多个辅助表。这种一个分片一个主表,多个从表的情况是水平分片的必然结果。这样分裂之后,分片的数量会迅速增加。如果每个分片代表一个独立的数据库,那么管理和维护数据库会非常麻烦,而且这些小分片往往只有两三个表,因此为此新建一个数据库利用率不高。分片完成后,可以再次进行一次“反向Merge”,即两个或多个业务相似、数据增长率相近的分片(主表的数据量在同一个数量级)可以放在同一个数据库上,逻辑上还是独立的分片,有自己的主表,根据各自主表的ID进行hash,不同的是它们的hash取模(也就是节点数)必须始终如一。这样每个数据库节点上的表数量就比较平均了。2.2.2.当所有的表都被划分为合适的分片后,所有跨分片的表间关联都必须中断。在写SQL时,cross-shardjoin、groupby、orderby都会被禁止。层面协调解决这些问题。特别想提一点:水平分片后,分片的粒度往往比垂直分片的粒度更小。原来单一的垂直分片将细分为一个或多个以一个主表为中心或多个间接关联。副表的分片,此时的分片粒度与领域驱动设计中“聚合”的概念不谋而合,甚至可以说是完全一致。每个分片的主表是聚合中的聚合根!3、在实施阶段,如果项目在开发之初就决定分库分表,可以严格按照分析设计方案推进。如果在中期的架构演进中实现,除了搭建基础设施实现sharding逻辑(这个话题下一篇会讲),还需要对原始SQL进行逐条过滤分析,以及修改受分片影响的那些。sql。第二部分:示例演示本文选择了一个知名应用:jpetstore来演示在分析阶段如何进行sharding。由于一些个人原因,演示中使用的jpetstore来自ibatis官方原版的一个demo版本,SVN地址为:http://mybatis.googlecode.com/svn/tags/java_release_2.3.4-726/jpetstore-5。jpetstore的业务逻辑这里就不介绍了。这是一个非常简单的电子商务系统原型。其领域模型如下:由三个模块组成:用户、产品和订单。那么垂直细分方案就出来了。接下来,让我们看一下水平分割。如果从实际的宠物店出发,可能出现数据暴涨的单表应该是Account和Order,所以需要对这两个表进行横向切分。对于Product模块,如果是实际系统,Products和Items的数量不会很多,所以只需要垂直切分即可,即五张表(Product、Category、Item、Iventory、Supplier)在一个数据库上节点(不水平拆分,不会有两个以上的数据库节点)。但是作为演示,我们假设产品模块也有大量的数据需要我们做水平切分。从分析来看,这个模块需要拆分成两个shard:一个是(Product(main),Category),一个是(Item(main),Iventory,Supplier),同时,我们认为:这两个分片的数据增长率应该差不多,业务也很接近,所以我们可以把这两个分片放在同一个数据库节点上,Item和Product数据在哈希时取相同的模数。根据上面介绍的绘图绘制方法,我们得到如下sharding示意图:图3.jpetstoresharding示意图这张图补充几点:1.用泳道来表示物理分片(一个数据库节点)2.如果你splitvertically将导出的分片进一步水平分割,但如果是共享物理分片,则用虚线框起来,表示逻辑上是独立的分片。3.深色实体代表主表4.X代表需要打断的表间关系
