java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Sharding-JDBC强制路由

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

作者:硕风和炜

本文主要介绍了浅谈Sharding-JDBC强制路由案例实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

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

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

Hint使用场景:

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强制路由内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文