来看下这篇文章,教你如何实现一个SpringBoot的Mybatis分库分表组件

如何设计这个组件?

在做这个组件之前,我想应该考滤如下几个问题

  • 我们不是对所有的插入的数据进行分库分表,我应该有一个标记来标记哪些插入的操作要进行分库分表。
  • 插入的数据应该分到哪张表?分库的时候我应该如何让数据更新散列的分到不同的表中。

对于第一个问题,因为这个组件是做的一个Spring一个分库分表的组件,我们大可使用SpringAop的特性来解决这个问题,比如:我自定义一个注解,只要在Mybatis的接口上标记了这个注解,在通过Spring Aop完美解决,那么在插入的时候我就需要分库分表的操作。

对于第二个问题,我可以采用Hash散列的方式来处理,在Java中的HashMap类中的put方法,我们完全可以借鉴这种思路。我想了解过HashMap源码的同鞋可能更加的清楚一些,在HashMap类中有一个hash的方扰动方法,这个方法中他把key的hash值进行了一个高半位和低半位的混合异或运算。这个便更好的增加随机性,更好的让数据均匀的散列。

可以看下下面这张图在使用了扰动函数后,数据分配的更加的均匀,这个可以更好的减少了hash碰撞。所以在解决第二个问题的时候,我们可以把这种Hash散列运用到数据库路由上。

代码实现

那我们先来解决第一个问题。如何让程序知道,我们在某个数据库操作的时候需要进行分库分表,这里涉及到知识有自定义注解和Spring AOP相关的

project
└─src
└─main
├─java
│  └─com
│      └─yqs
│          └─db
│              └─router
│                  ├─annotation
│                  ├─config
│                  ├─dynamic
│                  ├─strategy
│                  │  └─impl
│                  └─util
└─resources
└─META-INF

先来大致的分下包:

  • annotation 这个包下就是和注解相关的一些文件
  • config starter的自动配置类
  • dynamic 数据源的切换相关
  • stategy 计算被分到哪个库那个表策略相关的(这里用到的策略模式,在扩展功能时也很方便)
  • util 一些工具包,这里后面再说

注解讲解

先来看下在自定义注解中用到的元注解

  • Retention 标记当前注解的生命周期
  • Target 当前注解可以标记在哪些地方

Retention

注解有3种不同的生命周期 Class、Source、Runtime

  1. 注解只保留在源代码中,当把Java文件编辑成Class字节码的时候,此注解消失。
  2. 注解只保留在Class字节码中,当JVM在加载Class文件的时候,此注解消失。
  3. 注解在运行期间一直保留。

这个枚举类中就对应了上面说的三种生命周期

类型 描述
CLASS 注解只保留在Class字节码中,当JVM在加载Class文件的时候
SOURCE 注解只保留在源代码中
RUNTIME 注解在运行期间一直保留

Target

Target和上面说的那个注解一样,都是Java的元注解,Target注解标记当前注解可以标记在哪些位置,这里只看本文章用到的注解,注解也可以标记在不同的地方,比如 类、方法、字段、构造方法。

@Target({ElementType.TYPE,ElementType.METHOD})
复制代码

我想你一定在代码见过如上代码,此代码表明,当前的注解可以作用在方法,类上。加在其它的位置就会出现语法的错误。

在项目中使用此组件配置文件

我想在做这个项目之前应该先了解下这个组件的配置文件是什么样子的,这样在看后面的文章的时候可能更容易理解一些

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://ip:port/vipuser?useSSL=false

server.port=8080

mybatis.mapper-locations=classpath:mapper/*.xml

# 有几个库
db-router.db.datasource.dbCount=3
# 每一个库里有几个表
# 这里所说的表是相同的表比如有一个user表,
# 然后会多复制出几个相同的表比如命名成 user_01,user_02,user_03,user_04
db-router.db.datasource.tbCount=4
# 这个配置你可以理解成默认的数据源是哪一个
db-router.db.datasource.default=db00
# 这个配置是除了默认的数据源外的数据源
db-router.db.datasource.list=db01,db02
db-router.db.datasource.db00.driver-class-name=com.mysql.jdbc.Driver
db-router.db.datasource.db00.url=jdbc:mysql://ip:port/vipuser?useSSL=false
db-router.db.datasource.db00.username=root
db-router.db.datasource.db00.password=123456

db-router.db.datasource.db01.driver-class-name=com.mysql.jdbc.Driver
db-router.db.datasource.db01.url=jdbc:mysql://ip:port/vipuser?useSSL=false
db-router.db.datasource.db01.username=root
db-router.db.datasource.db01.password=123456

db-router.db.datasource.db02.driver-class-name=com.mysql.jdbc.Driver
db-router.db.datasource.db02.url=jdbc:mysql://ip:port/vipuser?useSSL=false
db-router.db.datasource.db02.username=root
db-router.db.datasource.db02.password=123456
复制代码

实现自定义注解

首页,我们上面说过要根据存入数据库的数据来计算将数据分配到哪个库哪张表里面。所以在定义这个注解的时候,我需要一个注解内的参数用来表明,根据哪个字段的数据计算所分配的库表。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface DBRouter {

    /**
     * 需要进行分表分库的字段
     * 通过此字段来计算分到哪个表哪个库
     * @return
     */
    String key() default 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值