一、序言

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

本文将基于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、实体类
@Data
@TableName("bu_order")
public class Order {
@TableId
private Long orderId;
private Integer orderType;
private Long userId;
private Double amount;
private Integer orderStatus;
@TableLogic
@JsonIgnore
private Boolean deleted;
}
2、Mapper类
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}
3、全局配置文件
spring:
config:
use-legacy-processing: true
shardingsphere:
datasource:
ds1:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/sharding-jdbc2?serverTimezone=UTC
username: root
password: 123456
names: ds1
props:
sql:
show: true
sharding:
tables:
bu_order:
actual-data-nodes: ds1.bu_order_$->{0..1}
key-generator:
column: order_id
type: SNOWFLAKE
table-strategy:
inline:
algorithm-expression: bu_order_${user_id%2}
sharding-column: user_id

(二)增删查改

1、保存数据

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

@Test
public void addOrders() {
for (long i = 1; i <= 10; i++) {
Order order = new Order();
order.setOrderId(i);
order.setOrderType(RandomUtil.randomEle(Arrays.asList(1, 2)));
order.setUserId(RandomUtil.randomEle(Arrays.asList(101L, 102L, 103L)));
order.setAmount(1000.0 * i);
orderMapper.insert(order);
}
}
2、查询列表数据

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

@GetMapping("/list")
public AjaxResult list(Order order) {
LambdaQueryWrapper<Order> wrapper = Wrappers.lambdaQuery(order);
return AjaxResult.success(orderMapper.selectList(wrapper));
}
3、分页查询数据

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

@GetMapping("/page")
public AjaxResult page(Page<Order> page, Order order) {
return AjaxResult.success(orderMapper.selectPage(page, Wrappers.lambdaQuery(order)));
}
4、查询详情

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

@GetMapping("/detail/{orderId}")
public AjaxResult detail(@PathVariable Long orderId) {
return AjaxResult.success(orderMapper.selectById(orderId));
}
5、删除数据

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

@DeleteMapping("/delete/{orderId}")
public AjaxResult delete(@PathVariable Long orderId) {
return AjaxResult.success(orderMapper.deleteById(orderId));
}
6、修改数据

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

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

三、理论分析

1、选择分片列

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

2、扩容

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


SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分库分表实践的更多相关文章

  1. mysql、oracle分库分表方案之sharding-jdbc使用(非demo示例)

    选择开源核心组件的一个非常重要的考虑通常是社区活跃性,一旦项目团队无法进行自己后续维护和扩展的情况下更是如此. 至于为什么选择sharding-jdbc而不是Mycat,可以参考知乎讨论帖子https ...

  2. Mysql中的分库分表

    mysql中的分库分表分库:减少并发问题分表:降低了分布式事务分表 1.垂直分表 把其中的不常用的基础信息提取出来,放到一个表中通过id进行关联.降低表的大小来控制性能,但是这种方式没有解决高数据量带 ...

  3. MySQL纯透明的分库分表技术还没有

    MySQL纯透明的分库分表技术还没有  种树人./oneproxy --proxy-address=:3307 --admin-username=admin --admin-password=D033 ...

  4. Mycat安装并实现mysql读写分离,分库分表

    Mycat安装并实现mysql读写分离,分库分表 一.安装Mycat 1.1 创建文件夹 1.2 下载 二.mycat具体配置 2.1 server.xml 2.2 schema.xml 2.3 se ...

  5. Docker安装Mycat并实现mysql读写分离,分库分表

    Docker安装Mycat并实现mysql读写分离,分库分表 一.拉取mycat镜像 二.准备挂载的配置文件 2.1 创建文件夹并添加配置文件 2.1.1 server.xml 2.1.2 serve ...

  6. MyCat | 分库分表实践

    引言 先给大家介绍2个概念:数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式. 切分模式 一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切可以称之 ...

  7. MariaDB Spider 数据库分库分表实践

    分库分表 一般来说,数据库分库分表,有以下做法: 按哈希分片:根据一条数据的标识计算哈希值,将其分配到特定的数据库引擎中: 按范围分片:根据一条数据的标识(一般是值),将其分配到特定的数据库引擎中: ...

  8. mycat+ mysql集群 分库分表

    mycat介绍Mycat数据库分库分表中间件国内最活跃的.性能最好的开源数据库中间件!Mycat关键特性关键特性支持SQL92标准支持MySQL.Oracle.DB2.SQL Server.Postg ...

  9. 【ShardingSphere技术专题】「ShardingJDBC」SpringBoot之整合ShardingJDBC实现分库分表(JavaConfig方式)

    前提介绍 ShardingSphere介绍 ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC.Sharding-Proxy和Shardin ...

随机推荐

  1. scanf报错问题

    VS2013 scanf()函数报错问题. 编译器就是说这个环境下用scanf()函数不安全,建议使用scanf_s()函数.如何要使用scanf()函数的话,就需要在头文件或者源文件开头加上:use ...

  2. Java集合-ArrayList源码分析

    目录 1.结构特性 2.构造函数 3.成员变量 4.常用的成员方法 5.底层数组扩容原理 6.序列化原理 7.集合元素排序 8.迭代器的实现 9.总结 1.结构特性 Java ArrayList类使用 ...

  3. 与Elasticsearch交互的客户端

    1.访问ES的方式 访问es的方式有两种,一种是http方式,还有一种是java客户端方式. 其中Java客户端又分为:1.1.Node client: 节点客户端实际上是一个集群中的节点(但不保存数 ...

  4. openSUSE修改grub来修复对win8的引导

    前言:继上一次安装试用各版本linux发行版后,由于做项目将机器纯windows了一把,现在又想安回centos,各种挫折折腾两天玩残一个u盘日,其中包括自己本本的原装系统也崩了,各种泪奔,下面记录一 ...

  5. gin中的SecureJSON 防止 json 劫持

    使用 SecureJSON 防止 json 劫持.如果给定的结构是数组值或map,则默认预置 "while(1)," 到响应体. package main import ( &qu ...

  6. 近期Android学习

    近5天没有更新博客,因为这几天略微放下了python的学习,android这边连带项目比较急迫,先花大约1个星期的时间把重心放在Android,但python肯定还会坚持下去,毕竟连着学了那么久了. ...

  7. 多种方式告诉你如何计算DM同步数据到TiDB的延时时间

    背景 用户在做技术选型的过程中,总是会对一些数据指标比较关心,特别是在和竞品相比较的时候,更加需要一些有说服力的数据.基于MySQL开发的项目在迁移到TiDB的时候,使用DM同步数据是必不可少的一个环 ...

  8. JAVA多线程学习五:线程范围内共享变量&ThreadLocal

    一.概念 可以将每个线程用到的数据与对应的线程号存放到一个map集合中,使用数据时从这个集合中根据线程号获取对应线程的数据,就可以实现线程范围内共享相同的变量. 二.代码 Runnable中的run( ...

  9. Android WebView组件 访问部分网页崩溃问题【已解决】

    最近刚接触Android,在测试WebView组件时发现总是出现崩溃现像: 提示:ERR_CLEARTEXT_NOT_PERMITTED 当时以为是权限问题,查找自己的AndroidManifest文 ...

  10. linux上printf出带颜色字体

    转载请注明来源:https://www.cnblogs.com/hookjc/ 统一定义: #define NONE         "\033[m"  #define RED   ...