sharding-jdbc分库分表(一)
创始人
2024-03-20 09:38:42
0

以商城商品为例

垂直分表:将一个表按照字段分成多表,每个表存储其中一部分字段

它带来的提升是:

1、为了避免IO争抢并减少锁表的几率,查看详情的用户与商品信息浏览相互不影响

2、充分发挥热门数据的操作效率,商品信息的操作的高效率不会被商品描述的低效率所拖累

垂直分库:

垂直分库是指按照业务将表进行分类,分页到不同的数据库上面,每个库可以放在不同的服务器上,它的核心理念是专库专用

它带来的提升是:

1、解决业务层面的耦合,业务清晰

2、能对不同业务的数据进行分组管理,维护,监控,扩展等

3、高并发场景下,垂直分库一定程度的提升IO,数据库连接数,降低单机硬件资源的瓶颈

垂直分库通过将表按业务分类,然后分布在不同数据库,并且可以将这些数据库部署在不同服务器上,从而达到多个服务器共同分摊压力的效果,但是依然没有解决单表数据量过大的问题。

水平分库:

是把同一个表的数据按一定规则拆到不同的数据库中,每个库可以放在不同的服务器上。

它带来的提升是:

1、解决了单库大数据,高并发的性能瓶颈

2、提高了系统的稳定性及可用性。稳定性体现在IO冲突少,锁定减少,可用性指某个库出问题,部分数据可用 

水平分表:

水平分表是在同一个数据库内,把同一个表的数据按一定规则拆到多个表中

它带来的提升是:

1、优化单一表数据量过大而产生的性能问题

2、避免IO争抢并减少锁表的几率

分库分表带来的问题:

1、事务一致性问题

        由于分库分表把数据分页在不同库甚至不同服务器,不可避免分带来分页式事务问题

2、跨节点关联查询

3、跨节点分页、排序、函数

4、主键重复问题

在分库分表环境中,由于表中数据同时存在不同的数据库中,主键值平时使用的自增长 将无用武之地,某个分区数据库生成的ID无法保证全局唯一。因此需要单独设计全局主键,以避免跨库主键重复问题

5、公共表

实际的应用场景中,参数表,数据字典表等都是数据量较少,变动少,而且属于高频联合查询的依赖表。

可以将这类表在每个数据库都保存一份,所有对公共表的更新操作都同时发送到所有分库执行

由于分库分表之后,数据被分散在不同的数据库、服务器。因此,对数据的操作也就无法通过常规方式完成,并且它还带来了一系列的问题。

Sharding-jdbc介绍

sharding-jdbc是当当网研发的开源分页式数据库中间件,从3.0开始Sharding-jdbc被包含在Sharding-Sphere,之后该项目进入 Apache,4.0版本之后的版本为Apache版本

Sharding-jdbc它定位为级Java框架,在java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

Sharding-jdbc的核心功能为数据分片和读写分离,通过Sharding-JDBC,应用可以透明的使用jdbc访问已经分库分表、读写分离的多个数据源,而不用关心数据源的数量以及数据如何分页。

与jdbc性能对比:

1、性能损耗测试:服务器资源充足、并发数相同,比较JDBC和Sharding-JDBC性能损耗,sharding-jdbc相对JDBC损耗不超过7%

2、性能对比测试:服务器资源使用到极限,相同场景JDBC与sharding-jdbc的吞吐量相当

3、性能对比测试:服务器资源使用到极限,sharding-jdbc采用分库分表后,sharding-jdbc吞吐量较JDBC不分表有接近2倍提升

sharding-jdbc快速入门

使用sharding-jdbc完成对订单表的水平分表,通过快速入门程序的开发,快速体验sharding-jdbc的使用方法。

人工创建两张表,t_order_1和t_order_2,这两张表是订单表拆分后的表,通过sharding-jdbc向订单表插入数据,按照一定的分片规则,主键为偶数的进入t_order_1,另一部分数据进入t_order_2,通过sharding-jdbc查询数据,根据SQL语句的内容从t_order_1或t_order_2查询数据。

代码mode(水平分表):

配置yml

