在我们的应用里,有一张业务数据表,目前数据量大概在2-3亿,放在oracle的一张表里,并且一般是每年会翻倍,以前一直在同一张表里,前不久我们将他拆分为16个小的数据库(实际上目前只是在同一服务器的不同schema)里,见链接 。因为数据是和会员相关的,因此拆分规则很简单,根据会员计算hash值,然后确定数据拆分到哪一个数据库,这个业务从本上上是没问题的。
在我们的计划里,接下来是要将这张表的数据拆分到64个mysql数据库中去,按照预估,再怎么也能撑几年了,做到这份上,也差不多了,谁让这个世界变化太快呢?
因为采用的是开源的amoeba 方案,对于应用来说,很简单,直接将jdbc驱动换成mysql,链接地址修改一下就ok了,到目前为止非常完美。这是amoeba这个方案带来的好处,就是对应用透明。
但是,在考虑接下来的工作的时候,碰到一些麻烦。主要问题有几点:
*路由的规则是在amoeba服务器上,和业务完全隔离
一开始看来问题不大的,但是和其他团队的交流来看,有时候是需要业务逻辑来参与这个路由的过程的,在amoeba上实现感觉不是很干净
*由于整个表的数据量特别大,往mysql转换的时候时间太长
目前主表大概100多G,往mysql里转的时候由于没有合适的工具,估计只能由应用来做,这个过程比较漫长,这是一个线上的应用,停机去做代价太大了,不停机的话,也比较麻烦,估计只能先把大部分线下转换掉,然后切换的时候短暂停机,做增量的同步,不过这个增量也不小的,还需要仔细评估
因此,我们需要考虑oracle和mysql并存的可行性,这样就可以小部分小部分的转,不管怎样都可以减小风险,但是就目前看来,因为应用里使用到的sql有挺多oracle相关的语法,例如sequence啊,三层嵌套的分页查询之类的,这样看来,对应用透明的oracle/mysql并存方案不大可行
* 我们的应用规模这么大,迟早要服务化,现在的情况是 application -> amoeba -> db,如果再加上一个服务层,就变成了 application -> service -> amoeba -> db,又多了一层,虽然和服务化带来的好处来说,多一层的性能消耗是可以接受的,但是总是不爽
废话了这么多,不得不提一下当时我对拆分这张表的打算:
* 收拢所有访问这张表的DAO API,集中统一管理(这个做了,而且现在也享受到了)
* 将这张表的DAO先做成服务,远程对应用服务,就是 application->service->db
* 在service这一层处理数据拆分的逻辑,为此我还开发了一个原型ibatis-sharding ,基于ibatis提供数据库的sharding方案,理念类似hibernate-shards
在服务这一层来提供数据库拆分方案,和amoeba的方案来说,对比如下:
feature | ibatis-sharding | amoeba |
能实现数据库拆分 | Y | Y |
拆分逻辑对应用透明 | 半透明(Service) | Y |
拆分逻辑的灵活性 | 好 | 一般 |
能方便实现不同数据库并存 | 通过ibatis改进来实现 | 目前无法实现 |
(晕,这个表格怎么没法修改啊,想加一行都不行)
另外,从性能上对比,在服务化的情景下,amoeba是 : application -> service -> amoeba -> dbs,而使用ibatis-sharding,由于ibatis-sharding只是一个类库,是和service部署在一起的,因此是: application->service->dbs,这样反而是使用ibatis-sharding的方案更省一些,而且还能享受到路由规则贴近应用的好处,方便啊,灵活啊,呵呵
总的说来,大部分情况下使用amoeba是第一选择,因为透明,简单,而且性能好,不过在有些场景下,比如路由规则太复杂,需要不同数据库并存,或者是有service层的架构,使用应用层的实现方案可能会更好