数据库读写分离解决方案介绍

概述

读写分离要做的事情就是决定一条 SQL 该到哪个数据库去执行,至于谁来做决定数据库这件事,要么数据库中间件去做,要么应用程序自己去做。首先针对应用程序自己去做的场景,读写分离的职责应该属于数据访问层而不是业务层,其次读写分离不应该入侵到代码中。因此在 Service—DAO—ORM— 数据库驱动的调用链中,要想做到代码弱入侵性或者零入侵性,只能将读写分离写在 ORM 层或者数据库驱动层,写在 ORM 层就和具体 ORM 框架耦合,写在数据库驱动层,就和具体数据库耦合。至于在 ORM 层还是在数据库驱动层实现读写分离,主要看更换 ORM 框架和数据库哪个成本更高和实现的难易程度。一般来讲,读写分离的核心方案主要有以下几种:

  • 第一种构建多套环境,优势是方便控制也容易集成一些简单的分布式事务,缺点是非动态同时代码量较多,配置难度大;
  • 第二种是依靠数据库中间件(例如:MyCat),由中间件做读写分离,优势是对整个应用程序都是透明的,缺点是降低性能,不支持多数据源事务;
  • 第三种是应用程序自己去做,例如使用支持读写分离的数据库驱动、使用 Spring 原生提供的 AbstractRoutingDataSource。后者需要控制只读事务和读写事务切换到主库,写操作切换到主库,读操作切换到从库;同时保证单个事务里面所有的 SQL 都是在同一个数据源里执行。缺点是多数据源的配置不灵活,不支持多数据源事务。具体实现方式可参考 基于 Service 层的 Spring 路由数据源 + AOP / Annotation基于 ORM 层的 Spring 路由数据源 + Mybatis 插件 / Annotation

读写分离解决方案

客户端解决方案

方案概述

  • 客户端解决方案(持久化层):TDDL、ShardingSphere-JDBC

优缺点

  • 优点

    • 数据源方便由应用直接管理
    • 运维不需要额外维护中间件
    • 理论上支持任何数据库(SQL 标准)
  • 缺点

    • 增加了开发成本、对代码有一定的入侵性
    • 不能做到动态增加数据源
    • 开发人员开发完成后,运维人员参与不了

中间件解决方案

方案概述

  • 中间件解决方案(代理层):MySQL Proxy、MyCat、Altas

优缺点

  • 优点

    • 持久化层不需要管数据库方面的事情
    • 数据源增加了对应用没有任何影响(不需要重启应用)
  • 缺点

    • 应用依赖了中间件,导致切换数据库变得困难
    • 增加了 Proxy 中间件,导致数据库性能下降
    • 增加了维护难度、高可用等问题

读写分离最佳实践

ShardingSphere

ShardingSphere 是 Apache 的一款分布式的数据库生态系统,它包含两大产品:ShardingSphere-Proxy、ShardingSphere-JDBC。值得一提的是,ShardingSphere-JDBC 提供了读写分离、数据分片等功能的支持。

ShardingSphere-Proxy

ShardingSphere-Proxy 被定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。代理层介于应用程序与数据库间,每次请求都需要做一次转发,请求会存在额外的时延。这种方式对于应用非常友好,应用基本零改动,和语言无关,可以通过连接共享减少连接数消耗。

ShardingSphere-JDBC

ShardingSphere-JDBC 是 ShardingSphere 的第一个产品,也是 ShardingSphere 的前身,业界经常简称之为 Sharding-JDBC。它定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使用客户端直连数据库,以 Jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

  • 适用于任何基于 JDBC 的 ORM 框架,如:JPA、Hibernate、Mybatis、Spring JDBC Template 或直接使用 JDBC。
  • 支持任何第三方的数据库连接池,如:C3P0、DBCP、HikariCP、BoneCP 等。
  • 支持任意实现 JDBC 规范的数据库,目前支持 MySQL、PostgreSQL、Oracle、SQL Server 以及任何可使用 JDBC 访问的数据库。

Dynamic-Datasource

