目录

  • 前言
  • 需求说明
  • 数据库表创建
  • 编写程序
    • 引入 `maven` 依赖
    • 实体类
    • `dao` 层
      • `Mapper` 接口
      • `Mapper.xml`
    • `Service` 层
    • `Controller` 层
    • `application.properties` 文件
  • 接口测试
    • 数据插入测试
    • 数据查询测试

前言

在 上一篇文章 中我们实现了水平分表,也就是两张列,字段完全相同的表在同一个数据库中,没有完成数据库的水平分割,这篇文章来完成水平方向的分库分表

关于水平分库分表可以参考文章:https://blog.csdn.net/weixin_38192427/article/details/122441366

需求说明

水平分库是把同一个表的 数据 按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。如 order_db_1order_db_2 两个数据库,它们分别部署在不同的服务器上,这两个库中的表分别都有 t_order_1t_order_2 两张表,这两张表的列,字段都是相同的。分别创建数据库,表,完成数据的插入与查询

数据库表创建

分别创建订单库 order_db_1order_db_2,然后在 order_db_1order_db_2中再分别创建 t_order_1、t_order_2 表,可以看到两张表的列是完全相同的

CREATE TABLE `t_order_1` (`order_id` int(11) NOT NULL COMMENT '订单id',`price` decimal(10,2) NOT NULL COMMENT '订单价格',`user_id` int(11) NOT NULL COMMENT '下单用户id',`status` varchar(50) CHARACTER SET utf8mb4 NOT NULL COMMENT '订单状态',PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;CREATE TABLE `t_order_2` (`order_id` int(11) NOT NULL COMMENT '订单id',`price` decimal(10,2) NOT NULL COMMENT '订单价格',`user_id` int(11) NOT NULL COMMENT '下单用户id',`status` varchar(50) CHARACTER SET utf8mb4 NOT NULL COMMENT '订单状态',PRIMARY KEY (`order_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

如下图所示

编写程序

引入 maven 依赖

主要依赖如下,其它依赖自行引入

<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version>
</dependency>

实体类

@Data
public class Order implements Serializable {@NotNull(message = "参数orderId不能为空")private Integer orderId;@NotNull(message = "参数price不能为空")private BigDecimal price;@NotNull(message = "参数userId不能为空")private Integer userId;@NotBlank(message = "参数status不能为空")private String status;
}

dao

Mapper 接口

@Mapper
public interface OrderMapper {int insertOrder(Order order);List<Order> findOrderByIds(List<Integer> orderIds);
}

Mapper.xml

<insert id="insertOrder" parameterType="org.example.pojo.Order">insert into t_order(order_id, price, user_id, status)values (#{orderId,jdbcType=INTEGER}, #{price,jdbcType=DECIMAL}, #{userId,jdbcType=INTEGER},#{status,jdbcType=VARCHAR})
</insert><select id="findOrderByIds" parameterType="java.util.List" resultType="org.example.pojo.Order">select<include refid="Base_Column_List"></include>from t_order AS twhere t.order_id in<foreach collection="list" item="id" open="(" separator="," close=")">#{id}</foreach>
</select>
  • 注意 SQL 语句的写法,抽象表名是 t_order,并不是具体的 t_order_1t_order_2

Service

@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderMapper orderMapper;@Overridepublic int insertOrder(Order order) {return orderMapper.insertOrder(order);}@Overridepublic List<Order> getOrderByIds(List<Integer> orderIds) {return orderMapper.findOrderByIds(orderIds);}
}

Controller

@Controller
@RequestMapping(path = "/order")
public class OrderController {@Autowiredprivate OrderService orderService;@PostMapping(path = "/addOrder")@ResponseBodypublic ResultMap addOrder(@Valid Order order, @NotNull BindingResult bindingResult) {// 参数校验if (bindingResult.hasErrors()) {String message = bindingResult.getFieldError().getDefaultMessage();return new ResultMap().fail().message(message);}int i = orderService.insertOrder(order);if (i > 0) {return new ResultMap().success().message("成功");}return new ResultMap().fail().message("失败");}@GetMapping(path = "/getOrder")@ResponseBodypublic ResultMap getOrder(@NotNull @RequestBody List<Integer> orderIds) {if (orderIds.isEmpty()) {return new ResultMap().fail().message("参数orderIds不能为空");}List<Order> orderList = orderService.getOrderByIds(orderIds);if (orderList.isEmpty()) {return new ResultMap().fail().message("没有查询到你想要的数据");}return new ResultMap().success().data(orderList).message("查询成功");}
}

application.properties 文件

server.port=8080# sharding-jdbc分片规则配置开始---------------------------------------------------------------
# 自定义数据源名称为 m1和m2
spring.shardingsphere.datasource.names=m1,m2spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://127.0.0.1:3306/order_db_1?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123456spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://127.0.0.1:3306/order_db_2?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTC
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=123456# 分库策略,以 user_id 为分片键
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id
# 分片策略为 user_id 为偶数操作 m1 数据源,否则操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=m$->{user_id % 2 + 1}# 指定表的数据分布情况,其中t_order可以自定义,配置数据节点 m1.t_order_1,m1.t_order_2,m2.t_order_1,m2.t_order_2
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=m$->{1..2}.t_order_$->{1..2}# 指定t_order表的主键是order_id,主键生成策略为SNOWFLAKE,它是一种分布式自增算法,保证id全局唯一
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE# 指定t_order表的分片策略,分片策略包括分片键和分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
# order_id为偶数的数据落在t_order_1,为奇数的落在t_order_2
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2 + 1}# 打开sql输出日志
spring.shardingsphere.props.sql.show=true
# sharding-jdbc分片规则配置结束---------------------------------------------------------------# 指定 mapper 文件路径
mybatis.mapper-locations=cldasspath:com/example/mapper/*.xml
mybatis.configuration.cache-enabled=true
# 开启驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true
  • user_id:分库策略,以 user_id 为分片键
  • m$->{user_id % 2 + 1}:分片策略表达式,user_id 为偶数操作 m1 数据源,否则操作 m2
  • order_id:分表策略,以 order_id 为分片键
  • t_order_$->{order_id % 2 + 1}:分片策略表达式,order_id 为偶数的数据落在 t_order_1 表,为奇数的落在t_order_2
  • 更多详细的配置文档说明:https://shardingsphere.apache.org/document/legacy/3.x/document/cn/manual/sharding-jdbc/configuration/config-spring-boot/

接口测试

数据插入测试

启动项目,使用 postman 测试接口 http://localhost:8080/order/addOrder,结果如下


由于传入的参数 orderIduserId 均为奇数,所以数据应该落到数据库 order_db_2 中的 t_order_2 表中,如下


在看看控制台 SQL 日志,如下


再看看数据库 order_db_1 中的 t_order_2 表数据,依然是空的

  • 参数 userId 来确定数据具体要插入到哪个数据库之中
  • 参数 orderId 来确定数据具体要插入到哪个表之中

数据查询测试

先查看 order_db_1 数据库中 t_order_1 表的数据如下


再查看 order_db_2 数据库中 t_order_2 表的数据如下


启动项目,使用 postman 测试接口 http://localhost:8080/order/getOrder,传入的参数 orderIds[1,2] 的数组,进行批量查询,结果如下


在看看控制台 SQL 日志,如下

  • 可以看到,这样的 SQL 语句出现了 2 次,因为总共有 4 张表,Sharding-JDBC 会去每一张表中去查询

SpringBoot整合Sharding-JDBC实现水平分库分表相关推荐

  1. springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码)

    springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码) 一.整合sharding-jdbc 关于springboot整合sharding ...

  2. 你分库分表的姿势对么?——详谈水平分库分表

    作者:vivo平台产品开发团队-Han Lei 一.背景 提起分库分表,对于大部分服务器开发来说,其实并不是一个新鲜的名词.随着业务的发展,我们表中的数据量会变的越来越大,字段也可能随着业务复杂度的升 ...

  3. 水平分库分表的关键问题及解决思路(转)

    水平分库分表的关键问题及解决思路 分片技术的由来 关系型数据库本身比较容易成为系统性能瓶颈,单机存储容量.连接数.处理能力等都很有限,数据库本身的"有状态性"导致了它并不像Web和 ...

  4. 水平分库分表的关键步骤以及可能遇到的问题

    http://www.infoq.com/cn/articles/key-steps-and-likely-problems-of-horizontal-split-table 分片技术的由来 关系型 ...

  5. mysql sharding 知乎_分库分表系列(1)-shardingsphere核心概念

    欢迎关注公众号: 戏说码农职场 咱们不闲扯, 就直接入正题, 这次总结说下sharding-jdbc 分库分表的工具.整体架构 Apache ShardingSphere 是一套开源的分布式数据库中间 ...

  6. 数据库水平分库分表后的数据分页查询解决方案

    2021-09-04 更: 推荐下自己的个人框架,后面代码都会移植到框架中 链接 2020-10-19 更: 月底不出意外,打算重构了,fabric区块链框架改的差不多了 2020-10-? 更: 谢 ...

  7. Oracle之垂直水平分库分表(一)

    现在开始讲另外一个知识点吧,这个知识点也是怎么说呢,就是非常有用的知识点,刚才看了一下表空间 现在咱们说一下ORACLE里面的表类型,表类型其实有这么多种表1. 正常我们的heap table,堆表, ...

  8. 水平分库分表的关键步骤和技术难点,分库分表的几种常见玩法及如何解决跨库查询等问题...

    http://blog.csdn.net/dinglang_2009/article/details/53195871 http://blog.csdn.net/dinglang_2009/artic ...

  9. Oracle之垂直水平分库分表(二)

    对于拆分的解决方案这块,上节课我们讲到了如何去拆分,然后拆分有些问题,引入了一系列的问题,比如说分布式事务的问题,关于分布式事务这个事啊,其实挺不好解决的,就是根据情况吧,咱们在这里说三个方案,你针对 ...

  10. 基于springboot的ShardingSphere5.2.1的分库分表的解决方案之数据加密之RSA的解决方案(九)

    1.需求场景 我们需要将密码字段采用公钥进行加密,然后用户查询的时候根据用户名称进行查询,同时将密码通过私钥解密出来返回给到用户,那么我们现在就开始模拟实现以上的场景,因此我们直接创建了shardin ...

最新文章

  1. 模板 - KM算法(O(n^3))(二分图最大权完美匹配)
  2. 一个美国女警的工作记录(转载)
  3. Swift 4.1增强了泛型、编译器和包管理器
  4. 使用SGD(Stochastic Gradient Descent)进行大规模机器学习
  5. 杭州高职单招计算机试题,河北省高职单招职业技能练习题20
  6. WebApiClient的JsonPatch局部更新
  7. ObjectContext.Refresh
  8. typec扩展坞hdmi没反应_typec扩展坞转hdmi/vga多功能网口usb转换器苹果华为电脑matebook6元优惠券券后价26.8元...
  9. webUI自动化一元素定位
  10. 大学生使用计算机趋势英语作文,学习使用电脑StudentUseofComputers
  11. 小D课堂 - 新版本微服务springcloud+Docker教程_6-05 高级篇幅之高并发情况下
  12. dubbo 自定义filter
  13. mysql 怎么导入sql文件_如何在MySQL中使用命令行导入SQL文件?
  14. Kolmogorov 的数学观与业绩
  15. python开根号函数的实现
  16. 解决黑苹果睡眠唤醒后立马死机(AppleHDAHDMI_DPDriver)
  17. HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
  18. 51个最佳jQuery教程和示例
  19. uis向3d投影全息界面的连续演化。
  20. 基于机器学习的车牌识别系统

热门文章

  1. linux命令行中的大括号,linux命令行学习(19):花括号扩展(brace expansion)
  2. java 正则表达式 unicode_java正则表达式中的POSIX 字符类和Unicode 块和类别的类介绍...
  3. 641. 设计循环双端队列
  4. 双极性根升余弦信号qpsk_基于CCSDS协议的中频信号源设计与实现
  5. 浪潮信息能制造超级计算机吗,浪潮信息为中国航天探索事业出力 高性能计算技术领衔...
  6. pwm 正弦波_增强型PWM抑制功能对于直列式电机控制的五大优势
  7. 【16年浙江省赛 B ZOJ 3937】More Health Points【树上dfs、斜率优化dp、动态维护下凸壳】
  8. python docx 表格样式修改 Package not found at ‘*.docx‘; “no style with name ‘Table Grid‘“
  9. linux 自动开飞行模式,Android飞行模式灰显不能操作问题分解
  10. Java 并发编程常识 —— by 梁飞