1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > SpringBoot整合Sharding-JDBC实现水平分库分表

SpringBoot整合Sharding-JDBC实现水平分库分表

时间:2019-06-20 01:46:00

相关推荐

SpringBoot整合Sharding-JDBC实现水平分库分表

目录

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

前言

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

关于水平分库分表可以参考文章:/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>

实体类

@Datapublic 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接口

@Mapperpublic 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

@Servicepublic 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和m2spring.shardingsphere.datasource.names=m1,m2spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.m1.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.m1.url=jdbc:mysql://127.0.0.1:3306/order_db_1?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTCspring.shardingsphere.datasource.m1.username=rootspring.shardingsphere.datasource.m1.password=123456spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.m2.driver-class-name=com.mysql.jdbc.Driverspring.shardingsphere.datasource.m2.url=jdbc:mysql://127.0.0.1:3306/order_db_2?characterEncoding=utf8&useSSL=false&autoReconnect=true&serverTimezone=UTCspring.shardingsphere.datasource.m2.username=rootspring.shardingsphere.datasource.m2.password=123456# 分库策略,以 user_id 为分片键spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id# 分片策略为 user_id 为偶数操作 m1 数据源,否则操作 m2spring.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_2spring.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_idspring.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_2spring.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/*.xmlmybatis.configuration.cache-enabled=true# 开启驼峰命名mybatis.configuration.map-underscore-to-camel-case=true

user_id:分库策略,以user_id为分片键m$->{user_id % 2 + 1}:分片策略表达式,user_id为偶数操作m1数据源,否则操作m2order_id:分表策略,以order_id为分片键t_order_$->{order_id % 2 + 1}:分片策略表达式,order_id为偶数的数据落在t_order_1表,为奇数的落在t_order_2表更多详细的配置文档说明:/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会去每一张表中去查询

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。