一篇搞定ShardingSphere-jdbc 实战

news2024/11/18 1:46:30

谈到分库分表中间件时,我们自然而然的会想到 ShardingSphere-JDBC 。

这篇文章,我们聊聊 ShardingSphere-JDBC 相关知识点,并实战演示一番。

1 ShardingSphere 生态

Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产品:

  • ShardingSphere-Proxy

  • ShardingSphere-JDBC

▍一、ShardingSphere-Proxy

ShardingSphere-Proxy 被定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。

代理层介于应用程序与数据库间,每次请求都需要做一次转发,请求会存在额外的时延。

这种方式对于应用非常友好,应用基本零改动,和语言无关,可以通过连接共享减少连接数消耗。

▍二、ShardingSphere-JDBC

ShardingSphere-JDBC 是 ShardingSphere 的第一个产品,也是 ShardingSphere 的前身, 我们经常简称之为:sharding-jdbc 。

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


当我们在 Proxy 和 JDBC 两种模式选择时,可以参考下表对照:

JDBC

Proxy

数据库

任意

MySQL/PostgreSQL

连接消耗数

异构语言

仅Java

任意

性能

损耗低

损耗略高

无中心化

静态入口

越来越多的公司都在生产环境使用了 sharding-jdbc ,最核心的原因就是:简单(原理简单,易于实现,方便运维)。

2 基本原理

在后端开发中,JDBC 编程是最基本的操作。不管 ORM 框架是 Mybatis 还是 Hibernate ,亦或是 spring-jpa ,他们的底层实现是 JDBC 的模型。

sharding-jdbc 的本质上就是实现 JDBC 的核心接口。

接口

实现类

DataSource

ShardingDataSource

Connection

ShardingConnection

Statement

ShardingStatement

PreparedStatement

ShardingPreparedStatement

ResultSet

ShardingResultSet

虽然我们理解了 sharding-jdbc 的本质,但是真正实现起来还有非常多的细节,下图展示了 Prxoy 和 JDBC 两种模式的核心流程。

1.SQL 解析

分为词法解析和语法解析。 先通过词法解析器将 SQL 拆分为一个个不可再分的单词。再使用语法解析器对 SQL 进行理解,并最终提炼出解析上下文。

解析上下文包括表、选择项、排序项、分组项、聚合函数、分页信息、查询条件以及可能需要修改的占位符的标记。

2.执行器优化

合并和优化分片条件,如 OR 等。

3.SQL 路由

根据解析上下文匹配用户配置的分片策略,并生成路由路径。目前支持分片路由和广播路由。

4.SQL 改写

将 SQL 改写为在真实数据库中可以正确执行的语句。SQL 改写分为正确性改写和优化改写。

5.SQL 执行

通过多线程执行器异步执行。

6.结果归并

将多个执行结果集归并以便于通过统一的 JDBC 接口输出。结果归并包括流式归并内存归并和使用装饰者模式的追加归并这几种方式。

本文的重点在于实战层面, sharding-jdbc 的实现原理细节我们会在后续的文章一一给大家呈现 。

3 实战案例

笔者曾经为武汉一家 O2O 公司订单服务做过分库分表架构设计 ,当企业用户创建一条采购订单 , 会生成如下记录:

  • 订单基础表t_ent_order :单条记录

  • 订单详情表t_ent_order_detail :单条记录

  • 订单明细表t_ent_order_item:N 条记录

订单数据采用了如下的分库分表策略:

  • 订单基础表按照 ent_id (企业用户编号) 分库 ,订单详情表保持一致;

  • 订单明细表按照 ent_id (企业用户编号) 分库,同时也要按照 ent_id (企业编号) 分表。

首先创建 4 个库,分别是:ds_0、ds_1、ds_2、ds_3 。

这四个分库,每个分库都包含 订单基础表 , 订单详情表 ,订单明细表 。但是因为明细表需要分表,所以包含多张表。

然后 springboot 项目中配置依赖 :

<dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.1.1</version></dependency>

配置文件中配置如下:

  • 配置数据源,上面配置数据源是: ds0、ds1、ds2、ds3 ;

  • 配置打印日志,也就是:sql.show ,在测试环境建议打开 ,便于调试;

  • 配置哪些表需要分库分表 ,在 shardingsphere.datasource.sharding.tables 节点下面配置:

上图中我们看到配置分片规则包含如下两点:

1.真实节点

