文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么

2023-06-25 12:27

关注

这篇文章主要讲解了“SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么”吧!

一、前言

SpringBoot整合sharding-jdbc实现分库分表与读写分离

二、简介

1、分片键

用于数据库/表拆分的关键字段

ex: 用户表根据user_id取模拆分到不同的数据库中

2、分片算法

可参考:https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/configuration/built-in-algorithm/sharding

分片策略(分片键+分片算法)

可查看源码 org.apache.shardingsphere.core.yaml.config.sharding.YamlShardingStrategyConfiguration

SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么

三、程序实现

温馨小提示:详情可查看案例demo源码

SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么

这里先贴出完整的application.yml配置,后面实现每一种分片策略时,放开其相应配置即可~

# sharding-jdbc配置spring:  shardingsphere:    # 是否开启SQL显示    props:      sql:        show: true    # ====================== ↓↓↓↓↓↓ 数据源配置 ↓↓↓↓↓↓ ======================    datasource:      names: ds-master-0,ds-slave-0-1,ds-slave-0-2,ds-master-1,ds-slave-1-1,ds-slave-1-2      # ====================== ↓↓↓↓↓↓ 配置第1个主从库 ↓↓↓↓↓↓ ======================      # 主库1      ds-master-0:        type: com.zaxxer.hikari.HikariDataSource        driver-class-name: com.mysql.jdbc.Driver        jdbc-url: jdbc:mysql://127.0.0.1:3306/ds0?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false        username: root        password: root      # 主库1-从库1      ds-slave-0-1:        type: com.zaxxer.hikari.HikariDataSource        driver-class-name: com.mysql.jdbc.Driver        jdbc-url: jdbc:mysql://127.0.0.1:3307/ds0?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false        username: root        password: root      # 主库1-从库2      ds-slave-0-2:        type: com.zaxxer.hikari.HikariDataSource        driver-class-name: com.mysql.jdbc.Driver        jdbc-url: jdbc:mysql://127.0.0.1:3307/ds0?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false        username: root        password: root      # ====================== ↓↓↓↓↓↓ 配置第2个主从库 ↓↓↓↓↓↓ ======================      # 主库2      ds-master-1:        type: com.zaxxer.hikari.HikariDataSource        driver-class-name: com.mysql.jdbc.Driver        jdbc-url: jdbc:mysql://127.0.0.1:3306/ds1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false        username: root        password: root      # 主库2-从库1      ds-slave-1-1:        type: com.zaxxer.hikari.HikariDataSource        driver-class-name: com.mysql.jdbc.Driver        jdbc-url: jdbc:mysql://127.0.0.1:3307/ds1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false        username: root        password: root      # 主库2-从库2      ds-slave-1-2:        type: com.zaxxer.hikari.HikariDataSource        driver-class-name: com.mysql.jdbc.Driver        jdbc-url: jdbc:mysql://127.0.0.1:3307/ds1?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&useSSL=false # MySQL在高版本需要指明是否进行SSL连接 解决则加上 &useSSL=false        username: root        password: root    sharding:      # ====================== ↓↓↓↓↓↓ 读写分离配置 ↓↓↓↓↓↓ ======================      master-slave-rules:        ds-master-0:          # 主库          masterDataSourceName: ds-master-0          # 从库          slaveDataSourceNames:            - ds-slave-0-1            - ds-slave-0-2          # 从库查询数据的负载均衡算法 目前有2种算法 round_robin(轮询)和 random(随机)          # 算法接口 org.apache.shardingsphere.spi.masterslave.MasterSlaveLoadBalanceAlgorithm          # 实现类 RandomMasterSlaveLoadBalanceAlgorithm 和 RoundRobinMasterSlaveLoadBalanceAlgorithm          loadBalanceAlgorithmType: ROUND_ROBIN        ds-master-1:          masterDataSourceName: ds-master-1          slaveDataSourceNames:            - ds-slave-1-1            - ds-slave-1-2          loadBalanceAlgorithmType: ROUND_ROBIN      # ====================== ↓↓↓↓↓↓ 分库分表配置 ↓↓↓↓↓↓ ======================      tables:        t_user:          actual-data-nodes: ds-master-$->{0..1}.t_user$->{0..1}          # 配置属性可参考 org.apache.shardingsphere.core.yaml.config.sharding.YamlShardingStrategyConfiguration          # =========== ↓↓↓↓↓↓ 行表达式分片策略 ↓↓↓↓↓↓ ===========          # 在配置中使用 Groovy 表达式,提供对 SQL语句中的 = 和 IN 的分片操作支持,只支持单分片健。#           # ====== ↓↓↓↓↓↓ 分库 ↓↓↓↓↓↓ ======#          database-strategy:#            inline:#              sharding-column: user_id # 添加数据分库字段(根据字段插入数据到哪个库 ex:user_id)#              algorithm-expression: ds-master-$->{user_id % 2} # 根据user_id取模拆分到不同的库中#           # ====== ↓↓↓↓↓↓ 分表 ↓↓↓↓↓↓ ======#          table-strategy:#            inline:#              sharding-column: sex   # 添加数据分表字段(根据字段插入数据到哪个表 ex:sex)#              algorithm-expression: t_user$->{sex % 2} # 分片算法表达式 => 根据用户性别取模拆分到不同的表中          # =========== ↓↓↓↓↓↓ 标准分片策略 ↓↓↓↓↓↓ ===========          # 精确分片算法 => sql在分库/分表键上执行 = 与 IN 时触发计算逻辑,否则不走分库/分表,全库/全表执行。#          database-strategy:#            standard:#              sharding-column: user_id # 分库用到的键#              precise-algorithm-class-name: com.zhengqing.demo.config.sharding.precise.MyDbPreciseShardingAlgorithm # 自定义分库算法实现类#          table-strategy:#            standard:#              sharding-column: sex # 添加数据分表字段(根据字段插入数据到那个表 ex:sex)#              precise-algorithm-class-name: com.zhengqing.demo.config.sharding.precise.MyTablePreciseShardingAlgorithm # 自定义分表算法实现类          # 范围分片算法 => sql在分库/分表键上执行 BETWEEN AND、>、<、>=、<= 时触发计算逻辑,否则不走分库/分表,全库/全表执行。#          database-strategy:#            standard:#              sharding-column: user_id#              precise-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyDbPreciseShardingAlgorithm#              range-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyDbRangeShardingAlgorithm#          table-strategy:#            standard:#              sharding-column: sex#              precise-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyTablePreciseShardingAlgorithm#              range-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyTableRangeShardingAlgorithm          # =========== ↓↓↓↓↓↓ 复合分片策略 ↓↓↓↓↓↓ ===========          # SQL 语句中有>,>=, <=,<,=,IN 和 BETWEEN AND 等操作符,不同的是复合分片策略支持对多个分片健操作。#          database-strategy:#            complex:#              sharding-columns: user_id,sex#              algorithm-class-name: com.zhengqing.demo.config.sharding.complex.MyDbComplexKeysShardingAlgorithm#          table-strategy:#            complex:#              sharding-columns: user_id,sex#              algorithm-class-name: com.zhengqing.demo.config.sharding.complex.MyTableComplexKeysShardingAlgorithm          # =========== ↓↓↓↓↓↓ hint分片策略 ↓↓↓↓↓↓ ===========          # 通过 Hint API实现个性化配置 => 可查看 com.zhengqing.demo.service.impl.UserServiceImpl.listPageForHint          database-strategy:            hint:              algorithm-class-name: com.zhengqing.demo.config.sharding.hint.MyDbHintShardingAlgorithm          table-strategy:            hint:              algorithm-class-name: com.zhengqing.demo.config.sharding.hint.MyTableHintShardingAlgorithm

