浅谈Sharding-JDBC强制路由案例实战

 更新时间:2023年07月27日 15:19:32   作者:硕风和炜  
本文主要介绍了浅谈Sharding-JDBC强制路由案例实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

🍀 一.Sharding-JDBC强制路由基本概念

在一些应用场景中,分片条件依赖于外部业务逻辑。因此需要提供一种通过在外部业务代码中指定路由配置的一种方式,在ShardingSphere中叫做Hint。如果使用Hint指定了强制分片路由,那么SQL将会无视原有的分片逻辑,直接路由至指定的数据节点操作。ShardingSphere使用ThreadLocal管理分片键值进行Hint强制路由。可以通过编程的方式向HintManager中添加分片值,该分片值仅在当前线程内生效。

Hint使用场景:

  • 数据分片操作,如果分片键没有在SQL或数据表中,而是在业务逻辑代码中
  • 读写分离操作,如果强制在主库进行某些数据操作

Sharding-JDBC强制路由案例实战官方指导手册

🍀 二.Sharding-JDBC强制路由案例实战

2.1 数据环境准备

没有创建过的同学们需要在 ljw_course_db1ljw_course_db2中创建 t_course表.

CREATE TABLE `t_course` (
  `cid` bigint(20) NOT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  `corder_no` bigint(20) DEFAULT NULL,
  `cname` varchar(50) DEFAULT NULL,
  `brief` varchar(50) DEFAULT NULL,
  `price` double DEFAULT NULL,
  `status` int(11) DEFAULT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.2 创建SpringBoot程序 - 导入依赖

引入依赖 (注意: 在这里使用ShardingSphere4.1版本为案例进行强制路由的实战)

<?xml version="1.0" encoding="UTF-8"?>
<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>
    <artifactId>shardingjdbc-hint</artifactId>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/>
    </parent>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-core-common</artifactId>
            <version>4.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.10</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.5.8</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>2.0.5</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>20.0</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.3 创建SpringBoot程序 - 实体类

与数据库表中对应的实体类

@TableName("t_course")
@Data
@ToString
public class Course {
    @TableId(type = IdType.ASSIGN_ID)
    private Long cid;
    private Long userId;
    private Long corderNo;
    private String cname;
    private String brief;
    private double price;
    private int status;
}

2.4 创建SpringBoot程序 - 数据库Mapper接口 & 主启动类

编写对应的数据库持久层CourseMapper接口

@Repository
public interface CourseMapper extends BaseMapper<Course> {
}

@Repository注解的类需要交给我们的Spring容器进行管理,因此需要我们在主启动类加上扫描接口的注解。

@SpringBootApplication
@MapperScan("com.ljw.mapper")
public class ShardingSphereApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShardingSphereApplication.class,args);
    }
}

2.5 创建SpringBoot程序 - 自定义强制路由配置类

在自定义类中编写分库或分表路由策略,实现HintShardingAlgorithm接口,并且重写doSharding方法

public class HintShardingAlgorithmConfig implements HintShardingAlgorithm<Long> {
    /**
     * 定义强制路由策略
     *      collection: 代表分片目标: 对哪些数据库 表进行分片,比如做分库路由,集合中就存储着 db1.t_course, db1.t_course
     *      hintShardingValue: 代表分片值, 指的是使用者对分片键赋的值
     */
    @Override
    public Collection<String> doSharding(Collection<String> collection, HintShardingValue<Long> hintShardingValue) {
        // 结果收集
        Collection<String> result = new ArrayList<>();
        // 遍历数据库
        // collection: 代表分片目标: 对哪些数据库 表进行分片,比如做分库路由,集合中就存储着 db1.t_course, db1.t_course
        for (String actualDb : collection) {
            // hintShardingValue: 代表分片值, 指的是使用者对分片键赋的值
            Collection<Long> values = hintShardingValue.getValues();
            for (Long value : values) {
                //分库路由 判断当前节点名称结尾 是否与取模结果一致
                if(actualDb.endsWith(String.valueOf(value % 2 + 1))){
                    result.add(actualDb);
                }
            }
        }
        return result;
    }
}

2.6 创建SpringBoot程序 - 强制路由配置文件

配置读写分离相关配置的信息

