数据库分库分表方案

数据库的拆分方式有两种:水平拆分和垂直拆分。水平拆分关注的单表数据量过大的问题,对于上千万过亿行数据的表来说,单表数据量过大,查询和变更的成本会变大,同时单库的吞吐量也会达到瓶颈,会同时对业务造成影响。水平拆分的目的就是为了将单表拆分为多表,每个表仍包含原有的数据结构。而垂直拆分关注的是表结构的拆分,我们需要根据业务的维度,将原本一个表拆分为多个表,其中每个表的结构与原表不同,这样不同的业务就可以根据需要访问不同的表,提高查询和修改的效率,当然,这同时也会带来一些问题,就是分布式事务的问题,这个问题我们在后面详细讨论。

根据如何切片,分库分表的方案一般分为三大类:客户端分片、代理分片以及支持事务的分布式数据库。下面我们来分别讨论:

(1)客户端分片

就数据库分片逻辑来说,方法其实很简单,我们利用分表键的值进行hash分片,也可以根据分表键进行范围分片(例如根据天来划分,其实就是将一天的数据划分到单张表中),还有很多其他定制的分片方法等。对数据库分片其实很简单,问题核心在于我们应用如何访问分库分表以后的数据,也就是分库分表后的路由规则。而客户端分片的方式是在应用层直接操作分片逻辑,每个应用都嵌入一个操作分片的逻辑实现,一般是通过jar依赖,业务在使用的时候直接依赖我们提供的jar包即可,在jar中我们提供跟基本操作数据库一样的操作方法,让业务对底层分库分表的路由和数据聚合无感知。

具体实施方式有三种:应用层直接实现,定制jdbc以及定制orm框架:

a、应用层直接实现

        改方法在应用层直接读取分片规则,然后解析规则,根据分片规则找到路由逻辑,应用层在每次操作的时候都知道要连接哪个数据库,以及那些表等,而我公司就是采用这种方法,改方法实现起来简单,可以快速上线应用,而且分片逻辑自己维护,出现问题也便于快速定位和解决。给个具体的例子如下: 

如图所示,业务应用在链接数据库的时候,首先会向规则服务器发起请求,找到其目标数据库的路由规则,然后通过该路由规则分别连上分片的DB,在获得数据后在应用内部进行数据聚合并返回给应用接口。当然这里路由规则可以使用本地缓存,不然每次连接都发起请求会造成规则服务器压力增大,同时也会增大应用跟数据库的交互时间,影响用户体验。但是,当分库分表的路由规则发生变化的时候怎么办呢?我就希望规则服务器可以将变更的信息推送到我们应用,让应用更新本地缓存。当然,这样又会让我们觉得我们对应用有了侵入,所以,我们公司在做规则保存和动态便跟的时候专门开发了一款动态配置信息变更的应用。后来该应用不仅用来做数据库分库分表规则的动态配置,后续很多的应用也在使用,后面我们再详细介绍。

b、通过定制jdbc协议

我们同样可以通过定制jdbc协议来实现我们的需求,让分库分表的逻辑在jdbc内部实现。这种方式虽然不对业务入侵,但是开发者必须要理解jdbc协议才能实现分库分表逻辑,sharding jdbc就是采用这种方式。

c、通过定制orm框架实现

我们也可以通过定制orm框架,将分片规则实现到orm中,可以通过在mybatis配置文件的sql中增加表索引参数来实现,单是改方式不够系统化,同时要求业务方自己配置,后续很难管理,除了问题很难排查。

(2)代理分片

代理分片很好理解,就是我们再应用和DB之间加一层代理,分片路由规则放在代理,有代理帮助我们去做路由和数据聚合。但是这种方式是增加了代理,会对性能有影响,毕竟中间加了一层网络传输,同时,我们还需要维护一套代理服务器,增加了成本,而且还要保证代理服务的可以,也会增加成本和开发运维的难度。

(3)支持事务的分布式数据库

这个就牛逼了,阿里的OceanBase就是支持分布式事务的数据库,其内部完全对使用者透明,用户完全不用关心起内部如何弹性伸缩,如何实现分布式事务,用就好了。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章