ShardingSphere-JDBC学习笔记

引言

开源产品的小故事

Sharding-JDBC是2015年开源的,早期的定位就是一个分布式数据库的中间件,而在它之前有一个MyCat的产品。MyCat也是从阿里开源出来的,作为分库分表的代名词火了很长一段时间,而MyCat早年的目标就是想进入apache(从命名也可以看出,希望像Tomcat一样),但是很可惜最后由于社区运营不是很成熟没有达成。但是现在它的这个愿望早就已经被ShardingSphere达成了,ShardingSphere现在就是apache的顶级开源项目。

ShardingSphere版本演进

从15年开始作为一个小的中间件,发展至今已成为了一个庞然大物。

当不使用分片键时,ShardingSphere是怎么执行的呢?

在之前4.x版本下,这种情况会拆分成多个SQL(每个真实表分片对应一个sql),查询多次。新版本下,会将每一个真实库里的语句通过UNION合并成一个大SQL,一起进行查询。

如果需要对一个真实库进行多个SQL查询,那么就需要通过多线程进行并发查询,这种情况下,如果要进行后续的结果归并,比如sum、max这样的结果归并,那就只能将所有的结果都合并到一个大内存,再进行归并。这种方式称为内存归并消耗内存,多线程

如果合并成了一个大的SQL,对一个真实库只要进行一次SQL查询,这样就可以通过一个线程进行查询。在进行结果归并时,就可以拿一条数据归并一次。这种方式称为流式归并极大的节约内存

另外,在使用in进行查询时,有可能计算出属于多个不同的分片。在4.x版本当中,如果出现了这种情况,由于ShardingSphere无法确定in算出来的分片有多少个,所以遇到这种情况,他就不再去计算in中所有的分片结果了,直接改为全路由分片。这样计算比较简单,但是查询的效率肯定不好。而在新版本下,能够准确的计算出分片

补充:ShardingSphere实现分库分表的核心概念

  1. 虚拟库: ShardingSphere的核心就是提供一个具备分库分表功能的虚拟库,他是一个ShardingSphereDatasource实例。应用程序只需要像操作单数据源一样访问这个ShardingSphereDatasource即可。

  2. 真实库: 实际保存数据的数据库。这些数据库都被包含在ShardingSphereDatasource实例当中,由ShardingSphere决定未来需要使用哪个真实库。

  3. 逻辑表: 应用程序直接操作的逻辑表。

  4. 真实表: 实际保存数据的表。这些真实表与逻辑表表名不需要一致,但是需要有相同的表结构,可以分布在不同的真实库中。应用可以维护一个逻辑表与真实表的对应关系,所有的真实表默认也会映射成为ShardingSphere的虚拟表。

  5. 分布式主键生成算法: 给逻辑表生成唯一主键。由于逻辑表的数据是分布在多个真实表当中的,所以单表的索引就无法保证逻辑表的ID唯一性。ShardingSphere集成了几种常见的基于单机生成的分布式主键生成器。比如SNOWFLAKE,COSID_SNOWFLAKE雪花算法可以生成单调递增的long类型的数字主键,还有UUID,NANOID可以生成字符串类型的主键。当然,ShardingSphere也支持应用自行扩展主键生成算法。比如基于Redis,Zookeeper等第三方服务,自行生成主键。

  6. 分片策略: 表示逻辑表要如何分配到真实库和真实表当中,分为分库策略和分表策略两个部分。分片策略由分片键和分片算法组成。分片键是进行数据水平拆分的关键字段。如果没有分片键,ShardingSphere将只能进行全路由,SQL执行的性能会非常差。分片算法则表示根据分片键如何寻找对应的真实库和真实表。简单的分片策略可以使用Groovy表达式直接配置,当然,ShardingSphere也支持自行扩展更为复杂的分片算法。

ShardingSphere-JDBC其他策略

广播表

广播表认为在所有的片里面是一致的,不会进行转发,即使配置了分片规则也不会生效

使用场景:在所有分片都需要的表,比如字典表,在所有库上数据保持一致

参考配置:

# 打印SQL,spring.shardingsphere.props.sql-show,不同版本的参数可能不同,中间是-
spring.shardingsphere.props.sql.show=true
spring.main.allow-bean-definition-overriding=true
spring.shardingsphere.datasource.names=m0,m1

spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=UTC
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123666

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb2?serverTimezone=UTC
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123666

spring.shardingsphere.sharding.tables.dict.key-generator.column=dictId
spring.shardingsphere.sharding.tables.dict.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.dict.key-generator.props.worker.id=1
spring.shardingsphere.sharding.tables.dict.actual-data-nodes=m$->{0..1}.dict_$->{1..2}