# 应用名称
spring.application.name=sharding-jdbc-hint
# 打印SQl
spring.shardingsphere.props.sql-show=true
# 定义多个数据源
spring.shardingsphere.datasource.names = db1,db2
# 数据源1
spring.shardingsphere.datasource.db1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db1.jdbc-url=jdbc:mysql://192.168.10.132:3306/ljw_course_db1?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
# 数据源2
spring.shardingsphere.datasource.db2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db2.jdbc-url=jdbc:mysql://192.168.10.133:3306/ljw_course_db2?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
# 配置默认数据源db1
spring.shardingsphere.sharding.default-data-source-name=db1
# Hint强制路由
# 使用t_course表测试强制路由到库
spring.shardingsphere.sharding.tables.t_course.database-strategy.hint.algorithm-class-name=com.ljw.hint.HintShardingAlgorithmConfig
# 强制路由到指定表
spring.shardingsphere.sharding.tables.t_course.table-strategy.hint.algorithm-class-name=com.ljw.hint.HintShardingAlgorithmConfig
#配置数据节点 指定t_course逻辑表表的真实分布情况
spring.shardingsphere.sharding.tables.t_course.actual-data-nodes=db$->{1..2}.t_course_$->{1..2}

🍀 三.Sharding-JDBC强制路由案例测试

先将我们数据库中表中原来的数据都删除掉,如果是新建的同学就不用了!

3.1 强制路由到库测试

    @Autowired
    private CourseMapper courseMapper;
    //测试强制路由 到指定库的插入操作
    @Test
    public void testInsertCourse(){
        //通过hintManager指定执行策略的分片键的值
        HintManager hintManager = HintManager.getInstance();
        //强制路由到db2,此时我们需要传入1,因为我们配置类的逻辑是vlaue%2+1->1%2+1
        hintManager.setDatabaseShardingValue(1L);
        for (int i = 0; i < 6; i++) {
            Course course = new Course();
            course.setUserId(1000L+i);
            course.setCname("Sharding-JDBC强制路由案例实战");
            course.setBrief("全网Sharding-JDBC强制路由案例实战最详细讲解!!!");
            course.setPrice(8939.00);
            course.setStatus(0);
            courseMapper.insert(course);
        }
    }

运行结果:

3.2 强制路由到库到表测试

@Autowired
    private CourseMapper courseMapper;
    @Test
    public void testHintDbToTable(){
        HintManager hintManager = HintManager.getInstance();
        //强制路由到指定库 -> db2
        hintManager.addDatabaseShardingValue("t_course",1L);
        //强制路由到指定表 ->course1
        hintManager.addTableShardingValue("t_course",0L);
        List<Course> courses = courseMapper.selectList(null);
        courses.forEach(System.out::println);
    }

运行结果:

🍀 四.总结

本篇文章主要讲解了Sharding-JDBC强制路由案例实战,实操过程非常重要,大家一定要动手亲自实践一下,更多相关Sharding-JDBC强制路由内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java通过jersey实现客户端图片上传示例

    Java通过jersey实现客户端图片上传示例

    本篇文章主要介绍了Java通过jersey实现客户端图片上传示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • java字符串拼接与性能分析详解

    java字符串拼接与性能分析详解

    在JAVA中拼接两个字符串的最简便的方式就是使用操作符”+”。如果你用”+”来连接固定长度的字符串,可能性能上会稍受影响,但是如果你是在循环中来”+”多个串的话,性能将指数倍的下降,下面我们分析一下JAVA字符串拼接的性能
    2014-01-01
  • jstl之map,list访问遍历以及el表达式map取值的实现

    jstl之map,list访问遍历以及el表达式map取值的实现

    下面小编就为大家带来一篇jstl之map,list访问遍历以及el表达式map取值的实现。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 大数组元素差异removeAll与Map效率对比

    大数组元素差异removeAll与Map效率对比

    这篇文章主要介绍了大数组元素差异removeAll与Map效率对比,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Java多边形重心计算

    Java多边形重心计算

    今天小编就为大家分享一篇关于Java多边形重心计算,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • 关于Java集合框架面试题(含答案)下

    关于Java集合框架面试题(含答案)下

    Java集合框架为Java编程语言的基础,也是Java面试中很重要的一个知识点。这里,我列出了一些关于Java集合的重要问题和答案。
    2015-12-12
  • 深入理解Java动态代理与静态代理

    深入理解Java动态代理与静态代理

    这篇文章主要介绍了深入理解Java动态代理与静态代理,静态代理,代理类和被代理的类实现了同样的接口,代理类同时持有被代理类的引用,动态代理的根据实现方式的不同可以分为JDK动态代理和CGlib动态代理
    2022-06-06
  • 使用JPA双向多对多关联关系@ManyToMany

    使用JPA双向多对多关联关系@ManyToMany

    这篇文章主要介绍了使用JPA双向多对多关联关系@ManyToMany,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • SpringBoot快速构建应用程序方法介绍

    SpringBoot快速构建应用程序方法介绍

    这篇文章主要介绍了SpringBoot快速构建应用程序方法介绍,涉及SpringBoot默认的错误页面,嵌入式Web容器层面的约定和定制等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
    2017-11-11
  • Springboot Thymeleaf字符串对象实例解析

    Springboot Thymeleaf字符串对象实例解析

    这篇文章主要介绍了Springboot Thymeleaf字符串对象实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2007-09-09

最新评论