ShardingJdbc实战-分库分表

2024-03-02 20:52

本文主要是介绍ShardingJdbc实战-分库分表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 基本配置
  • 分库分表的分片策略
    • 一、inline 行表达时分片策略
      • algorithm-expression行表达式
      • 完整案例和配置如下
    • 二、根据实时间日期 - 按照标准规则分库分表
      • 标准分片 - Standard
      • 完整案例和配置如下


基本配置

逻辑表

逻辑表是指:水平拆分的数据库或者数据表的相同路基和数据结构表的总称。比如用户数据根据用户id%2拆分为2个表,分别是:ksd_user0和ksd_user1。他们的逻辑表名是:ksd_user。
在shardingjdbc中的定义方式如下:

spring:shardingsphere:sharding:tables:# ksd_user 逻辑表名ksd_user:

分库分表数据节点 - actual-data-nodes

 tables:# ksd_user 逻辑表名ksd_user:# 数据节点:多数据源$->{0..N}.逻辑表名$->{0..N} 相同表actual-data-nodes: ds$->{0..2}.ksd_user$->{0..2}# 也可以这么写,不同数据源不同表actual-data-nodes: ds0.ksd_user$->{0..2},ds1.ksd_user$->{2..4}# 指定单数据源的配置方式-同一个数据源,不同表actual-data-nodes: ds0.ksd_user$->{0..4}# 全部手动指定actual-data-nodes: ds0.ksd_user0,ds1.ksd_user0,ds0.ksd_user1,ds1.ksd_user1,

寻找规则如下
在这里插入图片描述

分库分表的分片策略

在这里插入图片描述
分片策略由分片键和分片算法组成

一、inline 行表达时分片策略

对应InlineShardingStragey。使用Groovy的表达时,提供对SQL语句种的=和in的分片操作支持,只支持单分片键。对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的Java代码开放,如:ksd_user${分片键(数据表字段)userid % 5} 表示ksd_user表根据某字段(userid)模 5.从而分为5张表,表名称为:ksd_user0到ksd_user4 。数据库也是如此。

    # 配置默认数据源ds1sharding:# 默认数据源,主要用于写,注意一定要配置读写分离 ,注意:如果不配置,那么就会把三个节点都当做从slave节点,新增,修改和删除会出错。default-data-source-name: ds0# 配置分表的规则tables:# ksd_user 逻辑表名ksd_user:key-generator:# 主键的列明,雪花算法,也可以是UUIDcolumn: idtype: SNOWFLAKE# 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}actual-data-nodes: ds$->{0..2}.ksd_user$->{0..2}# 拆分库策略,也就是什么样子的数据放入放到哪个数据库中。database-strategy:inline:sharding-column: sex    # 分片字段(分片键)algorithm-expression: ds$->{sex % 3} # 分片算法表达式# 拆分表策略,也就是什么样子的数据放入放到哪个数据表中。table-strategy:inline:sharding-column: age    # 分片字段(分片键)algorithm-expression: ksd_user$->{age % 3} # 分片算法表达式

grove表达式说明:

  • ${begin…end} 表示区间范围
  • ${[unit1,unit2,….,unitn]} 表示枚举值
  • 行表达式种如果出现连续多个 e x p r e s s s i o n 或 {expresssion}或 expresssion->{expression}表达式,整个表达时最终的结果将会根据每个子表达式的结果进行笛卡尔组合

algorithm-expression行表达式

在这里插入图片描述

完整案例和配置如下

  • 准备三台服务器(测试用也可以用docker 安装三个服务),三个数据库ksd_sharding-db,名字相同,两个数据源ds0,ds1,ds2
  • 每个数据库下方新建ksd_user0、ksd_user1、ksd_user1即可
  • 数据库规则,result = (sex%3),result=0的放入ds2库,result=1的放入ds1库,result=2的放入ds2库
  • 数据表规则:result = (age%3),根据取模结果分别放入ksd_user0、ksd_user1、ksd_user1表
  • 如果数据库配置了主从复制,需要将主从复制取消掉
