14-ShardingSphere的分布式主键实现

news2025/2/23 10:54:44

1 ShardingSphere自动生成键

MySQL自增键、Oracle自增序列等。分片场景下问题就复杂了,不能依靠单实例上的自增键来实现不同数据节点之间的全局唯一主键,分布式主键的需求应运而生。ShardingSphere 作为一款优秀分库分表开源软件,同样提供分布式主键实现机制。

1.1 GeneratedKey

使用 ShardingSphere 提供的自动生成键方案时,开发过程及效果和上面描述完全一致。

ShardingSphere实现了 GeneratedKey 类:

先从 ShardingRule 找主键对应 Column是否已包含:

  • 是,则找到该主键
  • 不是,则生成新主键

分布式主键的生成看:

image-20240605101514365

GeneratedKey#generatedValues变量保存生成的主键,但生成主键的工作转移到 ShardingRule#generateKey,跳转过去:

根据logicTableName找TableRule,再找其包含的 ShardingKeyGenerator,再通过 ShardingKeyGenerator#generateKey 生成主键。

设计模式分析

ShardingRule只是个外观类,真正创建 ShardingKeyGenerator 的过程在 TableRule。而这里的 ShardingKeyGenerator 显然就是真正生成分布式主键入口。

1.2 ShardingKeyGenerator

public interface ShardingKeyGenerator extends TypeBasedSPI {

    /**
     * Generate key.
     * 
     * @return generated key
     */
    Comparable<?> generateKey();
}

TableRule一个构造器找到 ShardingKeyGenerator 创建:

ShardingKeyGeneratorServiceLoader类定义:

// 继承了 TypeBasedSPIServiceLoader
public final class ShardingKeyGeneratorServiceLoader extends TypeBasedSPIServiceLoader<ShardingKeyGenerator> {

  static {
    // 注册类路径中所有的 ShardingKeyGenerator
    NewInstanceServiceLoader.register(ShardingKeyGenerator.class);
  }

  public ShardingKeyGeneratorServiceLoader() {
    super(ShardingKeyGenerator.class);
  }
}

执行完后,ShardingKeyGeneratorServiceLoader#newService基于类型参数通过 SPI 创建实例,并赋值 Properties 属性:

继承 TypeBasedSPIServiceLoader 创建一个新的 ServiceLoader 类,然后在其静态方法注册相应 SPI 实现,这是 ShardingSphere 应用微内核模式常见做法。

sharding-core-common 工程的 META-INF/services 目录看到具体 SPI 定义:

2 ShardingSphere分布式主键实现

ShardingKeyGenerator 接口存在一批实现类。除前面:

  • SnowflakeShardingKeyGenerator
  • UUIDShardingKeyGenerator

还实现了:

  • LeafSegmentKeyGenerator
  • LeafSnowflakeKeyGenerator

2.1 UUIDShardingKeyGenerator

最简单的ShardingKeyGenerator:

2.2 SnowflakeShardingKeyGenerator

ShardingSphere最大容忍的时钟回拨毫秒数的默认0,可通过max.tolerate.time.difference.milliseconds设置。

常量定义,维护 SnowFlake 算法中各个 bit 之间的关系

generateKey 负责生成具体ID:

综合考虑时钟回拨、同一ms内请求,才完成 SnowFlake 算法具体实现。

2.3 LeafSegmentKeyGenerator 和 LeafSnowflakeKeyGenerator

实现类似SnowflakeShardingKeyGenerator的ShardingKeyGenerator困难,也属重复造轮子。因此,尽管 ShardingSphere 4.x提供了完整实现:

但5.x移除。目前,ShardingSphere 专门提供 OpenSharding 库存放新版的 LeafSegmentKeyGenerator 和 LeafSnowflakeKeyGenerator。新版实现类直接采用第三方美团提供的 Leaf 开源实现。

Leaf 提供两种生成 ID 方式:

  • 号段(Segment)模式
  • Snowflake 模式

无论哪种,都要提供一个 leaf.properties 文件,并设置配置项。无论哪种,应用程序都要设置一个leaf.key:

# for keyGenerator key
leaf.key=sstest

# for LeafSnowflake
leaf.zk.list=localhost:2181

如用号段模式,需依赖一张数据库表存储运行时数据,因此要在 leaf.properties 文件中添加数据库配置:

# for LeafSegment
leaf.jdbc.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&useSSL=false
leaf.jdbc.username=root
leaf.jdbc.password=123456

即可创建对应DataSource,并进一步创建用于生成分布式 ID 的 IDGen 实现类。

LeafSegmentKeyGenerator

基于号段模式的 SegmentIDGenImpl 实现类:

//通过DruidDataSource构建数据源并设置属性
DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(properties.getProperty(LeafPropertiesConstant.LEAF_JDBC_URL));
        dataSource.setUsername(properties.getProperty(LeafPropertiesConstant.LEAF_JDBC_USERNAME));
        dataSource.setPassword(properties.getProperty(LeafPropertiesConstant.LEAF_JDBC_PASSWORD));
