分库分表如何管理不同实例中几万张分片表?

大家好,我是小富~

ShardingSphere实现分库分表,如何管理分布在不同数据库实例中的成千上万张分片表?

上边的问题是之前有个小伙伴看了我的分库分表的文章,私下咨询我的,看到他的提问我第一感觉就是这老铁没用过ShardingSphere,因为这个问题在ShardingSphere中已经有了很好的解决方案,接下来看看怎么实现。

本文案例代码GitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/shardingsphere101/shardingsphere-autocreate-table

系列往期

往期系列文章(我佛系更新,无下限拖更):

(一)好好的系统,为什么要分库分表?

(二)分库分表的 21 条法则,hold 住!

(三)2 种方式快速实现分库分表,轻松拿捏!

ShardingSphere学习路线

本文是《ShardingSphere5.x分库分表原理与实战》系列的第四篇文章,在进行分库分表设计时,确认好了数据节点数量和分片策略以后,接下来要做的就是管理大量的分片表。实际实施过程中可能存在上百个分片数据库实例,每个实例中都可能有成千上万个分片表,如果仅依靠人力来完成这些任务显然是不现实的。所以,想要快速且自动化管理这些分片表,使用工具是十分必要滴。

前言

ShardingSphere框架成员中的Shardingsphere-jdbcShardingsphere-proxy都提供了自动化管理分片表的功能auto-tables,可以统一维护大量的分片表,避免了手动编写脚本和维护分片表的繁琐工作,极大程度减少分库分表的开发和维护成本,提升效率和可靠性。

这里咱们先使用Shardingsphere-jdbc来实际操作一下,Shardingsphere-proxy方式后续会有单独的文章详细讲解,就不在这里展开了。

准备工作

假设我们要对t_order表进行分库分表,首先我们要做的就是确定好分片方案,这里使用两个数据库实例db0db1,每个实例中t_order表分成1000张分片表t_order_1 ~ t_order_1000order_id字段作为分片键,分片算法使用取模算法order_id % n,分布式主键生成策略采用snowflake

t_order逻辑表的表结构如下:

CREATE TABLE `t_order` (`order_id` BIGINT ( 20 ) NOT NULL COMMENT "订单表分布式主健ID",`order_number` VARCHAR ( 255 ) NOT NULL COMMENT "订单号",`customer_id` BIGINT ( 20 ) NOT NULL COMMENT "用户ID",`order_date` date NOT NULL COMMENT "下单时间",`total_amount` DECIMAL ( 10, 2 ) NOT NULL COMMENT "订单金额",PRIMARY KEY ( `order_id` ) USING BTREE 
);

有了这些基础信息,可以先来进行t_order表的分片配置了,不考虑其他因素,这里先Run起来!

分片规则配置

设定好分片规则,接着编写逻辑表t_order的分片规则的配置,我分别使用yml配置Java编码两种方式做了实现。要注意的是两种方式不要并存,不然启动会报错

yml配置方式

使用yml配置相对简单易用比较直观,适合对分库分表要求不太复杂的场景,完整配置如下:

spring:shardingsphere:datasource:# 数据源名称,多数据源以逗号分隔 ,放在第一个的数据源为未配置分片规则表的默认数据源names: db0 , db1# 名称与上边 names 保持一致db0:....db1:....# 具体规则配置rules:sharding:# 分片算法定义sharding-algorithms:# 自定义分片算法名称t_order_database_algorithms:# 分片算法类型type: INLINE# 自定义参数props:algorithm-expression: db$->{order_id % 2}t_order_table_algorithms:type: INLINEprops:algorithm-expression: t_order_$->{order_id % 1000}t_order_mod:type: MODprops:# 指定分片数量sharding-count: 1000# 分布式序列算法配置key-generators:t_order_snowflake:type: SNOWFLAKE# 分布式序列算法属性配置props:worker-id: 1tables:# 逻辑表名称t_order:# 数据节点:数据库.分片表actual-data-nodes: db$->{0..1}.t_order_$->{1..1000}# 分库策略database-strategy:standard:# 分片列名称sharding-column: order_id# 分片算法名称sharding-algorithm-name: t_order_database_algorithms# 分表策略table-strategy:standard:# 分片列名称sharding-column: order_id# 分片算法名称sharding-algorithm-name: t_order_table_algorithms# 主键生成策略keyGenerateStrategy:column: order_idkeyGeneratorName: t_order_snowflake# 属性配置props:# 展示修改以后的sql语句sql-show: true

