Leaf分布式ID

news2025/1/21 3:00:56

文章目录

  • 系统对Id号的要求
  • UUID
  • snowflake
  • Leaf
    • Leaf-snowflake
    • Leaf-segment
      • MySQL自增主键
      • segment
      • 双buffer

系统对Id号的要求

1、业务

1)全局唯一性:不能出现重复的ID号,既然是唯一标识,这是最基本的要求

2)趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能

3)单调递增:保证下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求

  • 数据自增id

4)信息安全:如果ID是连续的, 竞对在两天中午12点分别下单,通过订单id号相减就能大致计算出公司一天的订单量 。所以在一些应用场景下,会需要ID无规则

  • UUID或雪花算法

2、可靠性

  • 平均延迟和TP999延迟都要尽可能低
  • 可用性5个9
  • 高QPS

UUID

1、定义

36个字符,示例:550e8400-e29b-41d4-a716-446655440000

public class IdUtil {
	/*
	 * 返回使用ThreadLocalRandom的UUID,比默认的UUID性能更优
	 */
	public static UUID fastUUID() {
		ThreadLocalRandom random = ThreadLocalRandom.current();
		return new UUID(random.nextLong(), random.nextLong());
	}
}

2、缺点

  • 太长,不易于存储
  • 无序性,如果作为数据库主键,可能会引起数据页位置频繁变动,严重影响性能
  • 信息不安全,基于MAC地址生成UUID的算法可能会造成MAC地址泄露

snowflake

1、结构

Long型64位的整数,如图1所示
在这里插入图片描述

  • 41-bit的时间戳

    可以表示(1L<<41)/(1000L360024*365)=69年的时间

  • 10-bit 数据中心ID和机器

    5bit数据中心id,5bit机器id,一般使用ZK分配

  • 12个自增序列号

    在同一毫秒内生成2^12个唯一的ID

理论上snowflake方案的QPS约为409.6w/s,可以保证在任何一个IDC、任何一台机器、在任意毫秒内、生成的ID都是不同的

2、问题

41-bit时间戳部分,强依赖机器时钟,如果机器上时钟回拨,会导致发号重复

Leaf

使用参考:Leaf生成单据号

Leaf-snowflake

1、适合场景:生成的ID需要无规则

2、解决机器时钟回拨问题

1)要求当前时间戳,必须 > 机器创建时间

2)同时

  • 对比其余Leaf节点的系统时间,来判断自身系统时间是否准确
  • RPC请求得到所有节点的系统时间,计算sum(time)/nodeSize < 阈值,则认为正确

阈值 = 5ms

因为理论上5ms内无法,完全使用完成后12个自增序列号,所以不会重复

否则直接报错自动摘除本身节点并报警

Leaf-segment

1、适合场景:生成的ID单调递增

2、实现:基于MySQL的自增主键

MySQL自增主键

1、获取ID方式

使用下列SQL读写MySQL得到ID号

begin;
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
commit;
  • Tickets64:表
  • stub:列

实现方式类似:

useGeneratedKeys=“true“ keyProperty=“id“
  • int insert(XxxDO xxxDo)时,先将DO内容写入db
  • insert成功后,再将JDBC自增主键值AUTO_INCREMENT,回写到DO的id属性字段
  • 后续可能会从DO中获取此id值进行查询数据、编辑数据

2、存在问题

因为每次都是都需要写,读MySQL才能获取ID值,单台MySQL的读写性能是瓶颈

3、解决-集群

  • 在分布式系统中多部署几台机器

  • 每台机器设置不同的初始值,且步长和机器数相等

    比如有两台机器。设置步长step为2,TicketServer1的初始值为1(1,3,5,7,9,11…)

    TicketServer2的初始值为2(2,4,6,8,10…)

  • 假设部署N台机器,步长需设置为N,每台的初始值依次为0,1,2…N-1 ,则整个Leaf架构如图2
    在这里插入图片描述

4、存在问题

  • 数据库压力还是很大,每次获取ID都得读写一次数据库,只能靠堆机器来提高性能
  • 系统水平扩展比较困难,定义好了步长和机器台数之后,如果要添加机器不好做

5、解决- 批量分段(segment)获取


segment

1、实现,如图3所示

1)db表设计

+-------------+--------------+------+-----+-------------------+-------------------------
| Field       | Type         | Null | Key | Default           | Extra                     
+-------------+--------------+------+-----+-------------------+--------------------------
| biz_tag     | varchar(128) | NO   | PRI |                   |                           
| max_id      | bigint(20)   | NO   |     | 1                 |                           
| step        | int(11)      | NO   |     | NULL              |                           
| desc        | varchar(256) | YES  |     | NULL              |                           
| update_time | timestamp    | NO   |     | CURRENT_TIMESTAMP | on update 
  • biz_tag用来区分业务(外卖、支付)
  • max_id表示该biz_tag目前所被分配的ID号段的最大值