dataSource.init();

//构建数据库访问Dao组件
IDAllocDao dao = new IDAllocDaoImpl(dataSource);
//创建IDGen实现类
this.idGen = new SegmentIDGenImpl();
//将Dao组件绑定到IDGen实现类
((SegmentIDGenImpl) this.idGen).setDao(dao);
this.idGen.init();
this.dataSource = dataSource;

创建IDGen实现类,即可通过该类生成目标 ID,LeafSegmentKeyGenerator 类中包含所有的实现细节:

Result result = this.idGen.get(properties.getProperty(LeafPropertiesConstant.LEAF_KEY));
return result.getId();
LeafSnowflakeKeyGenerator

LeafSnowflakeKeyGenerator实现依赖于分布式协调框架 Zookeeper,所以在配置文件中需要指定 Zookeeper 的目标地址:

# for LeafSnowflake
leaf.zk.list=localhost:2181

创建用于 LeafSnowflake 的 IDGen 实现类 SnowflakeIDGenImpl 相对比较简单,直接在构造器设置 zk 地址即可:

IDGen idGen = new SnowflakeIDGenImpl(properties.getProperty(LeafPropertiesConstant.LEAF_ZK_LIST), 8089);

通过 IDGen 获取模板 ID 的方式一致:

idGen.get(properties.getProperty(LeafPropertiesConstant.LEAF_KEY)).getId();

基于 Leaf 框架实现号段模式和 Snowflake 模式下的分布式 ID 生成方式非常简单,Leaf 框架为我们屏蔽了内部实现复杂性。

3 总结

ShardingSphere的分布式主键设计非常独立,本文各种分布式主键实现完全可直接套用到日常开发。

无论ShardingSphere自身实现的SnowflakeShardingKeyGenerator,还是基于第三方框架实现的 LeafSegmentKeyGenerator 和 LeafSnowflakeKeyGenerator,都为我们使用分布式主键提供直接解决方案。

参考:

  • 分布式主键

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都技术专家,多家大厂后端一线研发经验,在分布式系统、和大数据平台设计等方面有多年研究和实践经验,拥有从0到1的大数据平台和基础架构研发经验,对分布式存储、数据平台架构、数据仓库等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化

  • 活动&优惠券等营销中台建设

  • 交易平台及数据中台等架构和开发设计

  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化

    目前主攻降低软件复杂性设计、构建高可用系统方向。

参考:

  • 编程严选网

    本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

Ubuntu18.04安装pwntools报错解决方案

报错1&#xff1a;ModuleNotFoundError: No module named ‘setuptools_rust’ 报错信息显示ModuleNotFoundError: No module named setuptools_rust&#xff0c;如下图所示 解决方案&#xff1a;pip install setuptools_rust 报错2&#xff1a;pip版本低 解决方案&#xff…

【Test 49 】OSI 七层模型初识、网络传输的流程、IP地址和MAC地址! 面试高频考点!

文章目录 1. OSI七层模型2. TCP/IP五层(或四层)模型3. 网络传输基本流程 &#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#x1f427;&#…

MyBatis中的接口代理机制及其使用

1. MyBatis中的接口代理机制及其使用 文章目录 1. MyBatis中的接口代理机制及其使用2. 实操2.1 准备工作2.2 insert 增加操作2.3 delete 删除操作2.4 update 修改操作2.5 select 查询一条记录操作2.6 select 查询多条记录操作 3. 总结&#xff1a;4. 最后&#xff1a; MyBatis …

五、数据源池化技术实现

学这一节的时候重新梳理了DataSource、DriverManager、Driver、DriverProxy、Connection之间的关系&#xff0c;如下图 在整体流程中&#xff0c;这一块就是通过配置文件配置&#xff0c;在解析配置文件的时候就创建对应的数据源封装到Environment中&#xff0c;在执行sql的时…

使用Qt对word文档进行读写

目录 开发环境原理使用的QT库搭建开发环境准备word模板测试用例结果Gitee地址 开发环境 vs2022 Qt 5.9.1 msvc2017_x64&#xff0c;在文章最后提供了源码。 原理 Qt对于word文档的操作都是在书签位置进行插入文本、图片或表格的操作。 使用的QT库 除了基本的gui、core、…

3072. 将元素分配到两个数组中 II

题目 给你一个下标从 1 开始、长度为 n 的整数数组 nums 。 现定义函数 greaterCount &#xff0c;使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。 你需要使用 n 次操作&#xff0c;将 nums 的所有元素分配到两个数组 arr1 和 arr2 中。在第一次操…

【调试笔记-20240604-Linux-为 OpenWrt LuCI 界面添加多语言支持】

