Java ShardingJDBC实战演练

目录
  • 一、背景
  • 二、优化事项
  • 三、具体实战
  • 四、遇到的问题
  • 五、项目源码地址

一、背景

最近在公司手头上的项目单表达到了五千万的规模,而且日增长量每天就有10w左右,一个月就有大概300w的数据,这样一直下去过几个月以后表的数据很容易就上亿了,这样不利于管理以及在大表的情况下,对于表的DDL效率也会相对下降,和几个同事商量了下,于是乎开始做分表的技术优化。

二、优化事项

(1)首先先确定使用场景,当前表的使用场景更多的是根据一个具体的标识值去查询,范围查询的场景频率相对低下,在这这种情况下考虑想标识值作为分片键去进行分表。 具体的算法为:通过标识值通过算法算出具体的时间季度,按季节进行拆分进行拆分,也就是一年

record_delivery_log

4个表record_order_log_202101,record_order_log_202102,record_order_log_202103,record_order_log_202104

拆分前单表数据量为 5000w

拆分后单表的数据量变成1200w,能够容忍将来4~ 5倍的增长量,符合预期范围。

(2)调研了对应的分库分表中间件,目前Sharing-jdbc是最主流的中间件,而且社区和文档较完善,故采用Sharing-jdbc作为分表的中间件。

三、具体实战

在这里因为公司项目不好复用的原因,用一个模拟项目来模拟这次改造。

(1)参照sharing-jdbc文档对项目进行改造

引入sharing-jdbc对应的pom。

 <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.0.0-beta</version>
        </dependency>

对应的配置文件

#端口
server.port=8080

# 数据源ds0
spring.shardingsphere.datasource.name=ds0
# 数据源ds0的配置
spring.shardingsphere.datasource.ds0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds0.driverClassName=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.url=jdbc:mysql://localhost:3306/world1?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=123456

# 分片规则,这里只分表,所以仅指定表的分片规则
spring.shardingsphere.rules.sharding.tables.record_order_log.actual-data-nodes=ds0.record_order_log_$->{2021..2031}0$->{1..4}

# 指定数据库的分片键,只有一个库所以还是用分表的分片键
spring.shardingsphere.rules.sharding.tables.record_order_log.database-strategy.standard.sharding-column=order_delivery_id
spring.shardingsphere.rules.sharding.tables.record_order_log.database-strategy.standard.sharding-algorithm-name=database-inline

# 指定分表的分片键
spring.shardingsphere.rules.sharding.tables.record_order_log.table-strategy.standard.sharding-column=order_delivery_id
spring.shardingsphere.rules.sharding.tables.record_order_log.table-strategy.standard.sharding-algorithm-name=table-inline

# Omit t_order_item table rule configuration ...
# ...

# 分片规则(默认取模)
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds0
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.type=CLASS_BASED
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.strategy=STANDARD
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.algorithmClassName=com.cus.shd.sharingjdbc.config.OrderDeliveryIdShardingAlgorithm
spring.shardingsphere.props.sql.show=true

#mybatis-plus??
mybatis-plus.mapper-locations=classpath:mappers/*.xml
mybatis-plus.type-aliases-package=com.cus.shd.sharingjdbc.model
mybatis-plus.configuration.map-underscore-to-camel-case=true
# sql??
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#本地数据库链接,忽略了springboot自动加载后失效
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/world1?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2b8
spring.datasource.username=root
spring.datasource.password=123456

注意好分表键设置时候的表名。

(2)自定义分片键策略,根据order_delivery_id按季度进行存储

package com.cus.shd.sharingjdbc.config;

import org.apache.commons.lang.StringUtils;
import org.apache.shardingsphere.sharding.api.sharding.ShardingAutoTableAlgorithm;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Collection;

/**
 * @author ASUS
 * @Description 自定义分片策略
 * @Date 2021/11/6 22:20
 **/