对于我们的应用来讲,我们查询的逻辑表是:t_ent_order_item 。

它们在数据库中的真实形态是:t_ent_order_item_0 到 t_ent_order_item_7。

真实数据节点是指数据分片的最小单元,由数据源名称和数据表组成。

订单明细表的真实节点是:ds$->{0..3}.t_ent_order_item_$->{0..7} 。

2.分库分表算法

配置分库策略和分表策略 , 每种策略都需要配置分片字段( sharding-columns )和分片算法

4 基因法 & 自定义复合分片算法

分片算法和阿里开源的数据库中间件 cobar 路由算法非常类似的。

假设现在需要将订单表平均拆分到4个分库 shard0 ,shard1 ,shard2 ,shard3 。

首先将 [0-1023] 平均分为4个区段:[0-255],[256-511],[512-767],[768-1023],然后对字符串(或子串,由用户自定义)做 hash, hash 结果对 1024 取模,最终得出的结果 slot 落入哪个区段,便路由到哪个分库。

看起来分片算法很简单,但我们需要按照订单 ID 查询订单信息时依然需要路由四个分片,效率不高,那么如何优化呢 ?

答案是:基因法 & 自定义复合分片算法

基因法是指在订单 ID 中携带企业用户编号信息,我们可以在创建订单 order_id 时使用雪花算法,然后将 slot 的值保存在 10位工作机器 ID 里。

通过订单 order_id 可以反查出 slot , 就可以定位该用户的订单数据存储在哪个分片里。

Integer getWorkerId(Long orderId) {
 LongworkerId= (orderId >> 12) & 0x03ff;
 return workerId.intValue();
}

下图展示了订单 ID 使用雪花算法的生成过程,生成的编号会携带企业用户 ID 信息。

解决了分布式 ID 问题,接下来的一个问题:sharding-jdbc 可否支持按照订单 ID ,企业用户 ID 两个字段来决定分片路由吗?

答案是:自定义复合分片算法。我们只需要实现 ComplexKeysShardingAlgorithm 类即可。

复合分片的算法流程非常简单:

1.分片键中有主键值,则直接通过主键解析出路由分片;

2.分片键中不存在主键值 ,则按照其他分片字段值解析出路由分片。

5 扩容方案

既然做了分库分表,如何实现平滑扩容也是一个非常有趣的话题。

在数据同步之前,需要梳理迁移范围。

1.业务唯一主键

在进行数据同步前,需要先梳理所有表的唯一业务 ID,只有确定了唯一业务 ID 才能实现数据的同步操作。

需要注意的是:业务中是否有使用数据库自增 ID 做为业务 ID 使用的,如果有需要业务先进行改造 。另外确保每个表是否都有唯一索引,一旦表中没有唯一索引,就会在数据同步过程中造成数据重复的风险,所以我们先将没有唯一索引的表根据业务场景增加唯一索引(有可能是联合唯一索引)。

2.迁移哪些表,迁移后的分库分表规则

分表规则不同决定着 rehash 和数据校验的不同。需逐个表梳理是用户ID纬度分表还是非用户ID纬度分表、是否只分库不分表、是否不分库不分表等等。

接下来,进入数据同步环节

整体方案见下图,数据同步基于 binlog ,独立的中间服务做同步,对业务代码无侵入。

首先需要做历史数据全量同步:也就是将旧库迁移到新库。

单独一个服务,使用游标的方式从旧库分片 select 语句,经过 rehash 后批量插入 (batch insert)到新库,需要配置jdbc 连接串参数 rewriteBatchedStatements=true 才能使批处理操作生效。

因为历史数据也会存在不断的更新,如果先开启历史数据全量同步,则刚同步完成的数据有可能不是最新的。

所以我们会先开启增量数据单向同步(从旧库到新库),此时只是开启积压 kafka 消息并不会真正消费;然后在开始历史数据全量同步,当历史全量数据同步完成后,在开启消费 kafka 消息进行增量数据同步(提高全量同步效率减少积压也是关键的一环),这样来保证迁移数据过程中的数据一致。

增量数据同步考虑到灰度切流稳定性、容灾 和可回滚能力 ,采用实时双向同步方案,切流过程中一旦新库出现稳定性问题或者新库出现数据一致问题,可快速回滚切回旧库,保证数据库的稳定和数据可靠。

增量数据实时同步的大体思路 :

1.过滤循环消息

需要过滤掉循环同步的 binlog 消息 ;