Java编码方式

使用Java编码方式更加灵活和可扩展,可以根据业务定制分片规则,适合对分库分表有特殊需求或需要动态调整的场景。

/*** 公众号:程序员小富*/
@Configuration
public class ShardingConfiguration {/*** 配置分片数据源* 公众号:程序员小富*/@Beanpublic DataSource getShardingDataSource() throws SQLException {Map<String, DataSource> dataSourceMap = new HashMap<>();dataSourceMap.put("db0", dataSource0());dataSourceMap.put("db1", dataSource1());// 分片rules规则配置ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();// 分片算法shardingRuleConfig.setShardingAlgorithms(getShardingAlgorithms());// 配置 t_order 表分片规则ShardingTableRuleConfiguration orderTableRuleConfig = new ShardingTableRuleConfiguration("t_order", "db${0..1}.t_order_${1..1000}");orderTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "t_order_table_algorithms"));orderTableRuleConfig.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "t_order_database_algorithms"));shardingRuleConfig.getTables().add(orderTableRuleConfig);// 是否在控制台输出解析改造后真实执行的 SQLProperties properties = new Properties();properties.setProperty("sql-show", "true");// 创建 ShardingSphere 数据源return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), properties);}/*** 配置数据源1* 公众号:程序员小富*/public DataSource dataSource0() {HikariDataSource dataSource = new HikariDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/db0?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;}/*** 配置数据源2* 公众号:程序员小富*/public DataSource dataSource1() {HikariDataSource dataSource = new HikariDataSource();dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;}/*** 配置分片算法* 公众号:程序员小富*/private Map<String, AlgorithmConfiguration> getShardingAlgorithms() {Map<String, AlgorithmConfiguration> shardingAlgorithms = new LinkedHashMap<>();// 自定义分库算法Properties databaseAlgorithms = new Properties();databaseAlgorithms.setProperty("algorithm-expression", "db$->{order_id % 2}");shardingAlgorithms.put("t_order_database_algorithms", new AlgorithmConfiguration("INLINE", databaseAlgorithms));// 自定义分表算法Properties tableAlgorithms = new Properties();tableAlgorithms.setProperty("algorithm-expression", "db$->{order_id % 1000}");shardingAlgorithms.put("t_order_table_algorithms", new AlgorithmConfiguration("INLINE", tableAlgorithms));return shardingAlgorithms;}
}

上面我们在应用中编写好了分片规则,现在就差在数据库实例中创建分片表了,手动创建和管理1000张分片表确实是一个又脏又累的活,反正我是不会干的!

管理分片表

其实,ShardingSphere内已经为我们提供了管理分片表的能力。

当一张逻辑表t_order被配置了分片规则,那么接下来对逻辑表的各种DDL操作(例如创建表修改表结构等),命令和数据会根据分片规则,执行和存储到每个分片数据库和分片库中的相应分片表中,以此保持整个分片环境的一致性。

不过,使用Shardingsphere-jdbc管理分片表的过程中,是需要我们手动编写对逻辑表的DDL操作的代码。我们来跑几个单元测试用例来观察实际的执行效果,直接使用jdbcTemplate执行创建逻辑表t_order的SQL。

/*** @author 公众号:程序员小富* 自动创建分片表* @date 2023/12/31 17:25*/
@SpringBootTest
class AutoCreateTablesTests {@Resourceprivate JdbcTemplate jdbcTemplate;/*** 执行创建逻辑表的SQL,会根据AutoTables的配置自动在对应的数据源内创建分片表* @author 公众号:程序员小富*/@Testpublic void autoCreateOrderTableTest() {jdbcTemplate.execute("CREATE TABLE `t_order` (\n" +"  `order_id` bigint(20) NOT NULL,\n" +"  `order_number` varchar(255) NOT NULL,\n" +"  `customer_id` bigint(20) NOT NULL,\n" +"  `order_date` date NOT NULL,\n" +"  `total_amount` decimal(10,2) NOT NULL,\n" +"  PRIMARY KEY (`order_id`) USING BTREE\n" +");");}
}

根据之前配置的分片规则,将会在两个数据库实例 db0db1 中,分别生成1000张命名为t_order_1t_order_1000的分片表,看到两个数据库均成功创建了1000张分片表。

在次执行更新t_order表SQL,将字段order_number长度从 varchar(255)扩展到 varchar(500),执行SQL看下效果。

/*** @author 公众号:程序员小富* 自动创建分片表* @date 2023/12/31 17:25*/
@SpringBootTest
class AutoCreateTablesTests {@Resourceprivate JdbcTemplate jdbcTemplate;@Testpublic void autoModifyOrderTableTest() {jdbcTemplate.execute("ALTER TABLE t_order MODIFY COLUMN order_number varchar(500);");}
}

通过查看两个分片库,我们成功地将所有分片表的order_number字段长度更改为了varchar(500),在控制台日志中,可以看到它是通过在每个分片库内依次执行了1000次命令实现的。

Shardingsphere-jdbc实现分库分表时,可以采用这种默认的方式来管理分片表。但要注意的是,由于涉及到不同的数据库实例,如果不使用第三方的分布式事务管理工具(例如Seata等),执行过程是无法保证事务一致性的。

自定义管理分片表

上边为逻辑表配置分片规则,应用程序内执行对逻辑表的DDL操作,就可以很轻松的管理分片表。

自定义

不过,默认的分片管理还是有局限性的,我们在设计分片规则时往往会根据不同的业务维度来划分,例如按天、月、按季度生成分片表并分布到不同数据源中等。这样就需要一些自定义的规则来实现。

ShardingSphere 5.X版本后推出了一种新的管理分片配置方式:AutoTable。设置了AutoTable的逻辑表,将交由ShardingSphere自动管理分片,用户只需要指定分片数量和使用的数据库实例,无需再关心表的具体分布,配置格式如下:

spring:shardingsphere:# 数据源配置datasource:......# 具体规则配置rules:sharding:# 逻辑表分片规则tables:# 逻辑表名称t_order:.....# 自动分片表规则配置auto-tables:t_order: # 逻辑表名称actual-data-sources: db$->{0..1}sharding-strategy: # 切分策略standard: # 用于单分片键的标准分片场景sharding-column: order_id # 分片列名称sharding-algorithm-name: t_order_mod # 自动分片算法名称

ShardingSphere-Jdbc中配置使用auto-tables主要两个参数,actual-data-sources指定数据源分布,由于是管理分片表所以只需数据源信息即可;sharding-strategy指具体采用何种算法来进行分片。

对逻辑表的DDL操作,系统会首先检查是否配置了AutoTable,如果已配置,则优先采用配置的规则;若未配置,则将使用默认的逻辑表分片规则。

AutoTable支持ShardingSphere内置的全部自动分片算法,所谓自动分片算法就是根据actualDataSources设置的数据源信息,使用对应内置算法自行解析处理。

