首页 > 其他分享 >14-ShardingSphere的分布式主键实现

14-ShardingSphere的分布式主键实现

时间:2024-06-05 13:44:20浏览次数:28  
标签:ShardingKeyGenerator leaf 14 实现 ShardingSphere 主键 分布式

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 发布!

标签:ShardingKeyGenerator,leaf,14,实现,ShardingSphere,主键,分布式
From: https://www.cnblogs.com/JavaEdge/p/18232819

相关文章

  • T461430 「Daily OI Round 4」Mine
    T461430「DailyOIRound4」MineT461430「DailyOIRound4」Mine解题思路首先,有个简单的想法就是我们考虑选择的那个采矿点是谁,但是我们发现,如果直接算,会重复,比如采矿点\(A\)和采矿点\(B\)所能采集的线段集合如果有交,显然会方案数会重复。这里学到一个计数的技巧:考......
  • 代码随想录算法训练营day14(二叉树)
    代码随想录算法训练营day14(二叉树):学习内容:今天学习二叉树。二叉树节点标准写法(当前节点值,左右子节点,有点像链表节点的定义):structTreeNode{intval;TreeNode*left;TreeNode*right;TreeNode(intx):val(x),left(NULL),right(NULL){}};二......
  • 公安视频图像信息数据库及GA/T 1400视图库视频监控系统的使用场景
    随着科技的快速发展,大数据、人工智能等新技术不断融入各行各业,为各行各业带来了前所未有的变革。在公安领域,GA/T1400协议公安视频图像信息数据库的应用为视频监控场景提供了强有力的支持,极大地提升了公安工作的效率和准确性。一、公安视频图像信息数据库组成1、公安视频图像......
  • 安防综合管理系统EasyCVR视频汇聚平台GA/T 1400协议中的关键消息交互示例
    在当今的信息化时代,公共安全防范日益成为保障社会和谐稳定的关键。视频监控系统作为现代安全防范的重要手段,正不断在公安、交通、城市管理等领域发挥着越来越重要的作用。而GA/T1400协议视图库,作为公安视频图像信息应用系统的标准,与视频监控系统的结合使用,无疑为提升监控效果、强......
  • 2024-05-14影视排行榜
    1、《种地吧第二季》2、《我的阿勒泰》3、《哈哈哈哈哈第四季》4、《幕府将军》5、《辐射》6、《惜花芷》7、《微暗之火》8、《金手指》9、《乘风2024》10、《歌手2024》(被大家说成五旬老太守国门。。。)11、《与凤行》12、《女高推理班第三季》13、《庆余年......
  • 【会议征稿,IEEE出版】第二届算法、图像处理与机器视觉国际学术会议(AIPMV2024,7月12-14)
    2024年镇江市计算机科学技术大会暨第二届算法、图像处理与机器视觉国际学术会议(AIPMV2024)将于2024年7月12日-14日在江苏镇江召开。会议主要围绕算法、图像与视觉处理等研究领域展开讨论,为从事算法、图像与视觉处理研究的专家学者、工程技术人员、技术研发人员提供一个分享......
  • 学习笔记14:模型保存
    转自:https://www.cnblogs.com/miraclepbc/p/14361926.html保存训练过程中使得测试集上准确率最高的参数importcopybest_model_wts=copy.deepcopy(model.state_dict())best_acc=0train_loss=[]train_acc=[]test_loss=[]test_acc=[]forepochinrange(extend......
  • OOP课程第二次blog—23201408—钱文浩
    本次blog,针对第4~6次大作业题目集进行总结,目的在于总结不足、得出经验教训以及做出未来规划。本次blog分为以下几个部分。一、前言:(1)第4次和第6次大作业难度较大,需要考虑的情况很复杂多样,而且对整体设计能力的要求很高,类间关系设计继承、依赖、关联等等,而且因为输入的数据很多,某......
  • Android14 WMS-窗口添加流程(二)-Server端
    Android14WMS-窗口添加流程(一)-Client端-CSDN博客本文接着上文"Android14WMS-窗口添加流程(一)-Client端"往下讲。也就是WindowManagerService#addWindow流程。目录一.WindowManagerService#addWindow标志1:mPolicy.checkAddPermission标志2:getDisplayContentOrCreate......
  • MySQL从入门到高级 --- 12.事务 && 13.锁机制 && 14.日志
    文章目录第十二章&&第十三章&&第十四章:12.事务12.1特性12.2隔离级别13.锁机制13.1各存储引擎对锁的支持状况:13.2锁特性13.3MyISAM表锁13.3.1加表锁13.4InnoDB行锁13.4.1行锁特点13.4.2行锁模式14.日志14.1错误日志14.2二进制日志14.2.1日志格式14.3......