1. 程式人生 > >spring boot使用sharding jdbc的配置--讀寫分離

spring boot使用sharding jdbc的配置--讀寫分離

說明

  • 要排除DataSourceAutoConfiguration,否則多資料來源無法配置
@SpringBootApplication
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
    
}
  • 配置的多個數據源交給sharding-jdbc管理,sharding-jdbc建立一個DataSource資料來源提供給mybatis使用

步驟

  • 配置多個數據源,資料來源的名稱最好要有一定的規則,方便配置分庫的計算規則
@Bean(initMethod="init", destroyMethod="close", name="dataSource0")
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource0(){
    return new DruidDataSource();
}

@Bean(initMethod="init", destroyMethod="close", name="dataSource1")
@ConfigurationProperties(prefix = "spring.datasource2")
public DataSource dataSource1(){
    return new DruidDataSource();
}
  • 配置資料來源規則,即將多個數據源交給sharding-jdbc管理,並且可以設定預設的資料來源,當表沒有配置分庫規則時會使用預設的資料來源
@Bean
public DataSourceRule dataSourceRule(@Qualifier("dataSource0") DataSource dataSource0, 
        @Qualifier("dataSource1") DataSource dataSource1){
    Map<String, DataSource> dataSourceMap = new HashMap<>();
    dataSourceMap.put("dataSource0", dataSource0);
    dataSourceMap.put("dataSource1", dataSource1);
    return new DataSourceRule(dataSourceMap, "dataSource0");
}
  • 配置資料來源策略和表策略,具體策略需要自己實現
@Bean
public ShardingRule shardingRule(DataSourceRule dataSourceRule){
    //表策略
    TableRule orderTableRule = TableRule.builder("t_order")
            .actualTables(Arrays.asList("t_order_0", "t_order_1"))
            .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))
            .dataSourceRule(dataSourceRule)
            .build();
    TableRule orderItemTableRule = TableRule.builder("t_order_item")
            .actualTables(Arrays.asList("t_order_item_0", "t_order_item_1"))
            .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))
            .dataSourceRule(dataSourceRule)
            .build();
    //繫結表策略,在查詢時會使用主表策略計算路由的資料來源,因此需要約定繫結表策略的表的規則需要一致,可以一定程度提高效率
    List<BindingTableRule> bindingTableRules = new ArrayList<BindingTableRule>();
    bindingTableRules.add(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule)));
    return ShardingRule.builder()
            .dataSourceRule(dataSourceRule)
            .tableRules(Arrays.asList(orderTableRule, orderItemTableRule))
            .bindingTableRules(bindingTableRules)
            .databaseShardingStrategy(new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()))
            .tableShardingStrategy(new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()))
            .build();
}
  • 建立sharding-jdbc的資料來源DataSource,MybatisAutoConfiguration會使用此資料來源
@Bean("dataSource")
public DataSource shardingDataSource(ShardingRule shardingRule){
    return ShardingDataSourceFactory.createDataSource(shardingRule);
}
  • 需要手動配置事務管理器(原因未知)
//需要手動宣告配置事務
@Bean
public DataSourceTransactionManager transactitonManager(@Qualifier("dataSource") DataSource dataSource){
    return new DataSourceTransactionManager(dataSource);
}
  • 分庫策略的簡單實現,介面:DatabaseShardingAlgorithm
import java.util.Collection;
import java.util.LinkedHashSet;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.SingleKeyDatabaseShardingAlgorithm;
import com.google.common.collect.Range;

/**
 * Created by fuwei.deng on 2017年5月11日.
 */