public class OrderDeliveryIdShardingAlgorithm implements StandardShardingAlgorithm<Long> {

    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        String orderDeliveryId = shardingValue.getValue().toString();
        orderDeliveryId = orderDeliveryId.substring(0,orderDeliveryId.length() - 4);
        // 将时间戳转为当前时间
        LocalDateTime localDateTime = LocalDateTime.ofEpochSecond(Long.valueOf(orderDeliveryId)/1000, 0, ZoneOffset.ofHours(8));
        String availableTargetName;
        int month = localDateTime.getMonthValue();
        LocalDateTime nowTime = LocalDateTime.now();
        int year = nowTime.getYear();
        if(month >= 1 && month < 3){
            availableTargetName = "01";
        }else if(month >= 3 && month < 6){
            availableTargetName = "02";
        }else if(month >= 6 && month < 9){
            availableTargetName = "03";
        }else {
            availableTargetName = "04";
        }
        if(StringUtils.isEmpty(availableTargetName)){
            return null;
        }
        return String.format("%s_%s%s",shardingValue.getLogicTableName(),year,availableTargetName);
    }

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        return availableTargetNames;
    }

    @Override
    public void init() {

    }

    @Override
    public String getType() {
        return "ORDER_DELIVERY_ID";
    }
}

(3)模拟提供两个接口,一个按id查询,一个插入接口。(修改的场景暂时没有,所以不考虑)

新增的时候做了模拟插入,能够根据分片算法将数据存储到对应的表,达到效果。

查询同理。

(4)sharing-jdbc 不会自动的进行创建表,所以需在后台维护一个定时任务,到了一定的季度点就要进行建表操作。(需确保生产环境的应用程序对应的数据库账号是否有建表权限)

<update id="createNewTable" parameterType="String">
        CREATE TABLE ${tableName} SELECT * FROM record_order_log WHERE 1=2
    </update>

四、遇到的问题

1、引入sharing-jdbc包的时候报错了。这里debug到源码发现是mybatisPlus的自动启动器(MybatisPlusAutoConfiguration)有指定单一数据源类(spring中数据源不能有多个实现类)的时候才会启动,因为sharing的引入造成了多数据源(多datasource),所以这个就不会启动了,导致了实例化mapper的时候报错了。解决方案是在SpringBoot的启动类的注解加上

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DruidDataSourceAutoConfigure.class})

忽略掉SpringBoot数据源自动装配以及Druid数据源的自动装配,把所有的数据源实例化交给sharing-jdbc

2、部分项目存在历史遗留的问题,如果是mybatis或者hibernate的情况下,不想彻底引入sharding-jdbc数据源的话,个人觉得可以使用多数据源的形式来进行改造,去扩展需要使用分表的一些数据库操作,切换对应的sharding数据源进行数据库操作。具体可以参考switchDataSource目录下的一些切换数据源的代码。

3、给自己的疑问

忽略了DataSourceAutoConfiguration.class后,sharing-jdbc是如何整合mybatis-plus的?

答:其实也不难,相当于数据源这个对象原本由SpringBoot自带的数据源自动注入进行注入,现在换成了Sharding的自动装配(ShardingSphereAutoConfiguration)来进行注入,相当于换了整个数据源的一套东西,用的也是sharding整套的东西。

所以在改造的时候需要检查一下是否对旧的项目存在影响。

五、项目源码地址

cus-sharding-jdbc: sharding-jdbc springboot实战