spring.shardingsphere.sharding.broadcast-tables=dict

测试代码:

@Test
public void dict()
{
    Dict dict = new Dict();
    dict.setDictkey("1");
    dict.setDictval("true");
    dictMapper.insert(dict);

    Dict dict2 = new Dict();
    dict2.setDictkey("2");
    dict2.setDictval("false");
    dictMapper.insert(dict2);
}

@TableName("dict")
public class Dict {
    private Long dictid;
    private String dictkey;
    private String dictval;

    @Override
    public String toString() {
        return "Dict{" +
                "dictId=" + dictid +
                ", dictkey='" + dictkey + '\'' +
                ", dictval='" + dictval + '\'' +
                '}';
    }

    public Long getDictid() {
        return dictid;
    }

    public void setDictid(Long dictid) {
        this.dictid = dictid;
    }

    public String getDictkey() {
        return dictkey;
    }

    public void setDictkey(String dictkey) {
        this.dictkey = dictkey;
    }

    public String getDictval() {
        return dictval;
    }

    public void setDictval(String dictval) {
        this.dictval = dictval;
    }
}

测试结果:两个库的Dict表都增加了两条数据

注意:这里插入的是dict表,而不是dict_1和dict_2

绑定表

参考配置:

spring.shardingsphere.props.sql.show=true

spring.shardingsphere.datasource.names=m0,m1

spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=UTC
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123666

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb2?serverTimezone=UTC
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123666

#以下是新增部分
spring.shardingsphere.sharding.tables.user.key-generator.column=userid
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.user.key-generator.props.worker.id=1

spring.shardingsphere.sharding.tables.user.actual-data-nodes=m$->{0..1}.user_$->{1..2}
spring.shardingsphere.sharding.tables.user_course_info.actual-data-nodes=m$->{0..1}.user_course_info_$->{1..2}

spring.shardingsphere.sharding.tables.user.table-strategy.inline.sharding-column=userid
spring.shardingsphere.sharding.tables.user.table-strategy.inline.algorithm-expression=user_$->{Math.abs(userid.hashCode()%4).intdiv(2) +1}

spring.shardingsphere.sharding.tables.user_course_info.table-strategy.inline.sharding-column=userid
spring.shardingsphere.sharding.tables.user_course_info.table-strategy.inline.algorithm-expression=user_course_info_$->{Math.abs(userid.hashCode()%4).intdiv(2) +1}

spring.shardingsphere.sharding.binding-tables[0]=user,user_course_info

绑定表有什么作用呢?

举例生产场景:订单表和订单详情表,这两张表分片键的值是相同的,也就是说在相同分片规则的情况下,关联的数据一定会被分配到同一个分片中,所以直接到指定分片查询就可以了。绑定表在生产上非常常用,当分片数量很多时,比如64分片,试想不使用绑定表的情况下要如何查询(64*64的笛卡尔积,业务上肯定不能接受)

主从模式

早期版本叫主从模式,后续版本叫读写分离,主从做的事情其实就是读写分离。

主从参考配置:

spring.shardingsphere.props.sql.show=true

spring.shardingsphere.datasource.names=m0,m1

spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=UTC
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123666

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb2?serverTimezone=UTC
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123666

#以下是添加的部分,预期效果对dict表操作,更新到m0库,查询从m1
spring.shardingsphere.sharding.master-slave-rules.gao.master-data-source-name=m0
spring.shardingsphere.sharding.master-slave-rules.gao.slave-data-source-names[0]=m1

spring.shardingsphere.sharding.tables.dict.actual-data-nodes=gao.dict
spring.shardingsphere.sharding.tables.dict.key-generator.column=dictid
spring.shardingsphere.sharding.tables.dict.key-generator.type=snowflake
spring.shardingsphere.sharding.tables.dict.key-generator.props.worker.id=1

数据加密

对指定的字段类进行加密,加密后的密文字段存在数据表的指定列中。在应用代码使用时仍然操作明文列,但是观察日志可以看出转发到真实表的sql会处理成加密列去做操作,这样就达到了我们想要的效果。

好处是,不需要应用代码中额外的加密操作,内置支持多种加密方式AES、MD5、SM3、RC4等

参跑配置:

spring.shardingsphere.props.sql.show=true
spring.main.allow-bean-definition-overriding=true
spring.shardingsphere.datasource.names=m0,m1

spring.shardingsphere.datasource.m0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m0.url=jdbc:mysql://localhost:3306/coursedb?serverTimezone=UTC
spring.shardingsphere.datasource.m0.username=root
spring.shardingsphere.datasource.m0.password=123666

spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/coursedb2?serverTimezone=UTC
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=123666


spring.shardingsphere.sharding.tables.user.actual-data-nodes=m0.user_$->{1..2}
spring.shardingsphere.sharding.tables.user.key-generator.column=userid
spring.shardingsphere.sharding.tables.user.key-generator.type=SNOWFLAKE

spring.shardingsphere.sharding.encrypt-rule.encryptors.encryptor_aes.type=aes
spring.shardingsphere.sharding.encrypt-rule.encryptors.encryptor_aes.props.aes.key.value=123456
spring.shardingsphere.sharding.encrypt-rule.tables.user.columns.password.plainColumn=password
spring.shardingsphere.sharding.encrypt-rule.tables.user.columns.password.cipherColumn=password_cipher
#spring.shardingsphere.sharding.encrypt-rule.tables.user.columns.password.assistedQueryColumn=user_assisted
spring.shardingsphere.sharding.encrypt-rule.tables.user.columns.password.encryptor=encryptor_aes

影子库

主要是用在压测的场景,比如说你的业务开发完了,需要测试性能,这个时候最好的情况是压测环境和生产的环境是一样的,影子库就是和生产环境的库是一样的,但是数据不同。在操作生产环境的库时,ShardingSphere内部会转发到影子库去完成测试。但是要注意,既然是压测,对生产环境的性能肯定是有影响的

这里参考配置就不列举了,因为笔者也没测试过,感兴趣的参考官方文档测试效果

总结

学习时建议多关注各种策略的思想(结合虚拟库、真实表等核心概念理解记忆),而且学习ShardingSphere强烈推荐结合官方文档自己多多尝试。使用其实不难的,关键是要找对方法,网上文章千千万,版本也是千奇百怪,初学者看的配置越多可能越不理解,ShardingSphere每个大版本的配置项都有很多改进,所以笔者建议理解每种策略存在的意义,解决问题的思想才是更有价值的。

基本技能:至少要了解每种策略是干什么用的?适合哪些场景?如何参考官方文档配置落地?

高级功能:5.x版本提供的可插拔扩展点使用,比如分片算法策略扩展、路由策略扩展、转发到真实表前的扩展(加密脱敏等)、jdbc数据库扩展、甚至sql的解析规则扩展等(建议学习SPI的扩展方式,源码中大量使用)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python的基础练习题之学生管理系统

需求 使用Python基础写一个基于控制台的学生管理平台,里面功能分别是:1.录入学生信息2.查找学生信息3.删除学生信息4.修改学生信息5.排序6.统计学生总人数7.显示所有学生信息,要求数据存储在文件里。 代码 代码资源地址可以直接下载 效果图…

消除字母Scratch-第14届蓝桥杯Scratch省赛真题第6题

6. 消除字母(100分) 编程实现:消除字母。 具体要求: 1). 点击绿旗,角色、背景如图所示(创建1个字母表,并存入26个字母); 2). 等待1秒,阿拉蕾说&#xff1…

华为VRP系统基础华为ICT网络赛道

目录 1.华为VRP系统概述 3.2.命令视图与使用 3.3.基本配置命令 1.华为VRP系统概述 通用路由平台VRP(Versatile Routing Platform)是华为公司数据通信产品的通用操作系统平台。它以IP业务为核心,采用组件化的体系结构,在实现丰富功能特性的同时&#x…

AIGC学习笔记(1)——AI大模型提示词工程师

文章目录 AI大模型提示词工程师1 Prompt工程之原理1.1 AIGC的发展和产业前景前言AIGC时代的到来发展趋势和应用展望 1.2 大模型的类型和特点大模型的对比上手特点 1.3 大模型技术原理和发展成语接龙和暴力穷举ChatGPT如何理解人类语言如何存储数据图像存储电脑存数字如何让电脑…

【Docker基础二】Docker安装Mysql8

下载镜像 安装mysql(版本:8.0.35) # 拉取镜像 docker pull mysql:8.0.35 # 查看镜像是否已经下载 docker images 创建挂载目录 # 宿主机上创建挂载目录 (可以不创建,docker run -v配置了挂载目录,docker会自动…

ARMv8-AArch64 的异常处理模型详解之异常等级、执行状态以及安全状态

ARMv8-AArch64 的异常处理模型详解 一,特权和异常等级1.1 异常等级 Exception levels 二,特权的类型2.1 内存特权2.2 访问寄存器的特权 三,执行状态和安全状态3.1 执行状态 Execution states3.2 执行状态切换 3.3 安全状态 Security states3.…