Dynamic-Datasource 是 MyBatis-Plus 官方的读写分离框架。如果数据源较少,场景不复杂,不需要使用多数据源事务,可以选择上述任意一种读写分离方案。如果需要更多特性,又不想引入数据库中间件,可尝试 Dynamic-Datasource,具体的使用方式建议阅读 官方文档一官方文档二开源中国介绍

  • 优势:

    • 项目启动后支持动态增减数据源
    • 简化 Druid 和 HikariCp 配置,提供全局参数配置
    • 提供自定义数据源来源(默认使用 yml 或 properties 配置)
    • 数据源分组,适用于多种场景,包括纯粹多库、读写分离、一主多从、多主多从、混合模式
    • 使用 Spel 动态参数解析数据源,如从 session,header 和参数中获取数据源。(多租户架构神器)
    • 简单集成 Druid 数据源监控多数据源,简单集成 Mybatis-Plus 简化单表,简单集成 P6sy 格式化 SQL,简单集成 Jndi 数据源
    • 使用正则匹配或 Spel 表达式来切换数据源(实验性功能)
    • 默认支持通过 @DS 注解来动态选择数据源(代码入侵性强),额外支持使用 MyBatis 插件在 ORM 层实现纯读写分离(代码零入侵性),但两者不能同时使用
    • 使用 @DS 注解的时候,支持多层数据源嵌套切换。(一个业务 ServiceA 调用 ServiceB,ServiceB 调用 ServiceC,每个 Service 都是不同的数据源)
  • 劣势

    • 不支持多数据源事务(同一个数据源下支持事务),网上绝大多数普通方案(基于 Spring 路由数据源 )也都不能支持
    • 如果需要使用到分布式事务,那么架构应该到了微服务化的时候
    • 提示:如果项目中只有几个数据库,但是有强烈使用分布式事务的需求,建议还是使用传统方式自己构建多套环境集成 Atomic 这类方案
  • 约定

    • 只做切换数据源这件核心的事情,并不限制具体操作,切换了数据源可以做任何 CRUD 操作
    • 配置文件中所有以下划线 _ 分割的数据源,首部即为组的名称,相同组名称的数据源会放在一个组下
    • 切换数据源即可以是组名,也可以是具体数据源名称,切换时默认采用负载均衡机制切换
    • 默认的数据源名称为 master,可以通过 spring.datasource.dynamic.primary 修改
    • 方法上的注解优先于类上注解

扩展阅读

其他开源项目

MySQL 其他中间件介绍

企业实现 MySQL 读写分离与分库分表的其他中间件如下:

  • MySQL-Proxy(Oracle)
  • MySQL-Router(Oracle)
  • Atlas (Qihoo 360)
  • Atlas-sharding (Qihoo 360)
  • Cobar(是阿里巴巴 B2B 部门开发)
  • MyCat(基于阿里开源的 Cobar 产品而研发)
  • TDDL Smart Client 的方式(淘宝)
  • Oceanus(58 同城数据库中间件)
  • OneProxy(原支付宝首席架构师楼方鑫开发)
  • Vitess(谷歌开发的数据库中间件)
  • Heisenberg(百度)
  • TSharding(蘑菇街白辉)
  • xx-dbproxy(金山的 Kingshard、当当网的 Sharding-Jdbc )
  • ProxySQL(国外开源的 MySQL 中间件)
  • amoeba

MySQL 常用解决方案总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
MySQL 复制方案:
1.一主一从,高可用
2.一主一从,读写分离
3.一主多从,读写分离
4.一主多从,负载均衡
5.主主复制,双写
6.主主复制,单写
7.双主双从

MySQL 高性能架构方案:
1.代码级别
2.读写分离架构(读性能较高)
MySQL Proxy(Atlas、mysql router、proxySQL、maxscale、amoeba、xx-dbproxy等)
3.分布式架构(读写性能都提高)
分库分表--->Cobar--->TDDL(头都大了)--->DRDS
Mycat---->DBLE自主研发等
NewSQL--->TiDB

MySQL 高可用架构方案:
单活:MMM架构--->mysql-mmm(Google)
单活:MHA架构--->mysql-master-ha(日本DeNa),T-MHA
多活:MGR架构--->mysql 5.7新特性 MySQL Group Replication(5.7.17)--->Innodb Cluster
多活:
Percona XtraDB Cluster(PXC)
MySQL Cluster(Oracle RAC)
MariaDB Galera Cluster

Oracle 高可用架构方案:
1.RAC
2.DG
3.OGG

参考文献