sharding-jdbc结合mybatis实现分库分表功能

  最近忙于项目已经好久几天没写博客了,前2篇文章我给大家介绍了搭建基础springMvc+mybatis的maven工程,这个简单框架已经可以对付一般的小型项目。但是我们实际项目中会碰到很多复杂的场景,比如数据量很大的情况下如何保证性能。今天我就给大家介绍数据库分库分表的优化,本文介绍mybatis结合当当网的sharding-jdbc分库分表技术(原理这里不做介绍)

  首先在pom文件中引入需要的依赖

<dependency>
            <groupId>com.dangdang</groupId>
            <artifactId>sharding-jdbc-core</artifactId>
            <version>1.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.dangdang</groupId>
            <artifactId>sharding-jdbc-config-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

  二、新建一个sharding-jdbc.xml文件,实现分库分表的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:rdb="http://www.dangdang.com/schema/ddframe/rdb"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.dangdang.com/schema/ddframe/rdb
                        http://www.dangdang.com/schema/ddframe/rdb/rdb.xsd">

    <rdb:strategy id="tableShardingStrategy" sharding-columns="user_id" algorithm-class="com.meiren.member.common.sharding.MemberSingleKeyTableShardingAlgorithm"/>

    <rdb:data-source id="shardingDataSource">
        <rdb:sharding-rule data-sources="dataSource">
            <rdb:table-rules>
                <rdb:table-rule logic-table="member_index" actual-tables="member_index_tbl_${[0,1,2,3,4,5,6,7,8,9]}${0..9}"  table-strategy="tableShardingStrategy"/>
                <rdb:table-rule logic-table="member_details" actual-tables="member_details_tbl_${[0,1,2,3,4,5,6,7,8,9]}${0..9}"  table-strategy="tableShardingStrategy"/>
            </rdb:table-rules>
        </rdb:sharding-rule>
    </rdb:data-source>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="shardingDataSource" />
    </bean>
</beans>

  这里我简单介绍下一些属性的含义,

   <rdb:strategy id="tableShardingStrategy" sharding-columns="user_id" algorithm-class="com.meiren.member.common.sharding.MemberSingleKeyTableShardingAlgorithm"/>  配置分表规则器  sharding-columns:分表规 则 

  依赖的名(根据user_id取模分表),algorithm-class:分表规则的实现类

  <rdb:sharding-rule data-sources="dataSource"> 这里填写关联数据源(多个数据源用逗号隔开),

  <rdb:table-rule logic-table="member_index" actual-tables="member_index_tbl_${[0,1,2,3,4,5,6,7,8,9]}${0..9}"  table-strategy="tableShardingStrategy"/>  logic-table:逻辑表名(mybatis中代替的表名)actual-tables:

  数据库实际的表名,这里支持inline表达式,比如:member_index_tbl_${0..2}会解析成member_index_tbl_0,member_index_tbl_1,member_index_tbl_2;member_index_tbl_${[a,b,c]}会被解析成

    member_index_tbl_a,member_index_tbl_b和member_index_tbl_c,两种表达式一起使用的时候,会采取笛卡尔积的方式:member_index_tbl_${[a,b]}${0..2}解析为member_index_tbl_a0,member_index_tbl_a1                                       member_index_tbl_a2,member_index_tbl_b0,member_index_tbl_b1,member_index_tbl_b2;table-strategy:前面定义的分表规则器;

三、配置好改文件后,需要修改之前我们的spring-dataSource的几个地方,把sqlSessionFactory和transactionManager原来关联的dataSource统一修改为shardingDataSource(这一步作用就是把数据源全部托管给sharding去管理)

  

 四、实现分表(分库)逻辑,我们的分表逻辑类需要实现SingleKeyTableShardingAlgorithm接口的三个方法doBetweenSharding、doEqualSharding、doInSharding

/**
 * 分表逻辑
 * @author zhangwentao
 *
 */
public class MemberSingleKeyTableShardingAlgorithm implements SingleKeyTableShardingAlgorithm<Long> {

