分库策略

数据切分策略

根据时间段进行切分

最简单的切分方式,直接按数据创建时间进行切分,可水平切分为不同分表,也可使用分区表,但此种方案较适用于按时间维度进行查询的场景,并不适用于评价系统。

根据ID进行散列分表策略

这是较为常见的数据分表策略,是采用全局ID进行散列分布,使得数据均匀分布在不同表上,但此策略在评价系统上存在两个问题:

  • 原有数据需要进行迁移,按策略重新整理到不同表上
  • 当数据量增长到达一定程度时,表容量仍然存在到达上限的问题
  • 当数据量增长超过预期时,扩容又需要重新进行数据迁移
  • 分页查询逻辑复杂(DBA不允许使用merge表,同样union操作应该也不建议使用)

按ID增量区间进行切分

由于原有评价数据采用单表设计,为了不影响原有数据,可采用按增量区间切分的策略,如每1千万条数据或每1年数据存放一个分表。这种策略虽然可避免数据迁移,但会带来“热点”问题,也就是近期系统的读写都集中在最新的分表上,若分表存放在相同的物理节点上,会影响系统的性能。

按ID增量区间+ID散列进行切分

此种方案结合以上两种策略的优势,首先按增量区间切分可避免数据迁移及扩容问题,在区间内再按ID散列切分可避免“热点”问题,是一种较为“完美”的切分方案,但同样无法解决分页查询的问题。

 

全局ID生成策略

一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键生成机制。一方面,某个分区表自生成的ID无法保证在全局上是唯一的;另一方面,应用程序在插入数据之前需要先获得ID,以便进行SQL路由。以下为几种全局ID生成方案的比较:

采用UUID

使用UUID作主键是最简单的方案,但是缺点也是非常明显的。由于UUID非常的长,除占用大量存储空间外,最主要的问题是在索引上,在建立索引和基于索引进行查询时都存在性能问题。

根据一定规则生成ID

如商品库SPU ID,采用jvm id等多个参数按一定规则生成全局ID统。

维护sequence表生成ID

采用一个专门记录全局ID的数据表,每次生成ID时从此表读取+1,并随后更新之。此方案也较简单,但缺点同样明显,由于所有插入任何都需要访问该表,该表很容易成为系统性能瓶颈。另外,也需要控制多线程获取ID的锁问题。

另一种取巧的sequence表生成ID

同样采用一个专门记录全局ID的数据表,但利用mysql的replace into结合SELECT LAST_INSERT_ID()来获取ID,利用数据库自增长ID来避免应用程序对于多线程获取ID的锁控制。但该方案存在问题,由于replace into是执行delete和insert操作,在master-slave模式下,slave库的相应表的auto_increment不会相应更新,在master挂掉需要把slave提升为master时,将会出现主键冲突的问题。

posted @ 2015-06-09 17:16  感遇  阅读(220)  评论(0)    收藏  举报