UPDATE table SET max_id=max_id+step WHERE biz_tag=xxx
  • step表示每次分配的号段长度

2)系统架构
在这里插入图片描述

3) ID值趋势递增

eg:test_tag业务

  • Leaf Server 1:从DB加载号段[1,1000]。
  • Leaf Server 2:从DB加载号段[1001,2000]。
  • Leaf Server 3:从DB加载号段[2001,3000]。

用户通过Round-robin的方式调用Leaf Server的各个服务,通过CAS获取ID,所以某一个Client获取到的ID序列

可能是:1,1001,2001,2,1002,2002……

也可能是:1,2,1001,2001,2002,2003,3,4…

当某个Leaf Server号段用完之后,下一次请求就会从DB中加载新的号段,这样保证了每次加载的号段是递增

2、解决-读写性能

  • 原来获取一个ID值,都需要读写一次数据库

  • 现在只需要把step设置得足够大,比如1000。那么只有当1000个号被消耗完了之后才会去重新读写一次

    读写数据库的频率从1减小到了1/step

  • test_tag业务,在第一台Leaf机器上是1~1000的号段,当这个号段用完时

  • 会去加载另一个长度为step=1000的号段

  • 假设另外两台号段都没有更新,这个时候第一台机器新加载的号段就应该是3001~4000

  • 同时数据库对应的biz_tag = test_tag 这条数据的max_id会从3000被更新成4000

3、 解决-扩容操作

只需要对biz_tag分库分表

4、问题

  • 在号段消耗完的时候进行取号段时,还是会夯在更新数据库的I/O上

  • 假如取DB的时候网络发生抖动,或者DB发生慢查询就会导致整个系统的响应时间变慢

5、解决-双buffer


双buffer

1、解决-双buffer

  • 当其中一个Buffer中的号段消费到某个点(90%)时,就启异步线程的把下一个号段加载到内存中的另一个Buffer

2、 容灾

分库分表

4、问题

  • 在号段消耗完的时候进行取号段时,还是会夯在更新数据库的I/O上

  • 假如取DB的时候网络发生抖动,或者DB发生慢查询就会导致整个系统的响应时间变慢

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

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

相关文章

使用LLM(Large Language Model)进行主题建模

随着互联网技术的快速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域取得了显著的进步。其中&#xff0c;大型语言模型&#xff08;LLM&#xff09;在文本生成任务中表现尤为抢眼。本文旨在探讨LLM在主题建模方面的优势&#xff0c;以及如何将其应用于文本生成任…

深度图进行运算检测物体表面粗糙度

文章目录 应用场景算法原理核心代码应用场景 不同程度凹凸的零件表面粗糙度对零件的磨损产生影响,很大程度上关系到产品性能和使用寿命。不同于单独使用的产品,零件需要在装配中与其他零件相连,密封性和磨损量是厂商需要考虑的一大加工要素;其次,产品外观和触感也会影响到…

数据结构链表2(常考习题1)(C语言)

移除链表元素&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 解题思路&#xff1a; 情况1&#xff1a; 情…

【vluhub】skywalking

SkyWalking是一个开源监控平台&#xff0c;用于从服务和云原生基础设施收集、分析、聚合和可视化数据 低版本存在sql注入漏洞 访问地址 http://192.168.203.12:8080/graphql burpsuite抓数据包 替换 {"query":"query queryLogs($condition: LogQueryConditi…

安装STM32开发工具:STM32CubeMX、STM32CubeIDE、STM32CubeCLT

ST官网地址&#xff1a;https://www.st.com/content/st_com/en.html ST官网因为链接原因下载会比较慢&#xff0c;推荐使用STMCU中文官网&#xff0c;下载很通畅&#xff1a;STMCU中文官网 安装Java 在安装STM32开发软件STM32CubeMX和STM32CubeIDE、STM32CubeCTL之前&#x…

浏览器事件循环详解

1. 浏览器的进程模型 1.1. 何为进程&#xff1f; 程序运行需要有它自己的专属内存空间&#xff0c;可以把这块内存空间简单的理解为进程。 每个应用至少有一个进程&#xff0c;进程之间相互独立&#xff0c;即使要通信&#xff0c;也需要双方同意。 1.2. 何为线程&#xff1f…

【Linux】进程间通信(3):共享内存

目录 一、共享内存概述 二、共享内存相关函数 1、shmget函数 2、ftok函数 3、shmctl函数 4、 shmat函数 5、 shdt函数 三、使用共享内存相关函数管理共享内存的一般过程 1. 生成唯一的键值 2. 创建或获取共享内存段 3. 连接到共享内存段 4. 操作共享内存 5. 断开…

2024 NVIDIA开发者社区夏令营环境配置指南(Win Mac)

