经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MyBatis » 查看文章
SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分库分表
来源:jb51  时间:2022/3/1 11:38:21  对本文有异议

一、序言

在实际业务中,单表数据增长较快,很容易达到数据瓶颈,比如单表百万级别数据量。当数据量继续增长时,数据的查询性能即使有索引的帮助下也不尽如意,这时可以引入数据分库分表技术。

本文将基于SpringBoot+MybatisPlus+Sharding-JDBC+Mysql实现企业级分库分表。

1、组件及版本选择

  • SpringBoot 2.6.x
  • MybatisPlus 3.5.0
  • Sharding-JDBC 4.1.1
  • Mysql 5.7.35

2、预期目标

  • 使用上述组件实现分库分表,简化起见只讨论分表技术
  • 完成分表后的逻辑表与物理表间的增删查改
  • 引入逻辑删除和使用MybatisPlus内置分页技术

完整项目源码访问地址

二、代码实现

为了简化分表复杂性,专注于分表整体实现,简化分表逻辑:按照UserId的奇偶属性分别进行分表。以订单表这一典型场景为例,一般来说有关订单表,通常具有如下共性行为:

  • 创建订单记录
  • 查询XX用户的订单列表
  • 查询XX用户的订单列表(分页)
  • 查询XX订单详情
  • 修改订单状态
  • 删除订单(逻辑删除)

接下来通过代码实现上述目标。

(一)素材准备

1、实体类

  1. @Data
  2. @TableName("bu_order")
  3. public class Order {
  4. @TableId
  5. private Long orderId;
  6. private Integer orderType;
  7. private Long userId;
  8. private Double amount;
  9. private Integer orderStatus;
  10. @TableLogic
  11. @JsonIgnore
  12. private Boolean deleted;
  13. }

2、Mapper类

  1. @Mapper
  2. public interface OrderMapper extends BaseMapper<Order> {
  3. }

3、全局配置文件

  1. spring:
  2. config:
  3. use-legacy-processing: true
  4. shardingsphere:
  5. datasource:
  6. ds1:
  7. driver-class-name: com.mysql.cj.jdbc.Driver
  8. type: com.alibaba.druid.pool.DruidDataSource
  9. url: jdbc:mysql://127.0.0.1:3306/sharding-jdbc2?serverTimezone=UTC
  10. username: root
  11. password: 123456
  12. names: ds1
  13. props:
  14. sql:
  15. show: true
  16. sharding:
  17. tables:
  18. bu_order:
  19. actual-data-nodes: ds1.bu_order_$->{0..1}
  20. key-generator:
  21. column: order_id
  22. type: SNOWFLAKE
  23. table-strategy:
  24. inline:
  25. algorithm-expression: bu_order_${user_id%2}
  26. sharding-column: user_id

(二)增删查改

1、保存数据

由于依据主键的奇偶属性对原表分表,分表后每张表的数据量是分表前的二分之一。根据需要也可以自定义分表数量(比如10张),新分表后的数据量是不分表前的十分之一。

  1. @Test
  2. public void addOrders() {
  3. for (long i = 1; i <= 10; i++) {
  4. Order order = new Order();
  5. order.setOrderId(i);
  6. order.setOrderType(RandomUtil.randomEle(Arrays.asList(1, 2)));
  7. order.setUserId(RandomUtil.randomEle(Arrays.asList(101L, 102L, 103L)));
  8. order.setAmount(1000.0 * i);
  9. orderMapper.insert(order);
  10. }
  11. }

2、查询列表数据

查询指定用户的订单列表。

  1. @GetMapping("/list")
  2. public AjaxResult list(Order order) {
  3. LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery(order);
  4. return AjaxResult.success(orderMapper.selectList(wrapper));
  5. }

3、分页查询数据

分页查询指定用户的订单列表

  1. @GetMapping("/page")
  2. public AjaxResult page(Page<Order> page, Order order) {
  3. return AjaxResult.success(orderMapper.selectPage(page, Wrappers.lambdaQuery(order)));
  4. }

4、查询详情

通过订单ID查询订单详情。

  1. @GetMapping("/detail/{orderId}")
  2. public AjaxResult detail(@PathVariable Long orderId) {
  3. return AjaxResult.success(orderMapper.selectById(orderId));
  4. }

5、删除数据

通过订单ID删除订单(逻辑删除)

  1. @DeleteMapping("/delete/{orderId}")
  2. public AjaxResult delete(@PathVariable Long orderId) {
  3. return AjaxResult.success(orderMapper.deleteById(orderId));
  4. }

6、修改数据

修改数据一般涉及部分列,比如修改订单表的订单状态等。

  1. @PutMapping("/edit")
  2. public AjaxResult edit(@RequestBody Order order) {
  3. return AjaxResult.success(orderMapper.updateById(order));
  4. }

三、理论分析

1、选择分片列

选择分片列是经过精心对比后确定的,对于订单类场景,需要频繁以用户ID为查询条件筛选数据,因此将同一个用户的订单数据存放在一起有利于提高查询效率。

2、扩容

当分表后的表数据快速增长,可以预见即将达到瓶颈时,需要对分表进行扩容,扩容以2倍的速率进行,扩容期间需要迁移数据,工作量相对可控。

到此这篇关于SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分库分表 的文章就介绍到这了,更多相关SpringBoot分库分表 内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号