server:port: 8082servlet:context-path: /sharding-jdbc-simple-demospring:application:name: sharding-jdbc-simple-demohttp:encoding:enabled: truecharset: UTF-8force: true#shrading-jdbc配置shardingsphere:datasource:names: m1m1:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/shareding?useUnicode=trueusername: rootpassword: 123456sharding:  #指定t_order表的数据分页情况,配置数据节点 m1.t_order_1 m1.t_order_2tables:t_order:actual-data-nodes: m1.t_order_$->{1..2}key-generator:column: id #主键字段type: SNOWFLAKE #指定t_order表主键生成策略table-strategy: #指定t_order表的分片策略,分片策略包括分片键和分片算法inline:sharding-column: id #分片键algorithm-expression: t_order_$->{id%2+1} #分片算法props:sql:show: true #输出sharding-jdbc的真实sqlmybatis:configuration:map-underscore-to-camel-case: trueswagger:enable: true
logging:level:root: infoorg:springframeword:web: infocn:ping: debugdruid:sql: debug

maven:


org.springframework.bootspring-boot-starter-parent2.0.3.RELEASE4.0.0sharding-jdbc-simpleorg.springframework.bootspring-boot-starter-webcom.alibabadruid-spring-boot-starter1.2.11mysqlmysql-connector-java5.1.46com.baomidoumybatis-plus-boot-starter3.5.1org.apache.shardingspheresharding-jdbc-spring-boot-starter4.0.0-RC1org.projectlomboklombokio.springfoxspringfox-swagger-ui2.8.0org.springframework.bootspring-boot-starter-test

mysql创建表:

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

实体类:

package cn.ping.entity;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Builder;
import lombok.Data;import java.math.BigDecimal;/*** @author: yejianping* @date: 2022/12/5 15:12:25* @email: 1152665905@qq.com* @Description:*/
@Data
@Builder
@TableName("t_order")
public class Order {private Long id;private BigDecimal price;private Long userId;private String status;
}

mapper类:

package cn.ping.mapper;import cn.ping.entity.Order;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;import java.util.List;/*** @author: yejianping* @date: 2022/12/5 15:14:17* @email: 1152665905@qq.com* @Description:*/
public interface OrderMapper extends BaseMapper {List selectOrderList(@Param("position") Integer startPosition, @Param("size")Integer size);
}

mapper.xml





service

package cn.ping.server;import cn.ping.entity.Order;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;import java.util.List;/*** @author: yejianping* @date: 2022/12/5 15:16:52* @email: 1152665905@qq.com* @Description:*/
public interface IOrderService extends IService {/*** 通过ids查询Order* @param ids* @return*/List getOrderByIds(List ids);IPage getOrderPage(Integer page,Integer size);List getOrderList(Integer page,Integer size);
}

serviceImpl

package cn.ping.server.impl;import cn.ping.entity.Order;
import cn.ping.mapper.OrderMapper;
import cn.ping.server.IOrderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.util.List;/*** @author: yejianping* @date: 2022/12/5 15:21:06* @email: 1152665905@qq.com* @Description:*/
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl implements IOrderService {@Overridepublic List getOrderByIds(List ids) {if(CollectionUtils.isEmpty(ids)){return null;}return this.listByIds(ids);}@Overridepublic IPage getOrderPage(Integer page, Integer size) {LambdaQueryWrapper lqw = new LambdaQueryWrapper();lqw.orderByDesc(Order::getPrice);return page(new Page<>(page,size),lqw);}@Overridepublic List getOrderList(Integer page,Integer size){return this.baseMapper.selectOrderList((page-1)*size,size);}}

测试类

package cn.ping;import cn.ping.entity.Dog;
import cn.ping.entity.Order;
import cn.ping.server.IDogService;
import cn.ping.server.IOrderService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;/*** @author: yejianping* @date: 2022/12/5 15:22:35* @email: 1152665905@qq.com* @Description:*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingJdbcSimpleApplication.class})
@Slf4j
public class OrderTest {@Autowiredprivate IOrderService orderService;@Autowiredprivate IDogService dogService;@Testpublic void testOrderInsert(){List orderList = new ArrayList<>();for (int i = 0; i < 20; i++) {Order order = Order.builder().price(new BigDecimal(new Random().nextInt(100))).status("SUCCESS").userId(1L).build();orderList.add(order);}orderService.saveBatch(orderList);/*Order order = Order.builder().price(new BigDecimal(10)).status("SUCCESS").userId(1L).build();orderService.save(order);*/}@Testpublic void testFindByIds(){Long[] ids = {1599673041937334275L,1599673040175726594L};List orderByIds = orderService.getOrderByIds(Arrays.asList(ids));for (Order order : orderByIds) {log.info(order.toString());}}@Testpublic void testOrderPage(){IPage orderPage = orderService.getOrderPage(1, 10);for (Order order : orderPage.getRecords()) {log.info(order.toString());}}@Testpublic void testOrderList(){List orderList = orderService.getOrderList(1, 10);for (Order order : orderList) {log.info(order.toString());}}
}

