1. 程式人生 > >學習dangdang的分庫分表擴充套件框架sharding-jdbc(一)

學習dangdang的分庫分表擴充套件框架sharding-jdbc(一)

噹噹開源的sharding-jdbc,官方網址:https://github.com/dangdangdotcom/sharding-jdbc
 
一、簡介






好了,看了這麼多的介紹,感覺還是很高大上的,注意點有:
①對JDBC API進行了原生態的分裝,這是與cobar-client不一樣的地方,這就是他可以支援多個第三方ORM框架的關鍵
②可支援=,BETWEEN,IN等操作,說明,JDBC返回結果後,sharding進行了合併操作,這裡面肯定會有效能損耗
③支援分表,這也是cobar-client不支援的地方


好了,先簡單的按照官方網址的demo實踐一發:


先在MySQL中建2個庫




分別在這2個庫中執行:
CREATE TABLE IF NOT EXISTS `t_order_0` (  
	  `order_id` INT NOT NULL,  
	  `user_id`  INT NOT NULL,  
	  PRIMARY KEY (`order_id`)  
	);  
	CREATE TABLE IF NOT EXISTS `t_order_item_0` (  
	  `item_id`  INT NOT NULL,  
	  `order_id` INT NOT NULL,  
	  `user_id`  INT NOT NULL,  
	  PRIMARY KEY (`item_id`)  
	);  
	CREATE TABLE IF NOT EXISTS `t_order_1` (  
	  `order_id` INT NOT NULL,  
	  `user_id`  INT NOT NULL,  
	  PRIMARY KEY (`order_id`)  
	);  
	CREATE TABLE IF NOT EXISTS `t_order_item_1` (  
	  `item_id`  INT NOT NULL,  
	  `order_id` INT NOT NULL,  
	  `user_id`  INT NOT NULL,  
	  PRIMARY KEY (`item_id`)  
	);  


新建maven專案






ShardingJdbc

package com.study.base;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;


import javax.sql.DataSource;


import org.apache.commons.dbcp.BasicDataSource;


import com.dangdang.ddframe.rdb.sharding.api.ShardingDataSource;
import com.dangdang.ddframe.rdb.sharding.api.rule.BindingTableRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.DataSourceRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.ShardingRule;
import com.dangdang.ddframe.rdb.sharding.api.rule.TableRule;
import com.dangdang.ddframe.rdb.sharding.api.strategy.database.DatabaseShardingStrategy;
import com.dangdang.ddframe.rdb.sharding.api.strategy.table.TableShardingStrategy;


public class ShardingJdbc {
    
    public static void main(String[] args) throws SQLException {
        
        //資料來源
        Map<String, DataSource> dataSourceMap = new HashMap<>(2);
        dataSourceMap.put("sharding_0", createDataSource("sharding_0"));
        dataSourceMap.put("sharding_1", createDataSource("sharding_1"));
        
        DataSourceRule dataSourceRule = new DataSourceRule(dataSourceMap);
        
        //分表分庫的表,第一個引數是邏輯表名,第二個是實際表名,第三個是實際庫
        TableRule orderTableRule = new TableRule("t_order", Arrays.asList("t_order_0", "t_order_1"), dataSourceRule);
        TableRule orderItemTableRule = new TableRule("t_order_item", Arrays.asList("t_order_item_0", "t_order_item_1"), dataSourceRule);
        
        
        
        /**
         * DatabaseShardingStrategy 分庫策略
         * 引數一:根據哪個欄位分庫
         * 引數二:分庫路由函式
         * TableShardingStrategy 分表策略
         * 引數一:根據哪個欄位分表
         * 引數二:分表路由函式
         * 
         */
        ShardingRule shardingRule = new ShardingRule(dataSourceRule, Arrays.asList(orderTableRule, orderItemTableRule),
                Arrays.asList(new BindingTableRule(Arrays.asList(orderTableRule, orderItemTableRule))),
                new DatabaseShardingStrategy("user_id", new ModuloDatabaseShardingAlgorithm()),
                new TableShardingStrategy("order_id", new ModuloTableShardingAlgorithm()));
        
        
        DataSource dataSource = new ShardingDataSource(shardingRule);
        String sql = "SELECT i.* FROM t_order o JOIN t_order_item i ON o.order_id=i.order_id WHERE o.user_id=? AND o.order_id=?";
        try (
                Connection conn = dataSource.getConnection();
                PreparedStatement pstmt = conn.prepareStatement(sql)) {
                pstmt.setInt(1, 10);
                pstmt.setInt(2, 1001);
            try (ResultSet rs = pstmt.executeQuery()) {
                while(rs.next()) {
                    System.out.println(rs.getInt(1));
                    System.out.println(rs.getInt(2));
                    System.out.println(rs.getInt(3));
                }
            }
        }
    }