2.数据合并

同一条记录的多条操作只保留最后一条。为了提高性能,数据同步组件接到 kafka 消息后不会立刻进行数据流转,而是先存到本地阻塞队列,然后由本地定时任务每X秒将本地队列中的N条数据进行数据流转操作。此时N条数据有可能是对同一张表同一条记录的操作,所以此处只需要保留最后一条(类似于 redis aof 重写);

3.update 转 insert

数据合并时,如果数据中有 insert + update 只保留最后一条 update ,会执行失败,所以此处需要将 update 转为 insert 语句 ;

4.按新表合并

将最终要提交的 N 条数据,按照新表进行拆分合并,这样可以直接按照新表纬度进行数据库批量操作,提高插入效率。

扩容方案文字来自 《256变4096:分库分表扩容如何实现平滑数据迁移》,笔者做了些许调整。

6 总结

sharding-jdbc 的本质是实现 JDBC 的核心接口,架构相对简单。

实战过程中,需要配置数据源信息,逻辑表对应的真实节点和分库分表策略(分片字段分片算法

实现分布式主键直接路由到对应分片,则需要使用基因法 & 自定义复合分片算法

平滑扩容的核心是全量同步实时双向同步,工程上有不少细节。

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

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

相关文章

操作系统权限提升(二十三)之Linux提权-通配符(ws)提权

系列文章 操作系统权限提升(十八)之Linux提权-内核提权 操作系统权限提升(十九)之Linux提权-SUID提权 操作系统权限提升(二十)之Linux提权-计划任务提权 操作系统权限提升(二十一)之Linux提权-环境变量劫持提权 操作系统权限提升(二十二)之Linux提权-SUDO滥用提权 利用通配符…

redis的集群方式

1.主从复制 主从复制原理&#xff1a; 从服务器连接主服务器&#xff0c;发送SYNC命令&#xff1b; 主服务器接收到SYNC命名后&#xff0c;开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令&#xff1b; 主服务器BGSAVE执行完后&#xff0c;向所有从服务…

阿里测试7年,薪资从7K到25K,我的成功值得每一个人借鉴

7年从业经验&#xff0c;这篇文章将汇集自动化测试所需知识&#xff0c;拒绝标题党&#xff0c;水文。让所有想学习提升技术的能从文中获取有价值的知识。 在这个吃技术的IT行业来说&#xff0c;我之前每天做的是最基础功能测试的工作&#xff0c;但是随着时间的消磨&#xff…

C++回顾(五)—— 构造函数和析构函数

5.1 构造和析构 5.1.1 构造函数 &#xff08;1&#xff09;定义 1&#xff09;C中的类可以定义与类名相同的特殊成员函数&#xff0c;这种与类名相同的成员函数叫做构造函数&#xff1b;2&#xff09;构造函数在定义时可以有参数&#xff1b;3&#xff09;没有任何返回类型的…

第十届蓝桥杯省赛——5最大降水量(纯填空,分析)

题目&#xff1a;试题 E: 最大降雨量本题总分&#xff1a;15 分【问题描述】由于沙之国长年干旱&#xff0c;法师小明准备施展自己的一个神秘法术来求雨。这个法术需要用到他手中的 49 张法术符&#xff0c;上面分别写着 1 至 49 这 49 个数字。法术一共持续 7 周&#xff0c;每…

二叉树——二叉树的最近公共祖先

二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一…

如何使用DDexec在Linux上隐蔽运行二进制文件

关于DDexec DDexec是一种能够在Linux上使用无文件技术和隐秘技术运行二进制文件的方法&#xff0c;它可以使用dd工具来将Shell替换为其他进程。 众所周知&#xff0c;在Linux上运行一个程序&#xff0c;则这个程序必须以一个文件的形式存在&#xff0c;而且必须能够通过文件系…

电脑没有回收站找回删除文件的2种方法

最近后台收到了这样的咨询&#xff1a;”在网吧上网&#xff0c;删除东西的时候不小心把我的文件给删除了&#xff0c;但是桌面上没有回收站&#xff0c;怎么才能找回我的文件&#xff1f;“——针对“电脑没有回收站删除的东西怎么恢复”这种疑问&#xff1f;不妨看看下面数据…

环境搭建02-Ubuntu16.04 安装CUDA和CUDNN、CUDA多版本替换

1、CUDA安装 &#xff08;1&#xff09;下载需要的CUDA版本 https://developer.nvidia.com/cuda-toolkit-archive &#xff08;2&#xff09;安装 sudo sh cuda_8.0.61_375.26_linux.run&#xff08;3&#xff09;添加环境 gedit ~/.bashrc在文件末尾添加&#xff1a; ex…

【小程序】已有公众号认证,一步一步申请小程序(图文)

一、登陆公众号后台&#xff0c;找到左侧广告与服务&#xff0c;小程序管理&#xff0c;开通 二、选择快速注册认证小程序 三、快速创建 四、选择微信认证资质&#xff08;复用&#xff09;&#xff0c;这样不用再付认证费了 五、需要一个新的邮箱&#xff0c;这点挺让人无语&a…

【Hello Linux】进程优先级和环境变量

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下进程的优先级 环境变量 进程优先级环境变量进程的优先级基本概念如何查看优先级PRI与NINI值的设置范围NI值如何修改修改方式…

PT100铂电阻温度传感器

PT100温度传感器又叫做铂热电阻。     热电阻是中低温区&#xfe61;常用的一种温度检测器。它的主要特点是测量精度高&#xff0c;性能稳定。其中铂热电阻的测量精确度是&#xfe61;高的&#xff0c;它不仅广泛应用于工业测温&#xff0c;而且被制成标准的基准仪。金属热…

此网站可能不支持TLS1.2协议

问题描述 火狐浏览器版本&#xff1a;“97.0.1 (64 位)”&#xff0c;打开360网神设备Web管理地址时出现&#xff1a;“此网站可能不支持TLS1.2协议&#xff0c;而这是Firefox支持的最低版本。”&#xff0c;如下图所示。 原本是默认使用https协议打开的&#xff0c;看起来出问…

Ep_操作系统面试题-什么是线程,线程和进程的区别

1. 一个进程中可以有多个线程,多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间),但是每个线程有自己的程序计数器、虚拟机栈和 本地方法栈。 2.进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 视频讲解: https://edu.csdn.net/course/detail/38090 点我…