    /**
     * sql between 规则
     */
    public Collection<String> doBetweenSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        Collection<String> result = new LinkedHashSet<String>(tableNames.size());
        Range<Long> range = (Range<Long>) shardingValue.getValueRange();
        for (long i = range.lowerEndpoint(); i <= range.upperEndpoint(); i++) {
            Long modValue = i % 100;
            String modStr = modValue < 10 ? "0" + modValue : modValue.toString();
            for (String each : tableNames) {
                if (each.endsWith(modStr)) {
                    result.add(each);
                }
            }
        }
        return result;
    }

    /**
     * sql == 规则
     */
    public String doEqualSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {
        Long modValue = shardingValue.getValue() % 100;
        String modStr = modValue < 10 ? "0" + modValue : modValue.toString();
        for (String each : tableNames) {
            if (each.endsWith(modStr)) {
                return each;
            }
        }
        throw new IllegalArgumentException();
    }

    /**
     * sql in 规则
     */
    public Collection<String> doInSharding(Collection<String> tableNames, ShardingValue<Long> shardingValue) {

        Collection<String> result = new LinkedHashSet<String>(tableNames.size());
        for (long value : shardingValue.getValues()) {
            Long modValue = value % 100;
            String modStr = modValue < 10 ? "0" + modValue : modValue.toString();
            for (String tableName : tableNames) {
                if (tableName.endsWith(modStr)) {
                    result.add(tableName);
                }
            }
        }
        return result;
    }

}

五、以上四步,我们就完成了sharding-jdbc的搭建,我们可以写一个测试demo来检查我们的成果

<select id="getDetailsById" resultType="com.meiren.member.dataobject.MemberDetailsDO"
        parameterType="java.lang.Long">
        select user_id userId ,qq,email from member_details where     user_id =#{userId} limit 1
    </select>
  private static final String SERVICE_PROVIDER_XML = "/spring/member-service.xml";
	    private static final String BEAN_NAME = "idcacheService";

	    private ClassPathXmlApplicationContext context = null;
	    IdcacheServiceImpl bean = null;
	    IdcacheDao idcacheDao;

	    @Before
	    public void before() {
	        context= new ClassPathXmlApplicationContext(
	                new String[] {SERVICE_PROVIDER_XML});
	       idcacheDao=context.getBean("IdcacheDao", IdcacheDao.class);
	    }

	    @Test
	    public void getAllCreditActionTest() {
	     // int id = bean.insertIdcache();
	    	Long s=100l;
	      MemberDetailsDO memberDetailsDO=idcacheDao.getDetailsById(s);
	      System.out.println("QQ---------------------"+memberDetailsDO.getQq());
	    }

  打印sql语句,输出结果:QQ-------------------------------------100,证明成功!

  注意点:这次搭建过程中,我有碰到一个小坑,就是执行的时候会报错:,官方文档是有解决方案:引入 <context:property-placeholder location="classpath:/member_service.properties" ignore-unresolvable="true" />  ,引入这行代码的时候,·必须要要把这边管理配配置文件的bean删除,换句话说,即Spring容器仅允许最多定义一个PropertyPlaceholderConfigurer(或<context:property-placeholder/>),其余的会被Spring忽略掉(当时搞了半天啊)

小结:这次给大家分享了sharding-jdbc的配置是为了解决大数据量进行分库分表的架构,下一张,我将介绍拆分业务所需的duboo+zookeeper的配置(分布式),欢迎关注!

时间: 2024-12-19 09:42:49

sharding-jdbc结合mybatis实现分库分表功能的相关文章

Sharding JDBC如何分库分表?看完你就会了

Sharding JDBC的操作分为配置使用.读写分离.分库分表以及应用等,今天我们主要来了解一下关于分库分表的操作,如果你对此感兴趣的话,那我们就开始吧. 环境准备 pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE

一小时读懂Sharding JDBC之分库分表

作为轻量级java框架,sharding JDBC在Java的jdbc层提供了额外的服务,可以理解为增强版的jdbc驱动.其中,分库分表的操作是其中的重要一环,接下来就跟随我来看一看,这一操作如何进行. 环境准备 pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <v

分库分表(5) ---SpringBoot + ShardingSphere 实现分库分表

