SpringBoot3分库分表

news2025/2/28 16:07:56

标签:ShardingSphere5.分库.分表;

一、简介

分库分表的设计和实现方式,在之前的内容中总结过很多,本文基于SpringBoot3ShardingSphere5框架实现数据分库分表的能力;

不得不提ShardingSphere5文档中描述的两个基本概念:

垂直分片

按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。

水平分片

水平分片又称为横向拆分。 相对于垂直分片,它不再将数据根据业务逻辑分类,而是通过某个字段(或某几个字段),根据某种规则将数据分散至多个库或表中,每个分片仅包含数据的一部分。

下面从案例实践中,看看ShardingSphere5框架是如何实现分库分表的原理;

二、工程搭建

1、工程结构

2、依赖管理

这里只看两个核心组件的依赖:shardingsphere-jdbc组件是5.2.1版本,mybatis组件是3.5.13版本,在依赖管理中还涉及MySQL和分页等,并且需要添加很多排除配置,具体见源码;

<!-- Mybatis组件 -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis.version}</version>
</dependency>

<!-- ShardingSphere分库分表 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

三、配置详解

1、配置文件

此处只展示分库分表的相关配值,默认数据源使用db_master库,注意tb_order库表路由的策略和分片算法的关联关系,其他工程配置详见源码仓库;

spring:
  # 分库分表配置
  shardingsphere:
    datasource:
      # 默认数据源
      sharding:
        default-data-source-name: db_master
      names: db_master,db_0,db_1
      db_master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shard_db
        username: root
        password: 123456
      db_0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shard_db_0
        username: root
        password: 123456
      db_1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/shard_db_1
        username: root
        password: 123456
    rules:
      sharding:
        tables:
          # tb_order逻辑
          tb_order:
            actual-data-nodes: db_${0..1}.tb_order_${0..2}
            # tb_order库路由
            database-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: database_inline
            # tb_order表路由
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: table_inline
        sharding-algorithms:
          # tb_order库路由算法
          database_inline:
            type: INLINE
            props:
              algorithm-expression: db_${order_id % 2}
          # tb_order表路由算法
          table_inline:
            type: INLINE
            props:
              algorithm-expression: tb_order_${order_id % 3}
    props:
      sql-show: true
      sql-comment-parse-enabled: true

2、配置原理

在配置中需要管理三个数据源,shard_db默认库,在操作不涉及需要路由的表时默认使用该数据源,shard_db_0shard_db_1tb_order逻辑表的路由库;

逻辑表tb_order整体使用两个数据库,每个库建3张结构相同相同的表,在操作tb_order数据时,会根据order_id字段值定位数据所属的分片节点;

  • 库路由db_${0..1}采用db_${order_id%2}的算法;
  • 表路由tb_order_${0..2}采用tb_order_${order_id%3}的算法;

四、测试案例

1、主库操作

基于Mybatis持久层框架,实现对shard_db默认库的数据操作,注意控制台的日志打印,可以看到一系列解析逻辑以及库表节点的定位,分页查询使用PageHelper组件即可;

public class MasterTest {
    @Autowired
    private BuyerMapper buyerMapper ;
    @Autowired
    private SellerMapper sellerMapper ;
    @Test
    public void testBuyerQuery (){
        // 主键查询
        Buyer buyer = buyerMapper.selectByPrimaryKey(1) ;
        System.out.println(buyer.getId()+";"+buyer.getBuyerName());
    }
    @Test
    public void testBuyerInsert (){
        // 新增数据
        Buyer buyer = new Buyer() ;
        buyer.setBuyerName("买家Three");
        System.out.println(buyerMapper.insert(buyer));
    }
    @Test
    public void testBuyerUpdate (){
        // 更新数据
        Buyer buyer = buyerMapper.selectByPrimaryKey(3) ;
        if (buyer != null){
            buyer.setBuyerName("Three买家");
            System.out.println(buyerMapper.updateByPrimaryKey(buyer));
        }
    }
    @Test
    public void testSellerPage (){
        // 1、设置分页和查询条件
        PageHelper.startPage(2,2) ;
        SellerExample sellerExample = new SellerExample() ;
        sellerExample.setOrderByClause("id asc");
        // 2、查询数据
        List<Seller> sellerList = sellerMapper.selectByExample(sellerExample) ;
        // 3、构建分页实体对象
        PageInfo<Seller> pageInfo = new PageInfo<>(sellerList) ;
        System.out.println(pageInfo);
    }
}

2、分库操作

在对tb_order表执行增删改查时,会根据order_id的字段值计算库表的路由节点,注意分页时会查询所有的分库和分表,然后汇总查询的结果;

public class ShardTest {
    @Autowired
    private OrderMapper orderMapper ;
    /**
     * 写入100条数据
     */
    @Test
    public void testOrderInsert (){
        for (int i=1 ; i<= 100 ; i++){
            Order order = new Order(i,i%3+1,i%3+1) ;
            // orderMapper.insert(order) ;
        }
    }
    @Test
    public void testOrderQuery (){
        Order order = orderMapper.selectByPrimaryKey(5) ;
        System.out.println(order);
    }
    @Test
    public void testOrderUpdate (){
        Order order = orderMapper.selectByPrimaryKey(100) ;
        if (order != null){
            // 原数据:买家和卖家ID都是2
            order.setBuyerId(1);
            order.setSellerId(3);
            orderMapper.updateByPrimaryKey(order) ;
        }
    }