2024 NVIDIA开发者社区夏令营环境配置指南(Win & Mac) 1 创建Python环境 首先需要安装Miniconda&#xff1a; 大家可以根据自己的网络情况从下面的地址下载&#xff1a; miniconda官网地址&#xff1a;https://docs.conda.io/en/latest/miniconda.html 清华大学镜像地…

对提高数据和指令缓存命中率方法的验证

对于如何写出让CPU跑得更快的代码这一问题&#xff0c;我看到了两种方法&#xff0c;分别是&#xff1a;1、提高数据缓存命中率&#xff1b;2、提高指令缓存命中率。 本文对这两种方法进行了简单的验证&#xff0c;并提供了示例代码。 本文基于2.3 如何写出让 CPU 跑得更快的代…

大规模深度学习推理引擎是什么?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 首先&#xff0c;我们来理解 “深度学习”&#xff1a;它是人工智能的一个重要分支&#xff0c;模仿人脑的神经网络结构&#xff0c;运用多层神经网络来学习和解析数据。这些神经网络能够从庞大的数据集…

二、版本更新与插件安装

版本更新 点击版本管理 点击刷新列表后点击一键更新&#xff0c;即可完成更新&#xff08;注意完成更新必须要关闭正在运行的服务&#xff09; 更新拓展&#xff08;更新插件&#xff09; 点击拓展-刷新列表-一键更新 即可 注意&#xff1a;操作完成以后必须重新启动方可生效…

(六)activiti-modeler 设计器属性编辑弹窗bug修复

BUG重现 在使用流程设计器时&#xff0c;经常碰到弹窗不小心关闭&#xff0c;比如不小心点击了灰色背景上&#xff0c;此时BUG就出现了。弹窗被关闭了&#xff0c;分配用户属性被置空了&#xff0c;以前有数据也被清空了&#xff0c;还无法再次点击弹窗编辑。 不仅仅是分配用…

deque和优先级队列

咱学完栈和队列之后&#xff0c;又了解到了vector和list&#xff0c;更深入的了解到了它们各自的优势&#xff0c;那么有没有可能结合它们的优点摒弃弱点呢&#xff0c;其实是有人这么试过的&#xff0c;不过咱还在学vector和list就证明他可能没成功&#xff0c;不过并不影响我…

python中类class的魔法方法

开始介绍之前&#xff0c;我们先看下之前文章我们介绍过的内置类merryview的一些方法&#xff0c;如下图所示&#xff1a; 有很多双下划线开始和结束的method&#xff0c;这么多method是做啥子用的呢&#xff1f; 其实这些方法就是我们常说的魔法方法&#xff0c;也是python中的…

【代码随想录】二分查找

文章为代码随想录的学习笔记&#xff0c;链接&#xff1a; 代码随想录 只要看到面试题中给出的数组是有序数组&#xff0c;都可以想一想是否可以使用二分法。 基本概念 二分查找要求线性表必须采用顺序存储结构&#xff0c;而且表中元素按关键字有序排列。‘ 查找过程&…

2024年华数杯数学建模竞赛——赛题浅析

本次华数杯与国赛同频【第一天下午六点发题&#xff0c;第四天下午八点收卷】&#xff0c;一共74小时。难度约为国赛的0.8&#xff0c;题量约为国赛的0.8-0.9.非常适合作为国赛前的练手赛。下面为大家带来本次华数杯的选题建议&#xff0c;希望对大家有所帮助。 一图流 选题人…

【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 卢小姐的字符串解压缩(100分) - 三语言AC题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-C/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,支持题…

36-38 关系数据库入门

关系数据库入门 关系数据库概述 数据持久化 - 将数据保存到能够长久保存数据的存储介质中&#xff0c;在掉电的情况下数据也不会丢失。 数据库发展史 - 网状数据库、层次数据库、关系数据库、NoSQL数据库。 1970年&#xff0c;IBM的研究员E.F.Codd在Communication of the ACM…

【Material-UI】Autocomplete中的禁用选项:Disabled options

文章目录 一、简介二、基本用法三、进阶用法1. 动态禁用2. 提示禁用原因3. 复杂的禁用条件 四、最佳实践1. 一致性2. 提供反馈3. 优化性能 五、总结 Material-UI的Autocomplete组件提供了丰富的功能&#xff0c;包括禁用特定选项的能力。这一特性对于限制用户选择、提供更好的用…

长短期记忆网络LSTM

目录 一、LSTM提出的背景&#xff1a;1.RNN存在的问题&#xff1a;2.LSTM的思想&#xff1a;2.1回顾GRU的提出&#xff1a;2.2LSTM在GRU上的改进&#xff1a; 二、遗忘门、输入门、输出门&#xff1a;三、LSTM网络架构&#xff1a;1.候选记忆单元C~t&#xff1a;2.遗忘门、输入…