分库分表(5)--- ShardingSphere实现分库分表 有关分库分表前面写了四篇博客: 1.分库分表(1) --- 理论 2.分库分表(2) --- ShardingSphere(理论) 3.分库分表(3) ---SpringBoot + ShardingSphere实现读写分离 4.分库分表(4) ---SpringBoot + ShardingSphere 实现分表 这篇博客通过ShardingSphere实现分库分表,并在文章最下方附上项目Github地址. 一.项目概述 1.技术

面试官:如何做到不停机分库分表迁移?

需求说明 类似订单表,用户表这种未来规模上亿甚至上十亿百亿的海量数据表,在项目初期为了快速上线,一般只是单表设计,不需要考虑分库分表.随着业务的发展,单表容量超过千万甚至达到亿级别以上,这时候就需要考虑分库分表这个问题了,而不停机分库分表迁移,这应该是分库分表最基本的需求,毕竟互联网项目不可能挂个广告牌"今晚10:00~次日10:00系统停机维护",这得多low呀,以后跳槽面试,你跟面试官说这个迁移方案,面试官怎么想呀? 借鉴codis 笔者正好曾经碰到过这个问题,并借鉴了codis一

OneProxy实现MySQL分库分表

OneProxy实现MySQL分库分表 简介 Part1:写在最前 随着网站的壮大,MySQL数据库架构一般会经历一个过程: 当我们数据量比较小的时候,一台单实例数据库足矣.等我们数据量增大的时候,我们会采用一主多从的数据库架构来降低我们的读写io.当我们某张业务表达到几百万上千万甚至上亿时,就应该去进行分表处理.本文演示OneProxy对数据库实现分表处理,对前端应用是透明的. Part2:环境简介 HE1:192.168.1.248 Master1 HE3:192.168.1.250 Mas

OneProxy分库分表演示--楼方鑫

OneProxy分库分表演示 (杭州平民软件有限公司) OneProxy是为MySQL精心设计的数据访问层,可以为任何开发语言提供对MySQL数据库的智能数据路由功能,比如单点切换.读写分离.分库分表等高级功能.并且允许你在公有云和私有云环境下自由布署,打造属于自己的数据架构. 如果在测试中发现问题,请联系我(微博:平民架构,微信:anysql)! 分库分表 Oracle从8.0.x版本开始在数据库内部支持分区表,可以将数据按某一个字段的某一规律来进行分片存贮,以降低数据库索引的层级,提高访问效

SpringBoot 整合 Sharding jdbc 实现应用层分库分表

1.官网链接参考: https://shardingsphere.apache.org/document/current/cn/quick-start/sharding-jdbc-quick-start/ 感谢 ShardingSphere 团队! 2.首先建立测试的数据库表: (1)表结构如下: (2)建表脚本如下: CREATE DATABASE `sharding0` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; USE `shar

数据库分库分表(sharding)系列(三) 关于使用框架还是自主开发以及sharding实现层面的考量

当团队对系统业务和数据库进行了细致的梳理,确定了切分方案后,接下来的问题就是如何去实现切分方案了,目前在sharding方面有不少的开源框架和产 品可供参考,同时很多团队也会选择自主开发实现,而不管是选择框架还是自主开发,都会面临一个在哪一层上实现sharding逻辑的问题,本文会对这一系 列的问题逐一进行分析和考量.本文原文连接: http://blog.csdn.net/bluishglc/article/details/7766508转载请注明出处! 一.sharding逻辑的实现层面 从

数据库分库分表(sharding)系列

数据库分库分表(sharding)系列     目录; (一) 拆分实施策略和示例演示 (二) 全局主键生成策略 (三) 关于使用框架还是自主开发以及sharding实现层面的考量 (四) 多数据源的事务处理 (五) 一种支持自由规划无须数据迁移和修改路由代码的Sharding扩容方案 (一) 拆分实施策略和示例演示 第一部分:实施策略 图1.数据库分库分表(sharding)实施策略图解 1.准备阶段 对数据库进行分库分表(Sharding化)前,需要开发人员充分了解系统业务逻辑和数据库sch