SpringBoot整合Sharding-JDBC实现水平分库分表
目录
- 前言
- 需求说明
- 数据库表创建
- 编写程序
- 引入 `maven` 依赖
- 实体类
- `dao` 层
- `Mapper` 接口
- `Mapper.xml`
- `Service` 层
- `Controller` 层
- `application.properties` 文件
- 接口测试
- 数据插入测试
- 数据查询测试
前言
在 上一篇文章 中我们实现了水平分表,也就是两张列,字段完全相同的表在同一个数据库中,没有完成数据库的水平分割,这篇文章来完成水平方向的分库分表
关于水平分库分表可以参考文章:https://blog.csdn.net/weixin_38192427/article/details/122441366
需求说明
水平分库是把同一个表的 数据
按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。如 order_db_1
和 order_db_2
两个数据库,它们分别部署在不同的服务器上,这两个库中的表分别都有 t_order_1
和 t_order_2
两张表,这两张表的列,字段都是相同的。分别创建数据库,表,完成数据的插入与查询
数据库表创建
分别创建订单库 order_db_1
与 order_db_2
,然后在 order_db_1
与 order_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_1
或t_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
,结果如下
由于传入的参数 orderId
和 userId
均为奇数,所以数据应该落到数据库 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实现水平分库分表相关推荐
- springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码)
springboott整合mybatis-plus和sharding-jdbc实现分库分表和读写分离(含完整项目代码) 一.整合sharding-jdbc 关于springboot整合sharding ...
- 你分库分表的姿势对么?——详谈水平分库分表
作者:vivo平台产品开发团队-Han Lei 一.背景 提起分库分表,对于大部分服务器开发来说,其实并不是一个新鲜的名词.随着业务的发展,我们表中的数据量会变的越来越大,字段也可能随着业务复杂度的升 ...
- 水平分库分表的关键问题及解决思路(转)
水平分库分表的关键问题及解决思路 分片技术的由来 关系型数据库本身比较容易成为系统性能瓶颈,单机存储容量.连接数.处理能力等都很有限,数据库本身的"有状态性"导致了它并不像Web和 ...
- 水平分库分表的关键步骤以及可能遇到的问题
http://www.infoq.com/cn/articles/key-steps-and-likely-problems-of-horizontal-split-table 分片技术的由来 关系型 ...
- mysql sharding 知乎_分库分表系列(1)-shardingsphere核心概念
欢迎关注公众号: 戏说码农职场 咱们不闲扯, 就直接入正题, 这次总结说下sharding-jdbc 分库分表的工具.整体架构 Apache ShardingSphere 是一套开源的分布式数据库中间 ...
- 数据库水平分库分表后的数据分页查询解决方案
2021-09-04 更: 推荐下自己的个人框架,后面代码都会移植到框架中 链接 2020-10-19 更: 月底不出意外,打算重构了,fabric区块链框架改的差不多了 2020-10-? 更: 谢 ...
- Oracle之垂直水平分库分表(一)
现在开始讲另外一个知识点吧,这个知识点也是怎么说呢,就是非常有用的知识点,刚才看了一下表空间 现在咱们说一下ORACLE里面的表类型,表类型其实有这么多种表1. 正常我们的heap table,堆表, ...
- 水平分库分表的关键步骤和技术难点,分库分表的几种常见玩法及如何解决跨库查询等问题...
http://blog.csdn.net/dinglang_2009/article/details/53195871 http://blog.csdn.net/dinglang_2009/artic ...
- Oracle之垂直水平分库分表(二)
对于拆分的解决方案这块,上节课我们讲到了如何去拆分,然后拆分有些问题,引入了一系列的问题,比如说分布式事务的问题,关于分布式事务这个事啊,其实挺不好解决的,就是根据情况吧,咱们在这里说三个方案,你针对 ...
- 基于springboot的ShardingSphere5.2.1的分库分表的解决方案之数据加密之RSA的解决方案(九)
1.需求场景 我们需要将密码字段采用公钥进行加密,然后用户查询的时候根据用户名称进行查询,同时将密码通过私钥解密出来返回给到用户,那么我们现在就开始模拟实现以上的场景,因此我们直接创建了shardin ...
最新文章
- 模板 - KM算法(O(n^3))(二分图最大权完美匹配)
- 一个美国女警的工作记录(转载)
- Swift 4.1增强了泛型、编译器和包管理器
- 使用SGD(Stochastic Gradient Descent)进行大规模机器学习
- 杭州高职单招计算机试题,河北省高职单招职业技能练习题20
- WebApiClient的JsonPatch局部更新
- ObjectContext.Refresh
- typec扩展坞hdmi没反应_typec扩展坞转hdmi/vga多功能网口usb转换器苹果华为电脑matebook6元优惠券券后价26.8元...
- webUI自动化一元素定位
- 大学生使用计算机趋势英语作文,学习使用电脑StudentUseofComputers
- 小D课堂 - 新版本微服务springcloud+Docker教程_6-05 高级篇幅之高并发情况下
- dubbo 自定义filter
- mysql 怎么导入sql文件_如何在MySQL中使用命令行导入SQL文件?
- Kolmogorov 的数学观与业绩
- python开根号函数的实现
- 解决黑苹果睡眠唤醒后立马死机(AppleHDAHDMI_DPDriver)
- HTTP 错误 404.3 - Not Found 由于扩展配置问题而无法提供您请求的页面。如果该页面是脚本,请添加处理程序。如果应下载文件,请添加 MIME 映射。
- 51个最佳jQuery教程和示例
- uis向3d投影全息界面的连续演化。
- 基于机器学习的车牌识别系统
热门文章
- linux命令行中的大括号,linux命令行学习(19):花括号扩展(brace expansion)
- java 正则表达式 unicode_java正则表达式中的POSIX 字符类和Unicode 块和类别的类介绍...
- 641. 设计循环双端队列
- 双极性根升余弦信号qpsk_基于CCSDS协议的中频信号源设计与实现
- 浪潮信息能制造超级计算机吗,浪潮信息为中国航天探索事业出力 高性能计算技术领衔...
- pwm 正弦波_增强型PWM抑制功能对于直列式电机控制的五大优势
- 【16年浙江省赛 B ZOJ 3937】More Health Points【树上dfs、斜率优化dp、动态维护下凸壳】
- python docx 表格样式修改 Package not found at ‘*.docx‘; “no style with name ‘Table Grid‘“
- linux 自动开飞行模式,Android飞行模式灰显不能操作问题分解
- Java 并发编程常识 —— by 梁飞