数据库中间件-主流设计

1 数据库中间件的作用

在未进行读写分离/分库分表的情况下,我们是直接在应用中通过数据源(c3p0、druid、dbcp2等)与数据库建立连接,进行读写操作,架构如下所示:
在这里插入图片描述
可以看到在操作单库单表的情况下,我们是直接在应用中通过数据源(c3p0、druid、dbcp等)与数据库建立连接,进行读写操作。
大部分开发人员对于访问单库的应用的架构都是很熟悉的。但是在进行读写分离/分库分表后,底层的数据库实例就会有多个,读写分离情况下一个master多个slave;分库分表的情况下,有多个不同的分库。
从应用的角度来说,除了要与多个不同的数据库建立连接,还需要处理分库分表/读写分离特定场景下的问题:

  • 在读写分离的情况下,应用需要对读sql/写sql进行区分,读sql走从库,写sql走主库,并考虑主从同步延迟、高可用等一系列问题。
  • 在分库分表的情况下,应用需要能对sql进行解析、改写、路由、结果集合并等一些操作,以及分布式事务、分布式id生成等。

这无疑是个复杂的工作,而数据库中间件的作用,是让开发人员可以像操作单库单表那样去操作数据库,屏蔽底层复杂的实现。

2 数据库中间件设计方案

典型的数据库中间件设计方案有2种:服务端代理(proxy:代理数据库)、客户端代理(datasource:代理数据源)。下图演示了这两种方案的架构:
在这里插入图片描述
可以看到不论是代理数据库还是代理数据源,底层都操作了多个数据库实例。不同的是:

  • 服务端代理:

    我们独立部署一个代理服务,这个代理服务背后管理多个数据库实例。而在应用中,我们通过一个普通的数据源(c3p0、druid、dbcp等)与代理服务器建立连接,所有的sql操作语句都是发送给这个代理,由这个代理去操作底层数据库,得到结果并返回给应用。在这种方案下,分库分表和读写分离的逻辑对开发人员是完全透明的。

  • 客户端代理:

    应用程序需要使用一个特定的数据源,其作用是代理,内部管理了多个普通的数据源(c3p0、druid、dbcp等),每个普通数据源各自与不同的库建立连接。应用程序产生的sql交给数据源代理进行处理,数据源内部对sql进行必要的操作,如sql改写等,然后交给各个普通的数据源去执行,将得到的结果进行合并,返回给应用。数据源代理通常也实现了JDBC规范定义的API,因此能够直接与orm框架整合。在这种方案下,用户的代码需要修改,使用这个代理的数据源,而不是直接使用c3p0、druid、dbcp这样的连接池。

3 主流的数据库中间件实现对比

无论是代理数据库,还是代理数据源,二者的作用都是类似的。以下列出了这两种方案目前已有的实现以及各自的优缺点:
在这里插入图片描述

数据库代理

目前的实现方案有:阿里巴巴开源的cobar,mycat团队在cobar基础上开发的mycat,mysql官方提供的mysql-proxy,奇虎360在mysql-proxy基础开发的atlas。目前除了mycat,其他几个项目基本已经没有维护。
优点:多语言支持。也就是说,不论你用的php、java或是其他语言,都可以支持。原因在于数据库代理本身就实现了mysql的通信协议,你可以就将其看成一个mysql 服务器。mysql官方团队为不同语言提供了不同的客户端驱动,如java语言的mysql-connector-java,python语言的mysql-connector-python等等。因此不同语言的开发者都可以使用mysql官方提供的对应的驱动来与这个代理服务器建通信。
缺点:实现复杂。因为代理服务器需要实现mysql服务端的通信协议,因此实现难度较大。

数据源代理

目前的实现方案有:阿里巴巴开源的tddl,大众点评开源的zebra,当当网开源的sharding-jdbc。需要注意的是tddl的开源版本只有读写分离功能,没有分库分表,且开源版本已经不再维护。大众点评的zebra开源版本代码已经很久更新,基本上处于停滞的状态。当当网的sharding-jdbc目前算是做的比较好的,代码时有更新,文档资料比较全。

优点:去中心化,更加轻量,可以与任何orm框架整合。这种方案不需要实现mysql的通信协议,因为底层管理的普通数据源,可以直接通过mysql-connector-java驱动与mysql服务器进行通信,因此实现相对简单。
缺点:仅支持某一种语言。例如tddl、zebra、sharding-jdbc都是使用java语言开发,因此对于使用其他语言的用户,就无法使用这些中间件。版本升级困难,因为应用使用数据源代理就是引入一个jar包的依赖,在有多个应用都对某个版本的jar包产生依赖时,一旦这个版本有bug,所有的应用都需要升级。而数据库代理升级则相对容易,因为服务是单独部署的,只要升级这个代理服务器,所有连接到这个代理的应用自然也就相当于都升级了。

ORM框架代理

目前有hibernate提供的hibernate-shards,也可以通过mybatis插件的方式编写。相对于前面两种方案,这种方案可以说是只有缺点,没有优点。

我的设计

在这里插入图片描述
1、最上层的是ShardDataSource,用于进行分库分表。ShardDataSource包含了若干个GroupDataSource,每个连接的数据库集群相当于1个分片(Shard)。

2、中间一层是GroupDataSource,主要用于读写分离。下面通过一组SingleDataSource连接一个数据库服务组集群,分为一个主和若干个从。

3、最下一层是SingleDataSource,主要用于和mysql集群中的单个mysql实例直接建立连接。支持6种连接池:dbcp、dbcp2、druid、tomcat-jdbc、c3p0,hikaricp。用户无需直接使用SingleDataSource。

ShardDataSource、GroupDataSource都实现了JDBC协议的javax.sql.DataSource接口,因此你可以把二者都当做一个普通的数据库连接池来使用。所有读写分离、分库分表的底层实现逻辑,都对用户进行了屏蔽。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值