行表达式分片策略

# =========== ↓↓↓↓↓↓ 行表达式分片策略 ↓↓↓↓↓↓ ===========# 在配置中使用 Groovy 表达式,提供对 SQL语句中的 = 和 IN 的分片操作支持,只支持单分片健。# ====== ↓↓↓↓↓↓ 分库 ↓↓↓↓↓↓ ======database-strategy:  inline:    sharding-column: user_id # 添加数据分库字段(根据字段插入数据到哪个库 ex:user_id)    algorithm-expression: ds-master-$->{user_id % 2} # 根据user_id取模拆分到不同的库中# ====== ↓↓↓↓↓↓ 分表 ↓↓↓↓↓↓ ======table-strategy:  inline:    sharding-column: sex   # 添加数据分表字段(根据字段插入数据到哪个表 ex:sex)    algorithm-expression: t_user$->{sex % 2} # 分片算法表达式 => 根据用户性别取模拆分到不同的表中

标准分片策略

A: 精确分片算法

# 精确分片算法 => sql在分库/分表键上执行 = 与 IN 时触发计算逻辑,否则不走分库/分表,全库/全表执行。database-strategy:  standard:    sharding-column: user_id # 分库用到的键    precise-algorithm-class-name: com.zhengqing.demo.config.sharding.precise.MyDbPreciseShardingAlgorithm # 自定义分库算法实现类table-strategy:  standard:    sharding-column: sex # 添加数据分表字段(根据字段插入数据到那个表 ex:sex)    precise-algorithm-class-name: com.zhengqing.demo.config.sharding.precise.MyTablePreciseShardingAlgorithm # 自定义分表算法实现类
@Slf4jpublic class MyDbPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {        @Override    public String doSharding(Collection<String> dbNameList, PreciseShardingValue<Long> shardingValue) {        log.info("[MyDbPreciseShardingAlgorithm] SQL执行时传入的分片值: [{}]", shardingValue);        // 根据user_id取模拆分到不同的库中        Long userId = shardingValue.getValue();        for (String dbNameItem : dbNameList) {            if (dbNameItem.endsWith(String.valueOf(userId % 2))) {                return dbNameItem;            }        }        return null;    }}
@Slf4jpublic class MyTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Byte> {        @Override    public String doSharding(Collection<String> tableNameList, PreciseShardingValue<Byte> shardingValue) {        log.info("[MyTablePreciseShardingAlgorithm] SQL执行时传入的分片值: [{}]", shardingValue);        // 根据用户性别取模拆分到不同的表中        Byte sex = shardingValue.getValue();        for (String tableNameItem : tableNameList) {            if (tableNameItem.endsWith(String.valueOf(sex % 2))) {                return tableNameItem;            }        }        return null;    }}

B: 范围分片算法

# 范围分片算法 => sql在分库/分表键上执行 BETWEEN AND、>、<、>=、<= 时触发计算逻辑,否则不走分库/分表,全库/全表执行。database-strategy:  standard:    sharding-column: user_id    precise-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyDbPreciseShardingAlgorithm    range-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyDbRangeShardingAlgorithmtable-strategy:  standard:    sharding-column: sex    precise-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyTablePreciseShardingAlgorithm    range-algorithm-class-name: com.zhengqing.demo.config.sharding.range.MyTableRangeShardingAlgorithm
@Slf4jpublic class MyDbPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {        @Override    public String doSharding(Collection<String> dbNameList, PreciseShardingValue<Long> shardingValue) {        log.info("[MyDbPreciseShardingAlgorithm] SQL执行时传入的分片值: [{}]", shardingValue);        // 根据user_id取模拆分到不同的库中        Long userId = shardingValue.getValue();        for (String dbNameItem : dbNameList) {            if (dbNameItem.endsWith(String.valueOf(userId % 2))) {                return dbNameItem;            }        }        return null;    }}
@Slf4jpublic class MyDbRangeShardingAlgorithm implements RangeShardingAlgorithm<Long> {    @Override    public Collection<String> doSharding(Collection<String> dbNameList, RangeShardingValue<Long> shardingValue) {        log.info("[MyDbRangeShardingAlgorithm] shardingValue: [{}]", shardingValue);        List<String> result = Lists.newLinkedList();        int dbSize = dbNameList.size();        // 从sql 中获取 Between 1 and 1000 的值        // lower:1        // upper:1000        Range<Long> rangeValue = shardingValue.getValueRange();        Long lower = rangeValue.lowerEndpoint();        Long upper = rangeValue.upperEndpoint();        // 根据范围值取偶选择库        for (Long i = lower; i <= upper; i++) {            for (String dbNameItem : dbNameList) {                if (dbNameItem.endsWith(String.valueOf(i % 2))) {                    result.add(dbNameItem);                }                if (result.size() >= dbSize) {                    return result;                }            }        }        return result;    }}
@Slf4jpublic class MyTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Byte> {        @Override    public String doSharding(Collection<String> tableNameList, PreciseShardingValue<Byte> shardingValue) {        log.info("[MyTablePreciseShardingAlgorithm] SQL执行时传入的分片值: [{}]", shardingValue);        // 根据用户性别取模拆分到不同的表中        Byte sex = shardingValue.getValue();        for (String tableNameItem : tableNameList) {            if (tableNameItem.endsWith(String.valueOf(sex % 2))) {                return tableNameItem;            }        }        return null;    }}
@Slf4jpublic class MyTableRangeShardingAlgorithm implements RangeShardingAlgorithm<Byte> {    @Override    public Collection<String> doSharding(Collection<String> tableNameList, RangeShardingValue<Byte> shardingValue) {        log.info("[MyTableRangeShardingAlgorithm] shardingValue: [{}]", shardingValue);        Set<String> tableNameResultList = new LinkedHashSet<>();        Range<Byte> rangeValue = shardingValue.getValueRange();        Byte lower = rangeValue.lowerEndpoint();        Byte upper = rangeValue.upperEndpoint();        // between 0 and 1        // 根据性别值选择表        for (String tableNameItem : tableNameList) {            if (tableNameItem.endsWith(String.valueOf(lower))                    || tableNameItem.endsWith(String.valueOf(upper))) {                tableNameResultList.add(tableNameItem);            }        }        return tableNameResultList;    }}

复合分片策略

# =========== ↓↓↓↓↓↓ 复合分片策略 ↓↓↓↓↓↓ ===========# SQL 语句中有>,>=, <=,<,=,IN 和 BETWEEN AND 等操作符,不同的是复合分片策略支持对多个分片健操作。database-strategy:  complex:    sharding-columns: user_id,sex    algorithm-class-name: com.zhengqing.demo.config.sharding.complex.MyDbComplexKeysShardingAlgorithmtable-strategy:  complex:    sharding-columns: user_id,sex    algorithm-class-name: com.zhengqing.demo.config.sharding.complex.MyTableComplexKeysShardingAlgorithm
@Slf4jpublic class MyDbComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<String> {    @Override    public Collection<String> doSharding(Collection<String> dbNameList, ComplexKeysShardingValue<String> complexKeysShardingValue) {        log.info("[MyDbComplexKeysShardingAlgorithm] complexKeysShardingValue: [{}]", complexKeysShardingValue);        List<String> dbResultList = new ArrayList<>();        int dbSize = dbNameList.size();        // 得到每个分片健对应的值        // 用户id 范围查询        Range<String> rangeUserId = complexKeysShardingValue.getColumnNameAndRangeValuesMap().get("user_id");        // 性别        List<String> sexValueList = this.getShardingValue(complexKeysShardingValue, "sex");        // 对两个分片健进行逻辑操作,选择最终数据进哪一库? TODO        for (String sex : sexValueList) {            String suffix = String.valueOf(Long.parseLong(sex) % 2);            for (String dbNameItem : dbNameList) {                if (dbNameItem.endsWith(suffix)) {                    dbResultList.add(dbNameItem);                }                if (dbResultList.size() >= dbSize) {                    return dbResultList;                }            }        }        return dbResultList;    }    private List<String> getShardingValue(ComplexKeysShardingValue<String> shardingValues, final String key) {        List<String> valueList = new ArrayList<>();        Map<String, Collection<String>> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap();        if (columnNameAndShardingValuesMap.containsKey(key)) {            valueList.addAll(columnNameAndShardingValuesMap.get(key));        }        return valueList;    }}
@Slf4jpublic class MyTableComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {    @Override    public Collection<String> doSharding(Collection<String> tableNameList, ComplexKeysShardingValue<Long> complexKeysShardingValue) {        log.info("[MyTableComplexKeysShardingAlgorithm] complexKeysShardingValue: [{}]", complexKeysShardingValue);        Set<String> tableNameResultList = new LinkedHashSet<>();        int tableSize = tableNameList.size();        // 用户id 范围查询        Range<Long> rangeUserId = complexKeysShardingValue.getColumnNameAndRangeValuesMap().get("user_id");        Long lower = rangeUserId.lowerEndpoint();        Long upper = rangeUserId.upperEndpoint();        // 根据user_id选择表 TODO ...        for (String tableNameItem : tableNameList) {            if (tableNameItem.endsWith(String.valueOf(lower % 2))                    || tableNameItem.endsWith(String.valueOf(upper % 2))) {                tableNameResultList.add(tableNameItem);            }            if (tableNameResultList.size() >= tableSize) {                return tableNameResultList;            }        }        return tableNameResultList;    }}

Hint分片策略

#=========== ↓↓↓↓↓↓ hint分片策略 ↓↓↓↓↓↓ ===========# 通过 Hint API实现个性化配置 => 可查看 com.zhengqing.demo.service.impl.UserServiceImpl.listPageForHintdatabase-strategy:  hint:    algorithm-class-name: com.zhengqing.demo.config.sharding.hint.MyDbHintShardingAlgorithmtable-strategy:  hint:    algorithm-class-name: com.zhengqing.demo.config.sharding.hint.MyTableHintShardingAlgorithm
@Slf4jpublic class MyDbHintShardingAlgorithm implements HintShardingAlgorithm<Integer> {    @Override    public Collection<String> doSharding(Collection<String> dbNameList, HintShardingValue<Integer> hintShardingValue) {        log.info("[MyDbHintShardingAlgorithm] hintShardingValue: [{}]", hintShardingValue);        Collection<String> dbResultList = new ArrayList<>();        int dbSize = dbNameList.size();        for (String dbNameItem : dbNameList) {            for (Integer shardingValue : hintShardingValue.getValues()) {                if (dbNameItem.endsWith(String.valueOf(shardingValue % 2))) {                    dbResultList.add(dbNameItem);                }                if (dbResultList.size() >= dbSize) {                    return dbResultList;                }            }        }        return dbResultList;    }}
@Slf4jpublic class MyTableHintShardingAlgorithm implements HintShardingAlgorithm<Integer> {    @Override    public Collection<String> doSharding(Collection<String> tableNameList, HintShardingValue<Integer> hintShardingValue) {        log.info("[MyTableHintShardingAlgorithm] hintShardingValue: [{}]", hintShardingValue);        Collection<String> tableResultList = new ArrayList<>();        int tableSize = tableNameList.size();        Collection<Integer> hintShardingValueValueList = hintShardingValue.getValues();        for (String tableName : tableNameList) {            for (Integer shardingValue : hintShardingValueValueList) {                if (tableName.endsWith(String.valueOf(shardingValue % 2))) {                    tableResultList.add(tableName);                }                if (tableResultList.size() >= tableSize) {                    return tableResultList;                }            }        }        return tableResultList;    }}

使用时动态触发如下:

public IPage<User> listPageForHint() {   // 清除掉上一次的规则,否则会报错    HintManager.clear();    // HintManager API 工具类实例    HintManager hintManager = HintManager.getInstance();    // 库 => 主要是将value值传送到 MyDbHintShardingAlgorithm 中做逻辑分库处理    hintManager.addDatabaseShardingValue("t_user", 100);    hintManager.addDatabaseShardingValue("t_user", 1000);    // 指定表的分片健 => 指定查t_user0    hintManager.addTableShardingValue("t_user", 0);//        hintManager.addTableShardingValue("t_user", 1);    // 读写分离强制读主库,避免造成主从复制导致的延迟    hintManager.setMasterRouteOnly();    // 查询数据    Page<User> result = this.userMapper.selectPage(new Page<>(1, 10),            new LambdaQueryWrapper<User>()                    .eq(User::getSex, "0")                    .between(User::getUserId, 1L, 1000L)    );    // 清除规则    hintManager.close();    return result;}

感谢各位的阅读,以上就是“SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么”的内容了,经过本文的学习后,相信大家对SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