商品期货交易中的强行平仓:交易所的规定和风险控制

在商品期货交易中,保证金充足的情况下,一般不会被强行平仓。然而,有几种情况可能会导致强行平仓的发生: 1 持仓超过交易所限仓规定:交易所会设定限仓规定,限制每位投资者的持仓数量。如果超过限仓规定&…

CAD安装教程

CAD安装教程 目录 一. 下载CAD二. 安装CAD 一. 下载CAD 如果需要CAD安装包请私信。 二. 安装CAD 解压压缩包AutoCAD2022中文版,以管理员身份运行AutoCAD_2022_Simplified_Chinese_Win_64bit_dlm.sfx。 选择解压路径。…

【强化学习的数学原理-赵世钰】课程笔记(六)随机近似与随机梯度下降

目录 一.内容概述 二.激励性实例(Motivating examples) 三.Robbins-Monro 算法(RM 算法): 1.算法描述 2.说明性实例(llustrative examples) 3.收敛性分析(Convergence analysi…

阿里通义最新黑科技!“通义舞王”:让静态照片翩翩起舞,探索艺术与科技的无限可能

引子:穿越二维与三维的艺术边界 在科技日新月异的时代,艺术创作的疆界正以前所未有的速度拓展,,从AI作曲和音乐生成技术带来的跨风格音乐作品,到基于人工智能的诗歌与文学创作,艺术不再仅仅是人类个体情感与才华的体…

项目管理工具Maven

Maven Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机,Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. Maven基础内容 2. Maven的依赖管…

PHP文件代码加密系统,可批量全开源

代码文件加密系统 在程序运行时,实质上是在执行机器码,而虚拟机语言的基本概念是将程序加密到一定程度,也就是说,经过加密的PHP程序在执行时会被解密成opcode继续执行。 PHP在执行时会生成opcode,然后由Zend虚拟机继…

克服幻觉:提升语言模型在自然语言处理中的准确性与可靠性

随着语言模型(LLM)在自然语言处理(NLP)中的应用日益普及,它们在文本生成、机器翻译、情感分析等许多任务中展现出惊人的能力。然而,这些模型也常常显示出一个被称作“幻觉”(hallucination&…

37%规则,最优停止问题(麦穗理论)

近期又看到37%规则,又叫麦穗理论,有很多惊人的发现。 感觉像黄金分割,但又欠那么一点点1-0.6180.38238.2%。 有意思的是,有一个数学奖,叫菲尔兹奖,只将给不超过40岁的人。如果人能活100岁,那么…

springcloud微服务分布式 springboot+vue的轻院校园网购商城管理系统 Eureka

本文的研究目标是以商城的轻院网购商城管理体系为对象,论文的研究内容包括:商品信息、系统公告等方面进行了研究。系统以当前应用最为广泛的Java语言为基础,结合了目前应用最为广泛的嵌入式嵌入式平台,集成了B/S体系结构。数据库选…

Java分布式锁理论(redis、zookeeper) 详解

目录 一、分布式锁有哪些应用场景? 二、分布式锁的实现方案 三、zookeeper实现分布式锁 一直不释放锁怎么办? 如何避免分布式锁羊群效应问题? 四、redis实现分布式锁 一、分布式锁有哪些应用场景? 1、定时任务 2、秒杀抢购…

前端性能优化之图像优化

图像优化问题主要可以分为两方面:图像的选取和使用,图像的加载和显示。 图像基础 HTTP Archive上的数据显示,网站传输的数据中,60%的资源都是由各种图像文件组成的,当然这些是将各类型网站平均的结果,单独…

二分查找(一)

算法原理 原理:当一个序列有“二段性”的时候,就可以使用二分查找算法。 适用范围:根据规律找一个点,能将这个数组分成两部分,根据规律能有选择性的舍去一部分,进而在另一个部分继续查找。 除了最普通的…

ROS-机器人仿真urdf-rviz、xacro

文章目录 一、urdf集成rviz1.1 基本流程1.2 优化 rviz 启动 二、urdf语法详解2.1 robot2.2 link2.3 joint2.4 urdf练习2.5 urdf工具 三、URDF优化_xacro3-1 Xacro_语法详解3-2 Xacro_完整使用流程示例3- Xacro_实操 一、urdf集成rviz 1.1 基本流程 需求描述: 在 Rviz 中显示一…

simulink代码生成(四)——SCI模块:接收模块

首先,实现DSP28335的自收自发; 添加串口收发模块; 设置参数,根据硬件选择串口模块: 配置中断触发;SCIB的接收中断的CPU中断号为9,PIE级中断为3; 因此如下配置; 代码生成…