    /**
     * 建立資料來源
     * @param dataSourceName
     * @return
     */
    private static DataSource createDataSource(String dataSourceName) {
        BasicDataSource result = new BasicDataSource();
        result.setDriverClassName(com.mysql.jdbc.Driver.class.getName());
        result.setUrl(String.format("jdbc:mysql://localhost:3306/%s", dataSourceName));
        result.setUsername("root");
        result.setPassword("");
        return result;
    }


}



Maven依賴的pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
	    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
	    <modelVersion>4.0.0</modelVersion>  
	  
	    <groupId>org.study</groupId>  
	    <artifactId>sharding-jdbc</artifactId>  
	    <version>0.0.1-SNAPSHOT</version>  
	    <packaging>jar</packaging>  
	  
	    <name>sharding-jdbc</name>  
	    <url>http://maven.apache.org</url>  
	  
	    <properties>  
	        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
	        <spring.version>3.2.5.RELEASE</spring.version>  
	        <mybatis.version>3.2.4</mybatis.version>  
	    </properties>  
	  
	    <dependencies>  
	        <dependency>  
	            <groupId>junit</groupId>  
	            <artifactId>junit</artifactId>  
	            <version>4.10</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>com.dangdang</groupId>  
	            <artifactId>sharding-jdbc-core</artifactId>  
	            <version>1.0.0</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-orm</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>commons-dbcp</groupId>  
	            <artifactId>commons-dbcp</artifactId>  
	            <version>1.4</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.mybatis</groupId>  
	            <artifactId>mybatis-spring</artifactId>  
	            <version>1.2.2</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.mybatis</groupId>  
	            <artifactId>mybatis</artifactId>  
	            <version>${mybatis.version}</version>  
	        </dependency>  
	  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-expression</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-aop</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-beans</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-context</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-context-support</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-test</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.springframework</groupId>  
	            <artifactId>spring-tx</artifactId>  
	            <version>${spring.version}</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>mysql</groupId>  
	            <artifactId>mysql-connector-java</artifactId>  
	            <version>5.1.28</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>log4j</groupId>  
	            <artifactId>log4j</artifactId>  
	            <version>1.2.16</version>  
	        </dependency>  
	        <dependency>  
	            <groupId>org.slf4j</groupId>  
	            <artifactId>slf4j-log4j12</artifactId>  
	            <version>1.7.5</version>  
	        </dependency>  
	    </dependencies>  
	</project>  



ModuloDatabaseShardingAlgorithm
package com.study.base;


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;


/**
 * 
 * @author lyncc
 *
 */
public class ModuloDatabaseShardingAlgorithm implements SingleKeyDatabaseShardingAlgorithm<Integer>{


    @Override
    public String doEqualSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
        for (String each : availableTargetNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }


    @Override
    public Collection<String> doInSharding(Collection<String> availableTargetNames, ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        for (Integer value : shardingValue.getValues()) {
            for (String tableName : availableTargetNames) {
                if (tableName.endsWith(value % 2 + "")) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }


    @Override
    public Collection<String> doBetweenSharding(Collection<String> availableTargetNames,
            ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(availableTargetNames.size());
        Range<Integer> range = (Range<Integer>) shardingValue.getValueRange();
        for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : availableTargetNames) {
                if (each.endsWith(i % 2 + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }


}

ModuloTableShardingAlgorithm.java

package com.study.base;
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;


public final class ModuloTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Integer> {
    
    /**
    *  select * from t_order from t_order where order_id = 11 
    *          └── SELECT *  FROM t_order_1 WHERE order_id = 11
    *  select * from t_order from t_order where order_id = 44
    *          └── SELECT *  FROM t_order_0 WHERE order_id = 44
    */
    public String doEqualSharding(final Collection<String> tableNames, final ShardingValue<Integer> shardingValue) {
        for (String each : tableNames) {
            if (each.endsWith(shardingValue.getValue() % 2 + "")) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }
    
    /**
    *  select * from t_order from t_order where order_id in (11,44)  
    *          ├── SELECT *  FROM t_order_0 WHERE order_id IN (11,44) 
    *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,44) 
    *  select * from t_order from t_order where order_id in (11,13,15)  
    *          └── SELECT *  FROM t_order_1 WHERE order_id IN (11,13,15)  
    *  select * from t_order from t_order where order_id in (22,24,26)  
    *          └──SELECT *  FROM t_order_0 WHERE order_id IN (22,24,26) 
    */
    public Collection<String> doInSharding(final Collection<String> tableNames, final ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        for (Integer value : shardingValue.getValues()) {
            for (String tableName : tableNames) {
                if (tableName.endsWith(value % 2 + "")) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }
    
    /**
    *  select * from t_order from t_order where order_id between 10 and 20 
    *          ├── SELECT *  FROM t_order_0 WHERE order_id BETWEEN 10 AND 20 
    *          └── SELECT *  FROM t_order_1 WHERE order_id BETWEEN 10 AND 20 
    */
    public Collection<String> doBetweenSharding(final Collection<String> tableNames, final ShardingValue<Integer> shardingValue) {
        Collection<String> result = new LinkedHashSet<>(tableNames.size());
        Range<Integer> range = (Range<Integer>) shardingValue.getValueRange();
        for (Integer i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            for (String each : tableNames) {
                if (each.endsWith(i % 2 + "")) {
                    result.add(each);
                }
            }
        }
        return result;
    }
}

log4j.xml

<?xml version="1.0" encoding="UTF-8"?>    
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">  
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">  
  <!-- [控制檯STDOUT] -->  
  <appender name="console" class="org.apache.log4j.ConsoleAppender">  
     <param name="encoding" value="GBK" />  
     <param name="target" value="System.out" />  
     <layout class="org.apache.log4j.PatternLayout">  
       <param name="ConversionPattern" value="%-5p %c{2} - %m%n" />  
     </layout>  
  </appender>  
  
  <!-- [公共Appender] -->  
  <appender name="DEFAULT-APPENDER" class="org.apache.log4j.DailyRollingFileAppender">  
     <param name="File" value="${webapp.root}/logs/common-default.log" />  
     <param name="Append" value="true" />  
     <param name="encoding" value="GBK" />  
     <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />  
     <layout class="org.apache.log4j.PatternLayout">  
    <param name="ConversionPattern" value="%d %-5p %c{2} - %m%n" />  
     </layout>  
   </appender>  
  
   <!-- [錯誤日誌APPENDER] -->  
   <appender name="ERROR-APPENDER" class="org.apache.log4j.DailyRollingFileAppender">  
     <param name="File" value="${webapp.root}/logs/common-error.log" />  
     <param name="Append" value="true" />  
     <param name="encoding" value="GBK" />  
     <param name="threshold" value="error" />  
     <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />  
     <layout class="org.apache.log4j.PatternLayout">  
        <param name="ConversionPattern" value="%d %-5p %c{2} - %m%n" />  
     </layout>  
   </appender>  
  
   <!-- [元件日誌APPENDER] -->  
   <appender name="COMPONENT-APPENDER"  
class="org.apache.log4j.DailyRollingFileAppender">  
     <param name="File" value="${webapp.root}/logs/logistics-component.log" />  
     <param name="Append" value="true" />  
     <param name="encoding" value="GBK" />  
     <param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />  
     <layout class="org.apache.log4j.PatternLayout">  
    <param name="ConversionPattern" value="%d %-5p %c{2} - %m%n" />  
     </layout>  
   </appender>  
  
   <!-- [元件日誌] -->  
   <logger name="LOGISTICS-COMPONENT">  
      <level value="${loggingLevel}" />  
      <appender-ref ref="COMPONENT-APPENDER" />  
      <appender-ref ref="ERROR-APPENDER" />  
   </logger>  
  
   <!-- Root Logger -->  
   <root>  
       <level value="${rootLevel}"></level>  
       <appender-ref ref="DEFAULT-APPENDER" />  
       <appender-ref ref="ERROR-APPENDER" />  
       <appender-ref ref="console" /> 
       <appender-ref ref="COMPONENT-APPENDER" /> 
   </root>  
</log4j:configuration>  



好了,按照官方教程說明:





我們現在user_id是10,order_id是1001
我們應該在sharding0庫中的t_order_1和t_order_item_1中新建資料:


	INSERT INTO `t_order_1` VALUES ('1001', '10');  
	  
	INSERT INTO `t_order_item_1` VALUES ('4', '1001', '2');  




好了,準備工作做完了,我們執行main函式,執行結果為:




好了,sharding-jdbc正常工作了

相關推薦

學習dangdang分庫擴充套件框架sharding-jdbc

噹噹開源的sharding-jdbc,官方網址:https://github.com/dangdangdotcom/sharding-jdbc   一、簡介 好了,看了這麼多的介紹,感覺還是很高大上的,注意點有: ①對JDBC API進行了原生態的分裝,這是與cobar-c

文快速入門分庫中介軟體 Sharding-JDBC 必修課

書接上文 [《一文快速入門分庫分表(必修課)》](https://mp.weixin.qq.com/s/rYG58KS9kHDDOMajKT9y5Q),這篇拖了好長的時間,本來計劃在一週前就該寫完的,結果家庭內部突然人事調整,領導層進行權利交接,隨之宣佈我正式當爹,緊接著家庭地位滑落至第三名,還給我分配了一個

學習sharding-jdbc 分庫擴充套件框架

前一段時間研究阿里的分庫框架cobar-client,cobar-client是基於ibatis的SqlMapClientTemplate進行了一層薄薄的封裝,分裝成CobarSqlMapClientTemplate,在使用者在CRUD的時候可以透明的進行操作,算是現

數據庫分庫中間件 Sharding-JDBC 源碼分析 —— SQL 解析之刪除SQL

java 後端 架構 數據庫 中間件關註微信公眾號:【芋道源碼】有福利:RocketMQ / MyCAT / Sharding-JDBC 所有源碼分析文章列表RocketMQ / MyCAT / Sharding-JDBC 中文註釋源碼 GitHub 地址您對於源碼的疑問每條留言都將得到認真回復。甚至不知道如

數據庫分庫中間件 Sharding-JDBC 源碼分析 —— 布式主鍵

java 後端 架構 數據庫 中間件關註**微信公眾號:【芋道源碼】**有福利:RocketMQ / MyCAT / Sharding-JDBC 所有源碼分析文章列表RocketMQ / MyCAT / Sharding-JDBC 中文註釋源碼 GitHub 地址您對於源碼的疑問每條留言都將得到認真回復。甚至

噹噹分庫中介軟體-sharding-jdbc

使用指南 閱讀本指南前,請先閱讀快速起步。本文件使用更復雜的場景進一步介紹Sharding-JDBC的分庫分表能力。 資料庫模式 本文件中提供了兩個資料來源db0和db1,每個資料來源之中包含了兩組表t_order_0和t_order_1,t_order_item_

資料庫分庫中介軟體 Sharding-JDBC 原始碼分析 —— 分散式主鍵

������關注微信公眾號:【芋道原始碼】有福利: 1. RocketMQ / MyCAT / Sharding-JDBC 所有原始碼分析文章列表 2. RocketMQ / MyCAT / Sharding-JDBC 中文註釋原始碼 Gi

解讀分庫中介軟體Sharding-JDBC

3月18日-19日,由CSDN重磅打造的網際網路應用架構實戰峰會、資料庫核心技術與實戰應用峰會將在上海舉行。作為SDCC 2016(中國軟體開發者大會)系列技術峰會的一部分,秉承乾貨實料(案例)的內容原則,這兩場峰會將邀請業內頂尖的架構師和技術專家,共同探討高可用/高併發

分庫中間件sharding-jdbc的使用

關系 java高級 減少 壓力 連接 提前 ofo 水平拆分 指定 數據分片產生的背景,可以查看https://shardingsphere.apache.org/document/current/cn/features/sharding/,包括了垂直拆分和水平拆分的概念.

每日學習20170224-分庫全域性ID生成

由於資料量以及IO效率的因素,很多專案對資料支援的資料庫會採取分庫分表的方式。使用了分庫分表之後需要解決的一個問題就是主鍵的生成。多個表之間的主鍵就不能用資料庫本身的自增主鍵來支援,因為不同表之間生成的主鍵會重複。所以需要其他的方式獲取主鍵ID。 一般來說解決

程式設計師修神之路--做好分庫其實很難之一繼續送書

菜哥,領導讓我開發新系統了 這麼說領導對你還是挺信任的呀~ 必須的,為了設計好這個新系統,資料庫設計我花了好多心思呢 做一個系統我覺得不應該從資料庫入手,應該從設計業務模型開始,先不說這個,說說你的資料庫設計的優勢 為了高效能我首先設計了分庫 分表策略,為以後打下基礎 那你的資料量將來會很大嗎?分庫

java深度學習框架Deeplearning4j實戰BP神經網路分類器

1、Deeplearning4j 深度學習,人工智慧今天已經成了IT界最流行的詞,而tensorflow,phython又是研究深度學習神經網路的熱門工具。tensorflow是google的出品,而phython又以簡練的語法,獨特的程式碼結構和語言特性為眾多資料科學家和

Mysql千萬資料級設計及實現方案2附一致性雜湊原理解析

首先,接著上篇博文:Mysql千萬資料級分表設計及實現方案已經分析了自增id作分表key和全域性服務id(16位)作分表key進行分表的兩種設計方案。自增id優勢在於簡單,直接雜湊取模即可分表完成。根據

學習sharding-jdbc之spring+mybatis+sharding-jdbc整合

新建Maven專案 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:s

Linux驅動學習筆記----------IIC框架與流程

歷時一個月期末課程設計終於結束了!發現好多東西忘記了,iic流程也有些淡忘,有點慌,夜深人靜的時候就整理下吧!還有,杭州最近熱的我腦袋都不好用了! 關於iic: 1.是一種資料傳輸協議(spi,usb,sdio,uart…)

Dubbo框架應用之--服務體系

white 部件 esp 恢復 fonts resp auto zh-cn 通過 Dubbo 是阿裏巴巴公司開源的一個高性能優秀的服務框架,使得應用可通過高性能的 RPC 實現服務的輸出和輸入功能,能夠和 Spring框架無縫集成,也是一個很全面的

AVFoundation 框架初探究

device 延時 dede 指定 來電 reat 基本 oops iop 夜深時動筆 前面一篇文章寫了視頻播放的幾種基本的方式,算是給這個系列開了一個頭,這裏面最想說和探究的就是AVFoundation框架,很想把這個框架不敢說是完全理解,但

Spring Cloud Spring Boot mybatis布式微服務雲架構快速入門

springboot springcloud mybatis eureka config 快速入門本章主要目標完成Spring Boot基礎項目的構建,並且實現一個簡單的Http請求處理,通過這個例子對Spring Boot有一個初步的了解,並體驗其結構簡單、開發快速的特性。 系統要求:J

Java NIO框架Netty教程 – Hello Netty

tex highlight bsp ret 開發 包括 tor 習慣 事件機制 先啰嗦兩句,如果你還不知道Netty是做什麽的能做什麽。那可以先簡單的搜索了解一下。我只能說Netty是一個NIO的框架,可以用於開發分布式的Java程序。具體能做什麽,各位可以盡量發揮想象。技

linux學習之多高並發服務器篇

多線程 同步 https 進程調度 creat server side lis logs 高並發服務器 高並發服務器 並發服務器開發 1.多進程並發服務器   使用多進程並發服務器時要考慮以下幾點: 父最大文件描述個數(父進程中需要close關閉accept返回的新文件