到此这篇关于Java ShardingJDBC实战演练的文章就介绍到这了,更多相关Java ShardingJDBC内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot集成Sharding Jdbc使用复合分片的实践

    目录 1.Sharing JDBC 简介 2.系统改造 2.1 对接外部系统的系统 2.2 内部系统间的调用 3.解决方案 4.代码实现 4.1 Sharding JDBC 配置 4.2 数据源操作类 4.3 分片测试类 4.4 测试结果 参考文章: 最近主要的工作重心是数据库的容量规划. 随着业务的逐渐增大,原有保存在单表的数据量也日益增强.数据库数据会随着业务的发展而不断增多,因此数据操作,如增删改查的开销也会越来越大.再加上物理服务器的资源有限(CPU.磁盘.内存.IO 等).最终数据库所

  • 基于sharding-jdbc的使用限制

    目录 使用限制 JDBC未支持列表 DataSource接口 Connection接口 Statement和PreparedStatement接口 对于ResultSet接口 JDBC 4.1 SQL语句限制 shardingjdbc使用及踩坑内容 1.使用shardingjdbc做分库分表 2.踩坑内容 使用限制 JDBC未支持列表 Sharding-JDBC暂时未支持不常用的JDBC方法. DataSource接口 不支持timeout相关操作 Connection接口 不支持存储过程,函数

  • springboot整合shardingjdbc实现分库分表最简单demo

    一.概览 1.1 简介 ShardingSphere-JDBC定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务. 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架. 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC. 支持任何第三方的数据库连接池,如:DBCP,

  • SpringBoot整合sharding-jdbc实现分库分表与读写分离的示例

    目录 一.前言 二.数据库表准备 三.整合 四.docker-compose部署mysql主从 五.本文案例demo源码 一.前言 本文将基于以下环境整合sharding-jdbc实现分库分表与读写分离 springboot2.4.0 mybatis-plus3.4.3.1 mysql5.7主从 https://github.com/apache/shardingsphere 二.数据库表准备 温馨小提示:此sql执行时,如果之前有存在相应库和表会进行自动删除后再创建! DROP DATABAS

  • ShardingSphere jdbc集成多数据源的实现步骤

    目录 集成sharding jdbc 1. 引入依赖 2. 配置分表规则 问题 集成多数据源 1. 引入依赖 2. 多数据源配置 3. 增加多数据源配置 4. 使用 总结 最近有个项目的几张表,数量级在千万以上,技术栈是SpringBoot+Mybatis-plus+MySQL.如果使用单表,在进行查询操作,非常耗时,经过一番调研,决定使用分表中间件:ShardingSphere. ShardingSphere今年4月份成为了 Apache 软件基金会的顶级项目,目前支持数据分片.读写分离.多数

  • SpringBoot整合sharding-jdbc实现自定义分库分表的实践

    目录 一.前言 二.简介 1.分片键 2.分片算法 三.程序实现 一.前言 SpringBoot整合sharding-jdbc实现分库分表与读写分离 本文将通过自定义算法来实现定制化的分库分表来扩展相应业务 二.简介 1.分片键 用于数据库/表拆分的关键字段 ex: 用户表根据user_id取模拆分到不同的数据库中 2.分片算法 可参考:https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere

  • 使用Sharding-JDBC对数据进行分片处理详解

    目录 前言 一.加入依赖 二.修改application.yml配置文件 三.数据源定义 四.数据源分配算法实现 五.数据表分配算法 六.数据源配置 七.开始测试 定义一个实体 定义实体DAO 测试类,插入1000条user数据 效果:数据被分片存储到0~9的数据表中 前言 Sharding-JDBC是ShardingSphere的第一个产品,也是ShardingSphere的前身. 它定位为轻量级Java框架,在Java的JDBC层提供的额外服务.它使用客户端直连数据库,以jar包形式提供服务

  • Java使用Sharding-JDBC分库分表进行操作

    目录 主从库搭建 Compose File Master 配置 Slave 配置 主从配置 创建分库分表 Order 1 库 Order 2 库 User 库 Sharding-JDBC 引入 Sharding-JDBC 配置 可选配置 数据源配置 主从复制配置 数据节点配置 Demo 程序 Sharding-JDBC 是无侵入式的 MySQL 分库分表操作工具,所有库表设置仅需要在配置文件中配置即可,无须修改任何代码. 本文写了一个 Demo,使用的是 SpringBoot 框架,通过 Doc

  • Java ShardingJDBC实战演练

    目录 一.背景 二.优化事项 三.具体实战 四.遇到的问题 五.项目源码地址 一.背景 最近在公司手头上的项目单表达到了五千万的规模,而且日增长量每天就有10w左右,一个月就有大概300w的数据,这样一直下去过几个月以后表的数据很容易就上亿了,这样不利于管理以及在大表的情况下,对于表的DDL效率也会相对下降,和几个同事商量了下,于是乎开始做分表的技术优化. 二.优化事项 (1)首先先确定使用场景,当前表的使用场景更多的是根据一个具体的标识值去查询,范围查询的场景频率相对低下,在这这种情况下考虑想

  • Java中Object.equals和String.equals的区别详解

    前言 Java中的堆和常量池的区别是什么呢?Object.equals与String.equals的区别呢?下面让我妈通过一个小示例让你明白它- 1.基础知识 Java的存储空间:寄存器.栈.堆.静态存储区.常量存储区(常量池).其他存储位置. 此处重点介绍堆和常量存储区: 堆:存储new的对象; 常量池:用来存储final static.String的常量. 2.Object.equals与String.equals的区别 Object.equals(==):比较内存地址: String.eq

  • 利用Sharding-Jdbc组件实现分表

    看到了当当开源的Sharding-JDBC组件,它可以在几乎不修改代码的情况下完成分库分表的实现.摘抄其中一段介绍: Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零: 可适用于任何基于java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC. 可基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid等. 理论上可支持任意实现JDB

  • java版微信公众平台后台接入

    关于微信平台的后台接入,官方已经提供了php示例的下载,对于java这块后台接入,暂时还没有一个完整的案例可以拿来直接使用,我写了一个java版本的demo便于大家使用. 一.前期准备 项目是用maven构建,直接导入到eclipse即可,jdk的版本为1.8.0_111 ,这两项都可以根据实际需求进行修改,最终达成war发布到服务器中即可. 二.实战演练 操作前,先阅读一下官方的文档,先整体有个思路流程,官方地址参考 1.设置成开发者模式: 登录微信公众平台后台后,点「功能」-「高级功能」-「

  • SpringBoot 2.0 整合sharding-jdbc中间件实现数据分库分表

    一.水平分割 1.水平分库 1).概念:  以字段为依据,按照一定策略,将一个库中的数据拆分到多个库中. 2).结果  每个库的结构都一样:数据都不一样:  所有库的并集是全量数据: 2.水平分表 1).概念  以字段为依据,按照一定策略,将一个表中的数据拆分到多个表中. 2).结果  每个表的结构都一样:数据都不一样:  所有表的并集是全量数据: 二.Shard-jdbc 中间件 1.架构图 2.特点 1).Sharding-JDBC直接封装JDBC API,旧代码迁移成本几乎为零. 2).适

  • 开发10年,全记在这本Java进阶宝典里了

    蓦然回首自己做开发已经十年了,这十年中我获得了很多,技术能力.培训.出国.大公司的经历,还有很多很好的朋友.但再仔细一想,这十年中我至少浪费了五年时间,这五年可以足够让自己成长为一个优秀的程序员,可惜我错过了,我用这五年时间和很多程序员一样在困惑和迷茫中找不到出路! 路其实一直都在那里,只是我们看不到而已! 以前我一直被公司和技术牵着走,并不是自己在选择技术,而是不自觉地被推到了这个位置上.想想有多少人对于自己将来要从事的职业和技术类型进行过深入思考和比较呢?当我跳出编码后,我开始思考和程序及程

  • 简单了解Java方法的定义和使用实现详解

    这篇文章主要介绍了简单了解Java方法的定义和使用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.概念 Java语言中的"方法"(Method)在其他语言当中也可能被称为"函数"(Function).对于一些复杂的代码逻辑,如果希望重复使用这些代码,并且做到"随时任意使用",那么就可以将这些代码放在一个大括号"{}"当中,并且起一个名字.使用代码的时候,直接找到名

  • JAVA注解相关知识总结

    注解的概念 java注解: 比较官方的说法: 从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理.通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息. 注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值. 说说我的理解 注解

  • Spring Boot 集成 Sharding-JDBC + Mybatis-Plus 实现分库分表功能

    一. Sharding-jdbc简介 " Sharding-jdbc是开源的数据库操作中间件:定位为轻量级Java框架,在Java的JDBC层提供的额外服务.它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架. 官方文档地址:https://shardingsphere.apache.org/document/current/cn/overview/ 本文demo实现了分库分表功能.如有错误,欢迎各位在评论中指出.不

随机推荐