    @Test
    public void testOrderPage (){
        // 1、设置分页和查询条件
        PageHelper.startPage(1,10) ;
        OrderExample orderExample = new OrderExample() ;
        orderExample.createCriteria().andBuyerIdEqualTo(2).andSellerIdEqualTo(2);
        orderExample.setOrderByClause("order_id desc");
        // 2、查询数据
        List<Order> orderList = orderMapper.selectByExample(orderExample) ;
        // 3、构建分页实体对象
        PageInfo<Order> pageInfo = new PageInfo<>(orderList) ;
        System.out.println(pageInfo);
    }
}

3、综合查询

编写一个订单详情查询接口,同时使用三个库构建数据结构;如果是基于列表数据的检索,比较常规做法的是构建ES索引结构,如果没有搜索的需求,可以在订单表分页查询后去拼接其他结构;

@RestController
public class OrderController {

    @Resource
    private BuyerMapper buyerMapper ;
    @Resource
    private SellerMapper sellerMapper ;
    @Resource
    private OrderMapper orderMapper ;

    /**
     * 查询订单详情
     */
    @GetMapping("/order/info/{orderId}")
    public Map<String,Object> orderInfo (@PathVariable Integer orderId){
        Map<String,Object> orderMap = new HashMap<>() ;
        Order order = orderMapper.selectByPrimaryKey(orderId) ;
        if (order != null){
            orderMap.put("order",order) ;
            orderMap.put("buyer",buyerMapper.selectByPrimaryKey(order.getBuyerId())) ;
            orderMap.put("seller",sellerMapper.selectByPrimaryKey(order.getSellerId())) ;
        }
        return orderMap ;
    }
}

查看SQL语句

db_master ::: select id, buyer_name from tb_buyer where id = ? ::: [1]
db_master ::: select id, seller_name from tb_seller where id = ? ::: [3]
db_0 ::: select order_id, seller_id, buyer_id from tb_order_1 where order_id = ? ::: [100]

五、参考源码

文档仓库:
https://gitee.com/cicadasmile/butte-java-note

源码仓库:
https://gitee.com/cicadasmile/butte-spring-parent

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/862187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

伪类和伪元素有何区别?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 伪类&#xff08;Pseudo-class&#xff09;⭐ 伪元素&#xff08;Pseudo-element&#xff09;⭐ 区别总结⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前…

.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法

前言 前段时间有朋友问道一个这样的问题&#xff0c;.NET Core中如何通过Attribute的元数据信息来调用标记的对应方法。我第一时间想到的就是通过C#反射获取带有Custom Attribute标记的类&#xff0c;然后通过依赖注入&#xff08;DI&#xff09;的方式获取对应服务的方法并通过…

应用在智能仓储温湿度监测系统中的温度传感芯片

近年来各行各业越来越重视产品的仓库、冷库存储环境&#xff0c;食品、药品、化工产品的保存都离不开冷库。温湿度是影响冷库环境的主要因素&#xff0c;建立实时的温湿度监控系统&#xff0c;保存查看完整的历史温湿度数据十分必要。 物资的保存对存储环境的质量要求较为严格…

Spring IoC 详解

目录 一、引言二、Spring Bean三、将一个类声明为 Bean 所涉及的注解四、Component 和 Bean 的区别五、注入 Bean 的注解六、Autowired 和 Resource 的区别七、Bean7.1 作用域7.2 线程安全7.3 生命周期 一、引言 IoC&#xff08;Inversion of Control:控制反转&#xff09; 是…

JUC线程池的实战问题引出的一系列原理问题

1 我们为什么需要使用线程池 线程过多会带来额外的开销&#xff0c;其中包括创建销毁线程的开销、调度线程的开销等等&#xff0c;同时也降低了计算机的整体性能。线程池维护多个线程&#xff0c;等待、监督、管理、分配可并发执行的任务。这种做法&#xff0c;一方面避免了处…

分享3款屏幕录制软件,一定要来看!

在数字化时代&#xff0c;屏幕录制软件成为了一个必不可少的工具。它可以帮助用户捕捉并记录计算机屏幕上的活动&#xff0c;因此选择一款功能强大、易于使用的屏幕录制软件至关重要。本文将介绍3款备受好评的屏幕录制软件&#xff0c;通过本文的阅读&#xff0c;您将了解到它们…

Android图形-刷新与显示

目录 屏幕显示原理&#xff1a; 显示刷新的过程 VSYNC机制具体实现 小结&#xff1a; 屏幕显示原理&#xff1a; 过程描述&#xff1a; 应用向系统服务申请buffer 系统服务返回一个buffer给应用 应用开始绘制&#xff0c;绘制完成就提交buffer&#xff0c;系统服务把buffer数据…