  • MOD:取模分片算法
  • HASH_MOD:哈希取模分片算法
  • VOLUME_RANGE:基于分片容量的范围分片算法
  • BOUNDARY_RANGE:基于分片边界的范围分片算法
  • AUTO_INTERVAL:自动时间段分片算法

AutoTable使用

举个例子,我们使用内置MOD取模算法作为AutoTable的分片算法,同样是db0db1两个实例中各创建1000张分片表。那么当对逻辑表的DDL操作时,ShardingSphere会依据分片表编号t_order_0~t_order_1999 % 数据库实例数取模来确认DDL命令路由到哪个实例中执行。


spring:shardingsphere:# 数据源配置datasource:.....# 具体规则配置rules:sharding:# 自动分片表规则配置auto-tables:t_order:actual-data-sources: db$->{0..1}sharding-strategy:standard:sharding-column: order_datesharding-algorithm-name: t_order_mod# 分片算法定义sharding-algorithms:t_order_mod:type: MODprops:# 指定分片数量sharding-count: 2000

还是执行刚才创建表的单元测试,会发现db0db1两个实例中已经各自创建了1000张分片表,但你会发现1000张表已经不再是按照顺序创建的了。

上边使用的是内置自动分片算法,它对于我们来说是黑盒,提供它方便我们拿来即用。不过,如果想要做到更细粒度的管理分片表,最好的办法就是自定义分片算法,后续章节会介绍所有内置分片算法和自定义分片算法的使用

总结

在使用ShardingSphere实现分库分表的时候,要摒弃先建表、再配规则的传统思维,要先确定规则在建表,管理表是一件很简单的事,我们只要告诉ShardingSphere分片数量和分布规则,剩下的就让框架来处理就好了。

本文案例代码GitHub地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/shardingsphere101/shardingsphere-autocreate-table

我是小富~ 下期见

参考文献

