MySQL读写分离(一)——sharding-jdbc

最后都变了- 提交于 2020-05-02 04:39:42

sharding-sphere是强大的读写分离、分表分库中间件,sharding-jdbc是sharding-sphere的核心模块。官方网站

springboot项目中集成sharding-jdbc也非常简单。

首先,引入sharding-jdbc和druid的jar包:

<!-- for spring boot -->
<dependency>
    <groupId>io.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>${sharding-sphere.version}</version>
</dependency>

<!-- for spring namespace -->
<dependency>
    <groupId>io.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-namespace</artifactId>
    <version>${sharding-sphere.version}</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.13</version>
</dependency>

在properties或者yml中配置读写分离:

sharding.jdbc.datasource.names=master,slave0,slave1
sharding.jdbc.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.master.driver-class=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.master.url=xxx
sharding.jdbc.datasource.master.username=xxx
sharding.jdbc.datasource.master.password=xxx
sharding.jdbc.datasource.master.max-active=100
sharding.jdbc.datasource.master.min-idle=10
sharding.jdbc.datasource.master.initial-size=10
sharding.jdbc.datasource.master.test-on-borrow=true

sharding.jdbc.datasource.slave0.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.slave0.driver-class=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.slave0.url=xx
sharding.jdbc.datasource.slave0.username=xx
sharding.jdbc.datasource.slave0.password=xx
sharding.jdbc.datasource.slave0.max-active=100
sharding.jdbc.datasource.slave0.min-idle=10
sharding.jdbc.datasource.slave0.initial-size=10
sharding.jdbc.datasource.slave0.test-on-borrow=true

sharding.jdbc.datasource.slave1.type=com.alibaba.druid.pool.DruidDataSource
sharding.jdbc.datasource.slave1.driver-class=com.mysql.cj.jdbc.Driver
sharding.jdbc.datasource.slave1.url=xx
sharding.jdbc.datasource.slave1.username=xx
sharding.jdbc.datasource.slave1.password=xx
sharding.jdbc.datasource.slave1.max-active=100
sharding.jdbc.datasource.slave1.min-idle=10
sharding.jdbc.datasource.slave1.initial-size=10
sharding.jdbc.datasource.slave1.test-on-borrow=true

sharding.jdbc.config.masterslave.name=ds-ms
sharding.jdbc.config.masterslave.master-data-source-name=master
sharding.jdbc.config.masterslave.slave-data-source-names=slave0,slave1

注意这段配置,除了前缀,后面部分都是druid连接池相关的参数。所以,如果你使用的不是 druid连接池,那么后面的参数也要根据连接池属性做相应的变更。 当然,如果你想配置更多连接池属性,也可以继续添加配置。

到这里,读写分离的配置就完成了,读写分离的功能已经实现了。具体什么情况下走master,什么情况下走slave,根据我的测试,直接写结论吧。

  • 如果不是事务方法,那么所有的查询都一定会走slave库;
  • 如果是事务方法,那么第一个insert/update/delete语句之前的查询都会走slave库,之后的所有sql语句都会走master库;

事务方法中,查询sql默认会走slave库,但是一旦遇到insert/update/delete语句,就会设置一个查询主库的标志,而这个对象是存在ThreadLocal中的,那么同一个线程中其后的所有sql都会在主库执行。

强制读主 有些情况下,查询语句需要强制在master上执行,可以通过代码实现:

Object result;
HintManager hintManager = HintManager.getInstance();
hintManager.setMasterRouteOnly();
try {
    result = xxxxx;
} finally {
    hintManager.close();
}
return result;

为了方便,我们可以通过aop和自定注解实现这一功能:


// 定义注解
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MasterRoute {
    //
}

// 定义aop
@Aspect
@Slf4j
@Component
public class MasterRouteAspect {
    @Around(value = "@annotation(me.heys.anno.MasterRoute)")
    public Object readMaster(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result;
        HintManager hintManager = HintManager.getInstance();
        hintManager.setMasterRouteOnly();
        try {
            result = joinPoint.proceed();
        } finally {
            hintManager.close();
        }
        return result;
    }
}

这样,只需要在强制读主的方法上加@MasterRoute注解即可实现强制读主。

sharding-jdbc更多用于分表分库,用它只进行读写分离,有点杀鸡用牛刀的感觉。后面会介绍如何通过mysql的驱动实现读写分离。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!