sharding-jdbc和mybatis plus分页冲突,不能使用分页插件,查询总数有问题

相关内容

热门资讯

你的晚安是我的早安是什么歌曲 你的晚安是我的早安是什么歌曲苏天伦《你的早安是我的晚安》“你的晚安是我的早安”是单小源的歌曲《东京遇...
积极进取的小故事 积极进取的小故事现代的普通人,不要名人的。不能与别人重复,尽快回答   啄木鸟的故事       啄...
熊出没之探险日记3什么时候播出... 熊出没之探险日记3什么时候播出?熊出没之探险日记3,春节前播放。熊出没只是探险日记三2020年5月4...
谁知道所有有关“七”的歌?拜托... 谁知道所有有关“七”的歌?拜托了各位 谢谢就是歌曲名里有“七”这个字的!谢谢七月七迅谈日晴 看我七十...
求一本小说 女主穿越了三次 每... 求一本小说 女主穿越了三次 每次都在福临身边 后来怀孕了孩子被打掉了那个 女主叫什么雯?那个女主就是...
如果记忆不说话,流年也会开出花... 如果记忆不说话,流年也会开出花的基本信息书 名:《如果记忆不弯饥好说话,流年也会开出花》埋铅 作 者...
你好,旧时光漫画版在哪里可以看... 你好,旧时光漫画版在哪里可以看?暂时在绘心上连载
一首英文歌,男的组合唱的,MV... 一首英文歌,男的组合唱的,MV是一个婚礼的过程。求歌名。是不是darin的can'tstoplove...
为什么很多人喜欢用胶片相机? 为什么很多人喜欢用胶片相机?有一种情怀叫做“怀旧“吧,现在数码相机越来越普遍了,已经到了”全民摄影“...
女主先爱上男主,男主却不喜欢女... 女主先爱上男主,男主却不喜欢女主或者是另有所爱,最后女主男主还是在一起的穿越小说。有木有再生缘:我的...
爱情失恋伤感句子 爱情失恋伤感句子越是美好的从前,越幸福的曾经,现在只能带来锥心的疼痛,痛到撕心裂肺,肝肠寸断,终于痛...
24岁穿这个会不会显老 24岁穿这个会不会显老有点显老,这个颜色款式,颜色有点暗,没有活力,属于那种气质佳,长得高雅的女人,...
哈尔的移动城堡英语版 哈尔的移动城堡英语版可以发给我吗度盘~请查收~
秦时明月之万里长城什么时候播 秦时明月之万里长城什么时候播据说是今年暑假开播别急,官网什么的信他你就输了,12年之前底应该会出,杭...
孩子会得抽动症吗? 孩子会得抽动症吗?我天生的气性比较大,有时跟别人斗嘴时候就会手脚哆嗦,麻木,我问一下这是不是抽动症就...
亨德尔一生为音乐献出了怎样的贡... 亨德尔一生为音乐献出了怎样的贡献?亨德尔一生写了歌剧41部,清唱剧21部,以及大量的管乐器与弦乐器的...
礼仪起源和发展的经典故事? 礼仪起源和发展的经典故事?一、礼仪的起源;1、天神生礼仪;2、礼为天地人的统一体;3、礼产生于人的自...
描写桂林山水的句子有哪些? 描写桂林山水的句子有哪些?天下风光数桂林有杨万里的“梅花五岭八桂林,青罗带绕碧玉簪”;有邹应龙的“无...
避免与强敌正面对决的成语 避免与强敌正面对决的成语避免与强敌正面对决的成语避实就虚 【近义】避重就轻、避难就易、声东击西【反义...
多愁善感类的成语 多愁善感类的成语心细如发【解释】:极言小心谨慎,考虑周密。亦作“心细于发”。【出自】:吴梅《题天香石...