public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Long> {

    @Override
    public String doEqualSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) {
        for (String each : databaseNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
    
    @Override
    public Collection<String> doInSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(databaseNames.size());
        for (Long value : shardingValue.getValues()) {
            for (String tableName : databaseNames) {
                if (tableName.endsWith(value % 2 + "")) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
    
    @Override
    public Collection<String> doBetweenSharding(Collection<String> databaseNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(databaseNames.size());
        Range<Long> range = (Range<Long>) shardingValue.getValueRange();
        for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : databaseNames) {
                if (each.endsWith(i % 2 + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }

}
  • 分表策略的基本實現,介面:TableShardingAlgorithm
import java.util.Collection;
import java.util.LinkedHashSet;

import com.dangdang.ddframe.rdb.sharding.api.ShardingValue;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.SingleKeyTableShardingAlgorithm;
import com.google.common.collect.Range;

/**
 * Created by fuwei.deng on 2017年5月11日.
 */
public class ModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {

    @Override
    public String doEqualSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
    
    @Override
    public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        for (Long value : shardingValue.getValues()) {
            for (String tableName : tableNames) {
                if (tableName.endsWith(value % 2 + "")) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
    
    @Override
    public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        Range<Long> range = (Range<Long>) shardingValue.getValueRange();
        for (Long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : tableNames) {
                if (each.endsWith(i % 2 + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }

}
  • 至此,分庫分表的功能已經實現

讀寫分離

  • 讀寫分離需在建立DataSourceRule之前加一層主從資料來源的建立
// 構建讀寫分離資料來源, 讀寫分離資料來源實現了DataSource介面, 可直接當做資料來源處理. 
// masterDataSource0, slaveDataSource00, slaveDataSource01等為使用DBCP等連線池配置的真實資料來源
DataSource masterSlaveDs0 = MasterSlaveDataSourceFactory.createDataSource("ms_0", 
                    masterDataSource0, slaveDataSource00, slaveDataSource01);
DataSource masterSlaveDs1 = MasterSlaveDataSourceFactory.createDataSource("ms_1", 
                    masterDataSource1, slaveDataSource11, slaveDataSource11);

// 構建分庫分表資料來源
Map<String, DataSource> dataSourceMap = new HashMap<>(2);
dataSourceMap.put("ms_0", masterSlaveDs0);
dataSourceMap.put("ms_1", masterSlaveDs1);

// 通過ShardingDataSourceFactory繼續建立ShardingDataSource
  • 強制使用主庫時
HintManager hintManager = HintManager.getInstance();
hintManager.setMasterRouteOnly();
// 繼續JDBC操作

強制路由

  • 使用ThreadLocal機制實現,在執行資料庫操作之前通過HintManager改變用於計算路由的值
  • 設定HintManager的時候分庫和分表的策略必須同時設定,並且設定後需要路由的表都需要設定用於計算路由的值。比如強制路由後需要操作t_order和t_order_item兩個表,那麼兩個表的分庫和分表的策略都需要設定
HintManager hintManager = HintManager.getInstance();
hintManager.addDatabaseShardingValue("t_order", "user_id", 1L);
hintManager.addTableShardingValue("t_order", "order_id", order.getOrderId());
hintManager.addDatabaseShardingValue("t_order_item", "user_id", 1L);
hintManager.addTableShardingValue("t_order_item", "order_id", order.getOrderId());

事務

  • sharding-jdbc-transaction實現柔性事務(預設提供了基於記憶體的事務日誌儲存器和內嵌非同步作業),可結合elastic-job(sharding-jdbc-transaction-async-job)實現非同步柔性事務
  • 沒有與spring結合使用的方式,需要自己封裝

相關推薦

spring boot使用sharding jdbc配置--分離

說明 要排除DataSourceAutoConfiguration,否則多資料來源無法配置 @SpringBootApplication @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}

mysql+spring+mybatis實現資料庫分離[程式碼配置]

場景:一個讀資料來源一個讀寫資料來源。 原理:藉助spring的【org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource】這個抽象類實現,看名字可以瞭解到是一個路由資料來源的東西,這個類中有一個方法

spring MVC、mybatis配置分離,ReplicationDriver(轉載)

讀寫 就是 actor 只讀 完成後 方法 -o pass 執行 環境: 3臺數據庫機器,一個master,二臺slave,分別為slave1,slave2 2.要實現的目標: ①使數據寫入到master ②讀數據時,從slave1和s

使用Spring AOP實現MySQL分離

npr getclass mod rac ava nfa release box port spring aop , mysql 主從配置 實現讀寫分離,下來把自己的配置過程,以及遇到的問題記錄下來,方便下次操作,也希望給一些朋友帶來幫助。mysql主從配置參看:http:

sharding-JDBC 實現分離

aso engine lec bus manage 均衡 map 如果 use 需求 一主兩從,做讀寫分離。 多個從庫之間實現負載均衡。 可手動強制部分讀請求到主庫上。(因為主從同步有延遲,對實時性要求高的系統,可以將部分讀請求也走主庫) 本次不討論 MySQL如何配置

mycat配置分離

負載均衡 limit 壓力 防火 開啟 防火墻的設置 lease tar.gz 8.0 現有後端MYSQL架構: MHA1 192.168.1.20 MHA2 192.168.1.30 MHA3

ProxySQL配置分離

簡介 ProxySQL是具有GPL許可證的高效能MySQL代理。作為監視程序監視的守護程序執行。該程序監視守護程序並在發生崩潰時重新啟動它以最大限度地減少停機時間。 守護程序接受來自MySQL客戶端的傳入流量,並將其轉發到後端MySQL伺服器。 代理設計為連續執

redis配置分離以及利用哨兵sentinel進行自動主從切換

redis利用哨兵(sentinel)進行主從切換,斷斷續續,自己終於通過配置驗證了一下該功能,其中遇到過一些的問題,也是耗費了大量的時間才解決,接下來分享下配置的過程以及遇到的問題和解決方法。希望對各位有所幫助。 首先說一下實驗環境:

資料庫配置分離後如何方便地從主庫中讀取資料

基於ThinkPHP5.1.15+MySQL演示主從同步配置與讀寫分離解決方案。 軟體環境:ThinkPHP5.1.15+MariaDB 10.1.30(主伺服器)+MySQL5.7(從伺服器)+Win10 兩臺伺服器IP分別為:192.168.199.234、192.1

mysql jdbc 實現分離

這種方式直接在程式碼級別實現了mysql 讀寫分離 很簡單,只需要改一下配置檔案,就搞定了,是不是很嗨? jdbc.driverClassName=com.mysql.jdbc.ReplicationDriver jdbc.url=jdbc:mysql

linux系統安裝mycat,並配置分離規則

一.準備工作 1.因為Mycat是在java環境開發的,所以需要在實驗環境下安裝java,官方建議jdk1.7及以上版本,我這裡也寫一下將jdk1.6替換為jdk1.7的步驟,用來記錄一下,以免下次在遇到。 2.使用vi /etc/profile命令修改環境變數,具體配

shareding-jdbc實現分離最簡單的容易理解示例

資料庫建立create database demo_ds_master; //建立主庫create database demo_ds_slave_0; //建立從庫1create database

springboot2.x 整合mybatis-plus sharding-jdbc實現分離

首先,匯入依賴,下面只展示核心依賴 <dependency> <groupId>com.baomidou</groupId> <artifactId>my

Spring+Mybatis透明實現分離

背景 網上有好多讀寫分離的實踐,所應對的業務場景也不一樣,本方法參考了網上好多方法,最終實現為快速應對中小型網際網路產品的讀寫分離。 資料庫環境: 1臺master;多臺slaver 適用框架: spring+mybatis 操作資料庫的簡單原理

Redis配置分離

當資料量變得龐大的時候,讀寫分離還是很有必要的。同時避免一個redis服務宕機,導致應用宕機的情況,我們啟用sentinel(哨兵)服務,實現主從切換的功能。redis提供了一個master,多個slave的服務。準備三個redis服務,依次命名資料夾子master,slav

mysql的MHA之Atlas 配置, 分離實現

用戶 http 安裝包 state crypt 進入 rpm 安裝 down 1.安裝 Atlas #在主庫安裝,進入安裝包目錄 [[email protected]-db01 ~]# cd /home/oldboy/tools/ #下載Atlas [

Spring配置動態數據源-分離和多數據源

brush ride 常開 resolve ttr 表達 customer 事務管理 cda   在現在互聯網系統中,隨著用戶量的增長,單數據源通常無法滿足系統的負載要求。因此為了解決用戶量增長帶來的壓力,在數據庫層面會采用讀寫分離技術和數據庫拆分等技術。讀寫分離就是就是一

Spring Boot2.0.3 Mybatis Sharding-jdbc3.X整合實現資料庫的分離(一)MySql的主從配置

Mysql的安裝 這個網上一大堆的教程,我這裡安裝的mysql5.7。這裡就不細說了,直接貼相應的命令 wget http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm yum locali

Spring Boot + Mybatis 多資料來源配置實現分離

本文來自網易雲社群作者:王超應用場景:專案中有一些報表統計與查詢功能,對資料實時性要求不高,因此考慮對報表的統計與查詢去操作slave db,減少對master的壓力。根據網上多份資料測試發現總是使用master資料來源,無法切換到slave,經過多次除錯修改現已完美通過,現

spring + mybatis + mysql(主從) 配置多個resource(分離

改造原有的專案 實現讀寫分離 準備工作: 1.需要一個能夠執行的spring + mybatis的專案 2.mysql 主從資料庫 拆分Dao(按照讀寫去拆分) 拆分mapping檔案 新增資料庫配置檔案(jdbc.properties)