CSS简单使用

凡是html中的标签都可以进行选中&#xff0c;p代表标签中所有的p标签都遵从以上格式。<!DOCTYPE html> <html lang"en"> <head><style type"text/css">p{background-color: red;font-size: 40px;}.p1{font-family:楷体;}</styl…

爆!!!2023《TikTok美妆个护行业分析报告》重磅出炉,掌握趋势加速出海变现!

2022年是中国化妆品零售行业的拐点之年&#xff0c;零售总额跌破4000亿元大关&#xff0c;是13年来的首次下滑。随着国内消费者对化妆品支出的放缓&#xff0c;越来越多的美妆个护国牌选择出海寻找第二增长曲线&#xff0c;而新渠道如TikTok 等电商平台的崛起&#xff0c;也为出…

ECharts教程(详细)

ECharts教程(详细) 非常全面的ECharts教程&#xff0c;非常全面的ECharts教程&#xff0c;目前线条/节点颜色、线条粗细、线条样式、线条阴影、线条平滑、线条节点大小、线条节点阴影、线条节点边框、线条节点边框阴影、工具提醒、工具提醒样式、工具自定义提醒、工具提醒背景…

云Windows Server 2022 Datacenter 安装MySQL8解压缩版 mysql-8.0.32-winx64 230301记录

MySQL Community Downloads MySQL社区版压缩包下载地址 https://dev.mysql.com/downloads/mysql/ 解压到了C盘 没打算设置环境变量 右键点击开始 或 winx 以管理员身份打开 PowerShell 进入到安装目录下的 bin 目录 可以输入cd 后&#xff0c; 拖动 bin 文件夹到控制台&…

二分算法题

文章目录一、在排序数组中查找数字二、0~n-1中缺失的数字三、旋转数组的最小数字四、二维数组中的查找一、在排序数组中查找数字 题目传送门 法一&#xff1a;暴力解 直接遍历然后计数 法二&#xff1a;二分法求边界 看到关键字排序数组、有序数组&#xff0c;一定要想到二分…

Nacos2.x+Nginx集群配置

一、配置 nacos 集群 注意&#xff1a;需要先配置好 nacos 连接本地数据库 1、拷贝三份 nacos 2、修改配置文件&#xff08;cluster.conf&#xff09; 修改启动端口&#xff1a; nacos1&#xff1a;8818 nacos2&#xff1a;8828 nacos3&#xff1a;8838 当nacos客户端升级为…