mysql> stop slave;
server:port: 8085
spring:main:allow-bean-definition-overriding: trueshardingsphere:# 参数配置,显示sqlprops:sql:show: true# 配置数据源datasource:# 给每个数据源取别名,下面的ds1,ds2,ds3任意取名字names: ds0,ds1,ds2# 给master-ds1每个数据源配置数据库连接信息ds0:# 配置druid数据源type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://master:port/ksd-sharding-db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456maxPoolSize: 100minPoolSize: 5# 配置ds2-slaveds1:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://slave1:port/ksd-sharding-db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456maxPoolSize: 10minPoolSize: 5# 配置ds3-slaveds2:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://slave2:port/ksd-sharding-db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456maxPoolSize: 10minPoolSize: 5# 配置默认数据源ds1sharding:# 默认数据源,主要用于写,注意一定要配置读写分离 ,注意:如果不配置,那么就会把三个节点都当做从slave节点,新增,修改和删除会出错。default-data-source-name: ds0# 配置分表的规则tables:# ksd_user 逻辑表名ksd_user:key-generator:# 主键的列明,雪花算法,也可以是UUIDcolumn: idtype: SNOWFLAKE# 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}actual-data-nodes: ds$->{0..2}.ksd_user$->{0..2}# 拆分库策略,也就是什么样子的数据放入放到哪个数据库中。database-strategy:inline:sharding-column: sex    # 分片字段(分片键)algorithm-expression: ds$->{sex % 3} # 分片算法表达式# 拆分表策略,也就是什么样子的数据放入放到哪个数据表中。table-strategy:inline:sharding-column: age    # 分片字段(分片键)algorithm-expression: ksd_user$->{age % 3} # 分片算法表达式
# 整合mybatis的配置XXXXX
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.shardingjdbc.sharding.entity
@GetMapping("/save")public String insert() {User user = new User();user.setNickname("test" + new Random().nextInt());user.setBirthday(new Date());// 3%3=0,所以这条数据应该在ds0这台服务上user.setSex(3);// 25%3=1  所以这个条数据应该在ksd_user1这个表里面user.setAge(25);user.setPassword("123456");userMapper.addUser(user);return "success";}

在这里插入图片描述

二、根据实时间日期 - 按照标准规则分库分表

标准分片 - Standard

  • 对应StrandardShardingStrategy.提供对SQL语句中的=,in和恶between and 的分片操作支持
  • StrandardShardingStrategy只支持分片键。提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法
  • PreciseShardingAlgorithm是必选的,用于处理=和IN的分片
  • RangeShardingAlgorithm是可选的,是用于处理Betwwen and分片,如果不配置和RangeShardingAlgorithm,SQL的Between AND 将按照全库路由处理

完整案例和配置如下

yml配置

server:port: 8085
spring:main:allow-bean-definition-overriding: trueshardingsphere:# 参数配置,显示sqlprops:sql:show: true# 配置数据源datasource:# 给每个数据源取别名,下面的ds1,ds2,ds3任意取名字names: ds0,ds1,ds2# 给master-ds1每个数据源配置数据库连接信息ds0:# 配置druid数据源type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://master:port/ksd-sharding-db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456maxPoolSize: 100minPoolSize: 5# 配置ds2-slaveds1:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://slave1:port/ksd-sharding-db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456maxPoolSize: 10minPoolSize: 5# 配置ds3-slaveds2:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://slave2:port/ksd-sharding-db?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMTusername: rootpassword: 123456maxPoolSize: 10minPoolSize: 5# 配置默认数据源ds1sharding:# 默认数据源,主要用于写,注意一定要配置读写分离 ,注意:如果不配置,那么就会把三个节点都当做从slave节点,新增,修改和删除会出错。default-data-source-name: ds0# 配置分表的规则tables:# ksd_user 逻辑表名ksd_user:key-generator:# 主键的列明,雪花算法,也可以是UUIDcolumn: idtype: SNOWFLAKE# 数据节点:数据源$->{0..N}.逻辑表名$->{0..N}actual-data-nodes: ds$->{0..2}.ksd_user$->{0..2}# 拆分库策略,也就是什么样子的数据放入放到哪个数据库中。database-strategy:standard:sharding-column: birthday    # 分片字段(分片键)preciseAlgorithmClassName: com.example.shardingjdbc.sharding.algorithm.BirthdayAlgorithm# 拆分表策略,也就是什么样子的数据放入放到哪个数据表中。table-strategy:inline:sharding-column: age    # 分片字段(分片键)algorithm-expression: ksd_user$->{age % 3} # 分片算法表达式
# 整合mybatis的配置XXXXX
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.shardingjdbc.sharding.entity

自定义日期规则


/*** @description: BirthdayAlgorithm*/
public class BirthdayAlgorithm implements PreciseShardingAlgorithm<Date> {List<Date> dateList = new ArrayList<>();{Calendar calendar1 = Calendar.getInstance();calendar1.set(2020, 1, 1, 0, 0, 0);Calendar calendar2 = Calendar.getInstance();calendar2.set(2021, 1, 1, 0, 0, 0);Calendar calendar3 = Calendar.getInstance();calendar3.set(2022, 1, 1, 0, 0, 0);dateList.add(calendar1.getTime());dateList.add(calendar2.getTime());dateList.add(calendar3.getTime());}@Overridepublic String doSharding(Collection<String> collection, PreciseShardingValue<Date> preciseShardingValue) {// 获取属性 数据库中的值Date date = preciseShardingValue.getValue();// 获取数据源名称列表Iterator<String> iterator = collection.iterator();String target = null;for (Date item: dateList) {target = iterator.next();if (date.before(item)) {break;}}return target;}
}

测试结果

  • http://localhost:8085/user/save?sex=3&age=3&birthday=2020-03-09 —- ds1
    在这里插入图片描述
  • http://localhost:8085/user/save?sex=3&age=3&birthday=2021-03-09 —- ds2

在这里插入图片描述


这篇关于ShardingJdbc实战-分库分表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/767401

相关文章

Golang操作DuckDB实战案例分享

《Golang操作DuckDB实战案例分享》DuckDB是一个嵌入式SQL数据库引擎,它与众所周知的SQLite非常相似,但它是为olap风格的工作负载设计的,DuckDB支持各种数据类型和SQL特性... 目录DuckDB的主要优点环境准备初始化表和数据查询单行或多行错误处理和事务完整代码最后总结Duck

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

Golang使用minio替代文件系统的实战教程

《Golang使用minio替代文件系统的实战教程》本文讨论项目开发中直接文件系统的限制或不足,接着介绍Minio对象存储的优势,同时给出Golang的实际示例代码,包括初始化客户端、读取minio对... 目录文件系统 vs Minio文件系统不足:对象存储:miniogolang连接Minio配置Min

Mycat搭建分库分表方式

《Mycat搭建分库分表方式》文章介绍了如何使用分库分表架构来解决单表数据量过大带来的性能和存储容量限制的问题,通过在一对主从复制节点上配置数据源,并使用分片算法将数据分配到不同的数据库表中,可以有效... 目录分库分表解决的问题分库分表架构添加数据验证结果 总结分库分表解决的问题单表数据量过大带来的性能

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10

springboot实战学习(1)(开发模式与环境)

目录 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 (3)前端 二、开发模式 一、实战学习的引言 (1)前后端的大致学习模块 (2)后端 Validation:做参数校验Mybatis:做数据库的操作Redis:做缓存Junit:单元测试项目部署:springboot项目部署相关的知识 (3)前端 Vite:Vue项目的脚手架Router:路由Pina:状态管理Eleme