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,m1spring.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=123666spring.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=123666spring.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;@Overridepublic 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=truespring.shardingsphere.datasource.names=m0,m1spring.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=123666spring.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=1spring.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=truespring.shardingsphere.datasource.names=m0,m1spring.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=123666spring.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]=m1spring.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,m1spring.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=123666spring.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=123666spring.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=SNOWFLAKEspring.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.mzph.cn/news/606154.shtml

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

相关文章

一致性 Hash

一致性 Hash 一致性哈希算法(Consistent Hashing Algorithm)是一种分布式算法,常用于负载均衡。Memcached client 也选择这种算法,解决将 key-value 均匀分配到众多 Memcached server 上的问题。它可以取代传统的取模操作,解决了取模操作无法…

关于网盘下载速度提升的一些技巧!!

这里写自定义目录标题 前言:步骤:一、下载IDM二、安装油猴三、添加到Google拓展程序上PS:四、添加脚本五、IDM配置六、打开网页版网盘 前言: 18G的网盘资源下载时间仅仅3-5分钟 步骤: 一、下载IDM 这里我以IDM举例…

kettle分页抽取数据

背景 kettle抽取数据大家还是比较熟悉的,kettle在抽取数据的时候会开启很多通道,同时抽取,但是我现在遇到一个场景: 从一个mysql数据库里获取“已办”状态的数据id,然后拿这些id去一个oracle数据库里查询&#xff0c…

【MATLAB】ICEEMDAN_LSTM神经网络时序预测算法

有意向获取代码,请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 ICEEMDAN-LSTM神经网络时序预测算法是一种结合了改进的完全扩展经验模态分解(ICEEMDAN)和长短期记忆神经网络(LSTM)的时间序列预测方法。 …

【UE Niagara学习笔记】02 - 制作燃烧的火焰

目录 效果 步骤 一、添加资产 二、制作材质 三、制作粒子 3.1 循环播放 3.2 粒子生成的数量 3.3 粒子的生命周期和初始大小 3.4 火焰高度 3.5 火焰范围 3.6 火焰颜色 效果 步骤 一、添加资产 1. 在虚幻商城中搜索“M5 VFX Vol2. Fire and Flames(Niagara)”…

遇见狂神说 Spring MVC 学习笔记(完整笔记+代码)

MVC架构介绍 MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范MVC是将业务逻辑、数据、显示分离的方式来组织代码MVC主要作用是降低了视图与业务逻辑间的双向偶合MVC不是一种设计模式,是一种架构模式。当然不同的MVC存在差异…

python 文件

open """ def open(file: FileDescriptorOrPath, //路径mode: OpenTextMode "r", //设置打开文件的模式 r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 w 打开一个文件只用写入。如果该文件已存在则打开文件&#…

CodeWave智能开发平台--03--目标:应用创建--07供应商数据表格02

摘要 本文是网易数帆CodeWave智能开发平台系列的第10篇,主要介绍了基于CodeWave平台文档的新手入门进行学习,实现一个完整的应用,本文主要完成07供应商数据表格下 CodeWave智能开发平台的10次接触 CodeWave参考资源 网易数帆CodeWave开发…

Docker简述与基础部署详解

docker官网:https://www.docker.com docker中文库:https://www.docker.org.cn/ Docker是一种开源的容器化平台,用于轻松打包、交付和运行应用程序。Docker的主要优势在于它提供了一种轻量级、可移植、自包含的容器化技术,使得应用程序及其所…

智能手表喇叭无气孔导致老化播放后没声音

智能音箱喇叭老化播放后没声音 智能手表要做防水,在外壳上打了防水胶,结果出现播放突然没声音的现象. 原因 一直播放,设备温度升高,因为做了防水密闭导致喇叭腔体气压异常,导致播放没声音. …

pod节点jar包替换流程

1、查找到该docker容器 docker ps | grep backend # ./entrypoint.sh文件启动的那个容器2、替换jar 包 mv xxx.jar app.jar docker cp app.jar 66bc6fea9fb5:/home/aimind/3、重启容器 docker restart 66bc6fea9fb5 4、重启容器后进行功能验证 功能验证没问题了,再…

树莓派点亮led(1)

更换清华源 树莓派更换国内源(清华源)_树莓派更换清华源-CSDN博客 查看python版本 安装pipx 安装引脚 查看引脚 #安装gpio 创建文件夹 创建py文件 运行python文件 ubuntu传递文件到树莓派 1、启用ubuntu端的新终端 2拷贝文件到home目录下的用户文件夹…

数据库内核那些事|细说PolarDB优化器查询变换:IN-List变换

导读 数据库的查询优化器是整个系统的"大脑",一条SQL语句执行是否高效在不同的优化决策下可能会产生几个数量级的性能差异,因此优化器也是数据库系统中最为核心的组件和竞争力之一。阿里云瑶池旗下的云原生数据库PolarDB MySQL版作为领先的云…

【模拟IC学习笔记】 采样保持电路的设计

目录 采样保持工作原理 概念 时域响应-采保信号 采样网络的KT/C噪声 采样电容大小的选取 采样抖动(jitter) jitter对SNR的影响 法一 法二 采样开关的种类 单MOS管 实践:Nmos导通电阻 传输门 栅压自举开关 采样技术 上极板采样 下极板采样 采样保持…

spark的任务提交方式及流程

本地模式 local 测试用,不多赘述 分布式模式 standalone standalone集群是spark 自带的一个资源调度集群,分为两个角色,master/worker,master负责接收任务请求、资源调度(监听端口7077),worker负责运行exec…

NPS 内网穿透安装

NPS 内网穿透安装 NPS 内网穿透安装服务端搭建SSH配置流程 NPS 内网穿透安装 NPS分为服务端和客户端,对应的不同操作系统软件可以在GitHub RELEASES自行选择下载。 服务端搭建 由于个人非企业级使用,为了方便直接使用docker安装 1.docker运行 (注意…

喇叭性能指标

喇叭的技术指标 灵敏度 频率响应曲线 额定阻抗 谐振频率F0 失真THD 灵敏度 灵敏度越高,声音越大。 f0 f0(bass resonace frequency)是最低共振频率(低频下限频),越低表示对低频的响应越好,在满足音腔空间的条件下,声音更饱满. 可直接用f0测试仪测量或通过测量阻…

Qt / day01

1. 思维导图 2. 自由发挥应用场景实现一个登录窗口界面。 代码(mywidget.cpp): #include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {// windows setup //setup windows sizethis->resize(600, 370);//set window fixed si…

c/c++基础 自增自减运算符 大白讲解i++/i--/++i/--i

后置运算符:i表示在使用x之后,再使x的值加1,即ii1; 前置运算符:i表示在使用x之前,先使x的值加1,即ii1. 前缀运算和后缀运算的区别:前缀运算是“先变后用”,而后缀运算是“先用后变”…

【idea】idea 开发快捷键

在Java开发中,有一些常用的快捷键和工具,可以提高开发效率。以下是一些常见的Java开发常用到的功能和快捷键: IDE快捷键: 格式化代码:Ctrl Alt L,会让代码更整齐,调整间距之类的 导入包&am…