两年了^

我也想不到是到了现在 记得刚来腾讯工作半年时候&#xff0c;我写了一篇文章 在腾讯的这半年 之后&#xff0c;又经过了半年时间&#xff0c;我又写了一篇总结文章 一年了 现在又过了一年多&#xff0c;本想把两年的入职截图留下&#xff0c;之前因为微信存储太大把微信卸载后重…

实现功能:ChatGPT 微信助手可以自动搜索网络信息回答问题

“ ChatGPT微信助手升级内测功能上线&#xff01;原先只能回答通用问题,现在遇到需要查询具体信息的问题也不愁啦。” 01 — 最近&#xff0c;上线了ChatGPT微信助手的体验群&#xff1a;《ChatGPT 微信助手上线&#xff01;问答更便捷&#xff0c;功能持续升级中。》&#xff…

Android高手进阶教程(一)-------Android常用名令集锦(图文并茂)!

大家好&#xff0c;今天我们要讲的是android开发中&#xff0c;比较常用的名令集锦&#xff0c; 在我们开发中难免用到Android命令&#xff0c;有些确实命令确实很有用处。 特别对于一些初学者来说&#xff0c;命令根本没有想过用也不会用&#xff0c;比如他们想安装一个.apk文…

以太网网络安全协议(十三)

一、IPsec协议 IPsec。它是指在IP首部的后面追加“封装安全有效载荷”&#xff08;ESP&#xff09;和“认证首部”&#xff08;AH&#xff09; &#xff0c;从而对此后的数据进行加密&#xff0c;不被盗取者轻易解读。 二、TLS/SLL协议 SSL最早由网景公司提出&#xff0c;标准化…

架构设计第42讲:美团 - 可视化全链路日志追踪

架构设计第42讲&#xff1a;美团 - 可视化全链路日志追踪 目前在分布式场景下&#xff0c;业务追踪的主流实现方式包括两类&#xff0c;一类是基于日志的ELK方案&#xff0c;一类是基于单次请求调用的会话跟踪方案。然而随着业务逻辑的日益复杂&#xff0c;上述方案越来越不适用…

8月10日,每日信息差

1、菜鸟国际快递“承诺达、晚必赔”覆盖22国。具体来讲&#xff0c;菜鸟国际快递对无忧、经济和简易三种标准产品全面升级&#xff0c;其中英国、意大利、加拿大、美国四国时效平均提升30%以上。凡使用这三种快递产品发货至22国的商家&#xff0c;其货物在速卖通电商平台享有“…

网络安全 Day29-运维安全项目-iptables防火墙

iptables防火墙 1. 防火墙概述2. 防火墙2.1 防火墙种类及使用说明2.2 必须熟悉的名词2.3 iptables 执行过程※※※※※2.4 表与链※※※※※2.4.1 简介2.4.2 每个表说明2.4.2.1 filter表 :star::star::star::star::star:2.4.2.2 nat表 2.5 环境准备及命令2.6 案例01&#xff1a…

月度资金预算情况表取的数和结算页面不一样,是为什么?

月度资金预算情况表取的数和结算页面不一样&#xff0c;如下图&#xff0c;是为什么&#xff1f; 取数公式&#xff1a; CMPRFS(‘[收支项目01030101] ‘,K(‘单位’),’’,‘’,‘0’,ZDATEQC(‘-’),ZDATE(‘-’),‘1’,‘’,‘’)CMPRFS(‘[收支项目01030102] ‘,K(‘单位…

最新版本2023UI千月影视APP源码 开源完美版前后端完美匹配 后端基于ThinkPHP框架

最新版本的2023UI千月影视APP源码是一款开源的完美版应用程序&#xff0c;具备前后端完美匹配的特点。该应用的后端开发基于ThinkPHP框架&#xff0c;这是一个广泛使用的PHP开发框架&#xff0c;具有稳定性和安全性方面的优势。 2023UI千月影视APP是一款提供电影、电视剧、综艺…

文旅虚拟IP内卷国风,底层流量密码是什么?

数字化浪潮下&#xff0c;文旅虚拟IP已逐渐成为数字经济时代全新的增长风口以及传统文化传播载体。 虚拟IP具有极高的辨识度和可塑性&#xff0c;既可以作为虚拟主播在线上直播聊天互动&#xff0c;又可以化身虚拟解说员带你学习传统文化&#xff0c;还可以化身虚拟向导带你玩…

我与金融 —— 境外支付系统之安全测试实践(一)

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

【雕爷学编程】Arduino动手做(12)---霍尔模块之霍尔磁感应声光报警器(磁控开关,接220V)

37款传感器与模块的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&#x…

前端探索之旅

目录 简介:内容大纲:第一章 前端开发简介1.1 前端开发的定义和作用1.2 前端开发的职责1.3 前端开发的技能要求1.4 前端开发的发展前景总结&#xff1a; 第二章 HTML基础2.1 HTML基本结构2.2 常见HTML标签和元素 第三章 CSS基础3.1 CSS基本语法3.2 常见CSS选择器3.3 常见CSS属性…