  • https://shardingsphere.apache.org/
  • https://www.bookstack.cn/read/shardingsphere-5.3.2-zh/ddd3efa082ed1ffc.md
  • https://shardingsphere.apache.org/blog/cn/material/oct_12_6_autotable_your_butler-like_sharding_configuration_tool/
  • https://community.sphere-ex.com/
  • https://blog.csdn.net/qq_36641443/article/details/127343113

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/703376.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《高质量的C/C++编程规范》学习

目录 一、编程规范基础知识 1、头文件 2、程序的板式风格 3、命名规则 二、表达式和基本语句 1、运算符的优先级 2、复合表达式 3、if语句 4、循环语句的效率 5、for循环语句 6、switch语句 三、常量 1、#define和const比较 2、常量定义规则 四、函数设计 1、参…

【k8s资源调度-Deployment】

1、标签和选择器 1.1 标签Label 配置文件&#xff1a;在各类资源的sepc.metadata.label 中进行配置通过kubectl 命令行创建修改标签&#xff0c;语法如下 创建临时label&#xff1a;kubectl label po <资源名称> apphello -n <命令空间&#xff08;可不加&#xff0…

2024生物科学、医学技术与化学国际会议(ICBSMTC2024)

2024生物科学、医学技术与化学国际会议(ICBSMTC2024) 会议简介 ICBSMTC2024是一个聚焦于生物科学、医学技术与化学领域的学术交流活动&#xff0c;会议将在中国桂林举行&#xff0c;会议旨在促进相关领域的学术交流与发展。会议将汇集来自世界各地的顶级学者和专家&#xf…

人工智能_CPU微调ChatGLM大模型_使用P-Tuning v2进行大模型微调_007_微调_002---人工智能工作笔记0102

这里我们先试着训练一下,我们用官方提供的训练数据进行训练. 也没有说使用CPU可以进行微调,但是我们先执行一下试试: https://www.heywhale.com/mw/project/6436d82948f7da1fee2be59e 可以看到说INT4量化级别最低需要7GB显存可以启动微调,但是 并没有说CPU可以进行微调.我们…

【b站咸虾米】chapter5_uniapp-API_新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握

课程地址&#xff1a;【新课uniapp零基础入门到项目打包&#xff08;微信小程序/H5/vue/安卓apk&#xff09;全掌握】 https://www.bilibili.com/video/BV1mT411K7nW/?p12&share_sourcecopy_web&vd_sourceb1cb921b73fe3808550eaf2224d1c155 目录 5 API 5.1 页面和路…

Linux 文件操作

目录 C语言下的文件操作 Linux下的文件操作 文件描述符的前因后果 文件描述符的概念 文件描述符的分配规则 理解C语言的FILE结构体 Linux重定向 文件缓冲区 文件系统 文件系统的概念 ext2文件系统 对ext2的补充 虚拟文件系统的概念 软硬链接 C语言下的文件操作 …

备战蓝桥杯---基础算法刷题2

题目有一点水&#xff0c;不过还是有几个好题的&#xff0c;我在这分享一下&#xff1a; 很容易想到先往最高处跳再往最低处跳&#xff0c;依次类推&#xff0c;那怎么保证其正确性呢&#xff1f; 证法1. 在此&#xff0c;我们从0开始&#xff0c;假设可以跳到a,b,c(a<b<…

UE学习笔记-- bUseUnity 加速编译 及 踩坑记录

前言 在写 UE 项目时&#xff0c;使用 VS 2022 进行编译&#xff0c;发现编译不过。 原因是少了头文件&#xff0c;导致某些了类型缺失。 问题发现 但是很奇怪的是&#xff0c;以前编译没问题&#xff0c;在原本应该出问题的 cpp 文件里面加了一行注释之后&#xff0c;编译就…

嵌入式学习day25 Linux

进程基本概念: 1.进程: 程序&#xff1a;存放在外存中的一段数据组成的文件 进程&#xff1a;是一个程序动态执行的过程,包括进程的创建、进程的调度、进程的消亡 2.进程相关命令: 1.top 动态查看当前系统中的所有进程信息&#xff08;根据CPU占用率排序&a…

查看仓库版本记录

打开命令行窗口 输入git log即可。 若发现分支不对&#xff0c;方法如下 查看项目目录&#xff0c;命令行输入dir可以查看 多个moudel&#xff0c;进入到需要查版本记录的moudel下 命令行输入cd .\文件名如wowo-win-server\ 切换到wowo-win-server文件夹下后&#xff0c;再输入…

C语言内存管理-C进程内存布局

C进程内存布局 任何一个程序&#xff0c;正常运行都需要内存资源&#xff0c;用来存放诸如变量、常量、函数代码等等。这些不同的内容&#xff0c;所存储的内存区域是不同的&#xff0c;且不同的区域有不同的特性。因此我们需要研究C语言进程的内存布局&#xff0c;逐个了解不…

sonar-java 手写一个规则-单元测试分析

前言 最近做项目&#xff0c;定制sonar规则&#xff0c;提高Java代码质量&#xff0c;在编写的sonar规则&#xff0c;做验证时&#xff0c;使用单元测试有一些简单的心得感悟&#xff0c;分享出来。 自定义规则模式 sonar的自定义规则很简单&#xff0c;一般而言有2种模式可…

MySQL多实例与Mycat分布式读写分离的架构实践

文章目录 1.Mycat读写分离分布式架构规划2.在两台服务器中搭建八个MySQL实例2.1.安装MySQL软件2.2.创建每个MySQL实例的数据目录并初始化2.3.准备每个实例的配置文件2.4.准备每个实例的启动脚本2.6启动每台机器的MySQL多实例2.7.为每个MySQL实例设置密码2.8.查看每个MySQL实例的…

使用GPT生成python图表

首先&#xff0c;生成一脚本&#xff0c;读取到所需的excel表格 import xlrddata xlrd.open_workbook(xxxx.xls) # 打开xls文件 table data.sheet_by_index(0) # 通过索引获取表格# 初始化奖项字典 awards_dict {"一等奖": 0,"二等奖": 0,"三等…

three中界面交互gui.js库的使用

gui.js库(可视化改变三维场景) dat.gui.js说白了就是一个前端js库&#xff0c;对HTML、CSS和JavaScript进行了封装&#xff0c;学习开发的时候&#xff0c;借助dat.gui.js可以快速创建控制三维场景的UI交互界面&#xff0c;你打开课件中案例源码体验一下就能感受到。 学习dat…

一元函数微分学——刷题(22

目录 1.题目&#xff1a;2.解题思路和步骤&#xff1a;3.总结&#xff1a;小结&#xff1a; 1.题目&#xff1a; 2.解题思路和步骤&#xff1a; 由于是极坐标方程&#xff0c;所以这个式子一定成立&#xff1a; 然后代入r即可变为参数方程的求导&#xff1a; 3.总结&#xff…

【Linux运维系列】vim操作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

linux系统消息中间件rabbitmq普通集群的部署

rabbitmq普通集群的部署 普通集群准备环境查询版本对应安装rabbitmq软件启动创建登录用户开启用户远程登录查看端口 部署集群创建数据存放目录和日志存放目录:拷⻉erlang.cookie将其他两台服务器作为节点加⼊节点集群中查看集群状态创建新的队列 普通集群准备环境 配置hosts⽂件…

Matlab自学笔记二十七:详解格式化文本sprintf各参数设置方法

1.一个程序引例 上篇文章已经介绍了格式化文本的初步应用&#xff0c;程序示例如下&#xff1a; sprintf(|%f\n|%.2f\n|%8.2f,pi*ones(1,3)) 2.格式化操作符各字段的含义解析 格式化操作符可以有六个字段&#xff0c;只有主字符%和转换格式是必需的&#xff0c;其他都是可选…

数据库安全性与完整性设计

文章标签集合[数据库安全,数据敏感,通信安全,MD5,盐加密] 1 系统设计 1.1设计目标 &#xff08;1&#xff09;确定系统中需要保护的敏感数据和通信内容&#xff1b; &#xff08;2&#xff09;设计合适的签名、加密和解密算法&#xff1b; &#xff08;3&#xff09;实现…