调试笔记-系列文章目录 调试笔记-20240604-Linux-为 OpenWrt LuCI 界面添加多语言支持 文章目录 调试笔记-系列文章目录调试笔记-20240604-Linux-为 OpenWrt LuCI 界面添加多语言支持 前言一、调试环境操作系统&#xff1a;Ubuntu 22.04.4 LTS编译环境调试目标 二、调试步骤预…

vue-pdf 部分中文显示错误,第二次打开是空白,解决方法

首先鸣谢 1. https://blog.csdn.net/m0_71537867/article/details/131614868?spm1001.2014.3001.5506 2. https://blog.csdn.net/weixin_43763952/article/details/133769647 3. https://github.com/FranckFreiburger/vue-pdf/issues/229 4. https://blog.csdn.net/weixin_449…

Java中常用的单目运算符及用法详解

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

【Linux多线程】线程的终止、等待和分离

文章目录 线程终止正常退出return 退出pthread_exit函数终止线程 pthread_cancel强制终止线程进程终止 线程等待为什么需要等待线程&#xff1f;pthread_join函数 分离线程pthread_detach函数 线程终止 下面给出终止线程的三种方式&#xff1a; 正常退出&#xff1a; 线程执行…

【Flask-项目运行】解决用本机IP访问不到flask项目而用localhost可以访问到的问题

文章目录 一、问题描述二、解决办法 一、问题描述 使用 localhost 或 127.0.0.1 能访问到项目&#xff1a; 但是使用局域网 IP 访问不到&#xff1a; 二、解决办法 只需要在 app.py 中修改一行代码&#xff1a; run方法添加 host 参数指明全部 ip 可访问。

【Linux】(四)—— 文件权限管理

权限管理 这篇文章主要时对前篇文章中的用户和文件的权限操作做一些补充说明 用户权限&#xff1a; sudo&#xff1a;临时提升权限为root&#xff1b;sudo -s&#xff1a;永久提升权限为root。 ls -l显示的文件列表的第一列表示文件类型&#xff0c;第一个字母为-表示普通文…

wps:基本使用【笔记】

wps&#xff1a;基本使用【笔记】 前言版权推荐wps&#xff1a;基本使用如何去除复制文本的样式显示空格、换行、分节符快捷键设置字体添加章节添加奇数页分节符设置页边距设置页眉页脚设置页码 最后 前言 2024-6-5 23:10:12 以下内容源自《【笔记】》 仅供学习交流使用 版权…

vue3中的ref与reactive的区别

这里写自定义目录标题 1、两者的区别2、用法3、vue3中声明的数组/对象3.1 通过reactive 声明的Array/Object&#xff0c;需要重新分配一个全新的对象&#xff0c;会出错、或失去响应式效果 3.2 解决方案 4、cosnt 说明5、Proxy 与 defineProperty 1、两者的区别 ref&#xff1…

13- Redis 中的 压缩列表 数据结构

压缩列表的最大特点&#xff0c;就是它被设计成一种内存紧凑型的数据结构&#xff0c;占用 一块连续的内存空间&#xff0c;不仅可以利用 CPU 缓存&#xff0c;而且会针对不同长度的数据&#xff0c;进行相应编码&#xff0c;这种方法可以有效的节省内存开销。 但是&#xff0…

R语言探索与分析20-北京市气温预测分析

一、序言 近年来&#xff0c;人类大量燃烧煤炭、天然气等含碳燃料导致温室气 体过度排放&#xff0c;大量温室气体强烈吸收地面辐射中的红外线&#xff0c;造 成温室效应不断累积&#xff0c;使得地球温度上升&#xff0c;造成全球气候变暖。气象温度的预测一直以来都是天气预…

windows系统 flutter 开发环境配置

1、管理员运行powershell&#xff0c;安装&#xff1a;Chocolatey 工具&#xff0c;粘贴复制运行下列脚本: Chocolatey 官方安装文档 Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol [System.Net.ServicePointManage…

如何自动化地评估 AIGC 生图的质量?

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学。 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 合集&#x…

秋招突击——算法打卡——6/5——提高{(状态机模型)股票买卖、(单调队列优化DP)最大子序列和}——新做:{考试的最大困扰度}

文章目录 提高(状态机模型)股票买卖IV思路分析实现代码参考代码 新作考试的最大困扰度个人实现参考思路 总结 提高 (状态机模型)股票买卖IV 上一次的思路总结&#xff0c;上次写的时候忘记总结了&#xff0c;现在重新画一下图 思路分析 这道题是一个经典的状态机模型&#…

Python | Leetcode Python题解之第134题加油站

题目&#xff1a; 题解&#xff1a; class Solution:def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:start, cur_res, total_res 0, 0, 0for i in range(len(gas)):cur_res gas[i] - cost[i]total_res gas[i] - cost[i]if cur_res < 0:cur_r…