天天看點

MySQL讀寫分離(一)——sharding-jdbc

sharding-sphere是強大的讀寫分離、分表分庫中間件,sharding-jdbc是sharding-sphere的核心子產品。官方網站
MySQL讀寫分離(一)——sharding-jdbc

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,根據我的測試,直接寫結論吧。

  • sharding-jdbc是根據sql類型決定在master或者slave上面執行的,跟事務沒關系
  • 同一個方法中,遇到dml語句,那麼該語句和其後面的所有sql都會在主庫執行
查詢sql預設會走slave庫,但是一旦遇到dml語句,就會設定一個查詢主庫的标志,而這個對象是存在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的驅動實作讀寫分離。

繼續閱讀