学习dangdang的分库分表扩展框架sharding-jdbc(一)

前一段时间研究阿里的分库框架cobar-client,cobar-client是基于ibatis的SqlMapClientTemplate进行了一层薄薄的封装,分装成CobarSqlMapClientTemplate,在用户在CRUD的时候可以透明的进行操作,算是现在大多公司分库的一个成熟解决方案,不过现在面临的一些问题:

   ①不支持分表

   ②基于ibatis而且2013年后基本维护了,没有进行升级,所以大多公司都基于该思想进行了自己的重写


来看下当当开源的sharding-jdbc,官方网址:https://github.com/dangdangdotcom/sharding-jdbc


先允许我盗一波图:

学习dangdang的分库分表扩展框架sharding-jdbc(一)_第1张图片


学习dangdang的分库分表扩展框架sharding-jdbc(一)_第2张图片


好了,看了这么多的介绍,感觉还是很高大上的,注意点有:

①对JDBC API进行了原生态的分装,这是与cobar-client不一样的地方,这就是他可以支持多个第三方ORM框架的关键

②可支持=BETWEENIN等操作,说明,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项目

学习dangdang的分库分表扩展框架sharding-jdbc(一)_第3张图片


Maven依赖的pom.xml


	4.0.0

	org.study
	sharding-jdbc
	0.0.1-SNAPSHOT
	jar

	sharding-jdbc
	http://maven.apache.org

	
		UTF-8
		3.2.5.RELEASE
		3.2.4
	

	
		
			junit
			junit
			4.10
		
		
			com.dangdang
			sharding-jdbc-core
			1.0.0
		
		
			org.springframework
			spring-orm
			${spring.version}
		
		
			commons-dbcp
			commons-dbcp
			1.4
		
		
			org.mybatis
			mybatis-spring
			1.2.2
		
		
			org.mybatis
			mybatis
			${mybatis.version}
		

		
			org.springframework
			spring-expression
			${spring.version}
		
		
			org.springframework
			spring-aop
			${spring.version}
		
		
			org.springframework
			spring-beans
			${spring.version}
		
		
			org.springframework
			spring-context
			${spring.version}
		
		
			org.springframework
			spring-context-support
			${spring.version}
		
		
			org.springframework
			spring-test
			${spring.version}
		
		
			org.springframework
			spring-tx
			${spring.version}
		
		
			mysql
			mysql-connector-java
			5.1.28
		
		
			log4j
			log4j
			1.2.16
		
		
			org.slf4j
			slf4j-log4j12
			1.7.5
		
	


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 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;
    }

}

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{

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

    @Override
    public Collection doInSharding(Collection availableTargetNames, ShardingValue shardingValue) {
        Collection 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 doBetweenSharding(Collection availableTargetNames,
            ShardingValue shardingValue) {
        Collection result = new LinkedHashSet<>(availableTargetNames.size());
        Range range = (Range) 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 {
    
    /**
    *  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 tableNames, final ShardingValue 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 doInSharding(final Collection tableNames, final ShardingValue shardingValue) {
        Collection 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 doBetweenSharding(final Collection tableNames, final ShardingValue shardingValue) {
        Collection result = new LinkedHashSet<>(tableNames.size());
        Range range = (Range) 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

    
  
  
    
    
       
       
       
         
       
    
  
    
    
       
       
       
       
       
      
       
     
  
     
     
       
       
       
       
       
       
          
       
     
  
     
     
       
       
       
       
       
      
       
     
  
     
     
        
        
        
     
  
     
     
         
         
         
        
        
     
  

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

学习dangdang的分库分表扩展框架sharding-jdbc(一)_第4张图片

我们现在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函数,运行结果为:

学习dangdang的分库分表扩展框架sharding-jdbc(一)_第5张图片

好了,sharding-jdbc正常工作了



官网说sharding-jdbc是支持与orm框架整合的,下一节我们整合一下mybatis    END~






 



你可能感兴趣的:(开源框架)