Apache Seata基于改良版雪花算法的分布式UUID生成器分析2


title: 关于新版雪花算法的答疑
author: selfishlover
keywords: [Seata, snowflake, UUID, page split]
date: 2021/06/21

本文来自 Apache Seata官方文档,欢迎访问官网,查看更多深度文章。

关于新版雪花算法的答疑

在上一篇关于新版雪花算法的解析中,我们提到新版算法所做出的2点改变:

  1. 时间戳不再时刻追随系统时钟。
  2. 节点ID和时间戳互换位置。由原版的:
    在这里插入图片描述

改成:在这里插入图片描述

有细心的同学提出了一个问题:新版算法在单节点内部确实是单调递增的,但是在多实例部署时,它就不再是全局单调递增了啊!因为显而易见,节点ID排在高位,那么节点ID大的,生成的ID一定大于节点ID小的,不管时间上谁先谁后。而原版算法,时间戳在高位,并且始终追随系统时钟,可以保证早生成的ID小于晚生成的ID,只有当2个节点恰好在同一时间戳生成ID时,2个ID的大小才由节点ID决定。这样看来,新版算法是不是错的?

这是一个很好的问题!能提出这个问题的同学,说明已经深入思考了标准版雪花算法和新版雪花算法的本质区别,这点值得鼓励!在这里,我们先说结论:新版算法的确不具备全局的单调递增性,但这不影响我们的初衷(减少数据库的页分裂)。这个结论看起来有点违反直觉,但可以被证明。

在证明之前,我们先简单回顾一下数据库关于页分裂的知识。以经典的mysql innodb为例,innodb使用B+树索引,其中,主键索引的叶子节点还保存了数据行的完整记录,叶子节点之间以双向链表的形式串联起来。叶子节点的物理存储形式为数据页,一个数据页内最多可以存储N条行记录(N与行的大小成反比)。如图所示:
在这里插入图片描述

B+树的特性要求,左边的节点应小于右边的节点。如果此时要插入一条ID为25的记录,会怎样呢(假设每个数据页只够存放4条记录)?答案是会引起页分裂,如图:
在这里插入图片描述

页分裂是IO不友好的,需要新建数据页,拷贝转移旧数据页的部分记录等,我们应尽量避免。

理想的情况下,主键ID最好是顺序递增的(例如把主键设置为auto_increment),这样就只会在当前数据页放满了的时候,才需要新建下一页,双向链表永远是顺序尾部增长的,不会有中间的节点发生分裂的情况。

最糟糕的情况下,主键ID是随机无序生成的(例如java中一个UUID字符串),这种情况下,新插入的记录会随机分配到任何一个数据页,如果该页已满,就会触发页分裂。

如果主键ID由标准版雪花算法生成,最好的情况下,是每个时间戳内只有一个节点在生成ID,这时候算法的效果等同于理想情况的顺序递增,即跟auto_increment无差。最坏的情况下,是每个时间戳内所有节点都在生成ID,这时候算法的效果接近于无序(但仍比UUID的完全无序要好得多,因为workerId只有10位决定了最多只有1024个节点)。实际生产中,算法的效果取决于业务流量,并发度越低,算法越接近理想情况。

那么,换成新版算法又会如何呢?
新版算法从全局角度来看,ID是无序的,但对于每一个workerId,它生成的ID都是严格单调递增的,又因为workerId是有限的,所以最多可划分出1024个子序列,每个子序列都是单调递增的。
对于数据库而言,也许它初期接收的ID都是无序的,来自各个子序列的ID都混在一起,就像这样:
在这里插入图片描述

如果这时候来了个worker1-seq2,显然会造成页分裂:
在这里插入图片描述

但分裂之后,有趣的事情发生了,对于worker1而言,后续的seq3,seq4不会再造成页分裂(因为还装得下),seq5也只需要像顺序增长那样新建页进行链接(区别是这个新页不是在双向链表的尾部)。注意,worker1的后续ID,不会排到worker2及之后的任意节点(因而不会造成后边节点的页分裂),因为它们总比worker2的ID小;也不会排到worker1当前节点的前边(因而不会造成前边节点的页分裂),因为worker1的子序列总是单调递增的。在这里,我们称worker1这样的子序列达到了稳态,意为这条子序列已经"稳定"了,它的后续增长只会出现在子序列的尾部,而不会造成其它节点的页分裂。

同样的事情,可以推广到各个子序列上。无论前期数据库接收到的ID有多乱,经过有限次的页分裂后,双向链表总能达到这样一个稳定的终态:
在这里插入图片描述

到达终态后,后续的ID只会在该ID所属的子序列上进行顺序增长,而不会造成页分裂。该状态下的顺序增长与auto_increment的顺序增长的区别是,前者有1024个增长位点(各个子序列的尾部),后者只有尾部一个。

到这里,我们可以回答开头所提出的问题了:新算法从全局来看的确不是全局递增的,但该算法是收敛的,达到稳态后,新算法同样能达成像全局顺序递增一样的效果。


扩展思考

以上只提到了序列不停增长的情况,而实践生产中,不光有新数据的插入,也有旧数据的删除。而数据的删除有可能会导致页合并(innodb若发现相邻2个数据页的空间利用率都不到50%,就会把它俩合并),这对新算法的影响如何呢?

经过上面的流程,我们可以发现,新算法的本质是利用前期的页分裂,把不同的子序列逐渐分离开来,让算法不断收敛到稳态。而页合并则恰好相反,它有可能会把不同的子序列又合并回同一个数据页里,妨碍算法的收敛。尤其是在收敛的前期,频繁的页合并甚至可以让算法永远无法收敛(你刚分离出来我就又把它们合并回去,一夜回到解放前~)!但在收敛之后,只有在各个子序列的尾节点进行的页合并,才有可能破坏稳态(一个子序列的尾节点和下一个子序列的头节点进行合并)。而在子序列其余节点上的页合并,不影响稳态,因为子序列仍然是有序的,只不过长度变短了而已。

以seata的服务端为例,服务端那3张表的数据的生命周期都是比较短的,一个全局事务结束之后,它们就会被清除了,这对于新算法是不友好的,没有给时间它进行收敛。不过已经有延迟删除的PR在review中,搭配这个PR,效果会好很多。比如定期每周清理一次,前期就有足够的时间给算法进行收敛,其余的大部分时间,数据库就能从中受益了。到期清理时,最坏的结果也不过是表被清空,算法从头再来。

如果您希望把新算法应用到业务系统当中,请务必确保算法有时间进行收敛。比如用户表之类的,数据本就打算长期保存的,算法可以自然收敛。或者也做了延迟删除的机制,给算法足够的时间进行收敛。

如果您有更好的意见和建议,也欢迎跟seata社区联系!

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

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

相关文章

C++初阶学习第四弹——类与对象(中)——刨析类与对象的核心点

类与对象(上):C初阶学习第三弹——类与对象(上)——初始类与对象-CSDN博客 前言: 在前面文章中,我们已经讲了类与对象的思想和类与对象的一些基本操作,接下来这篇文章我们将讲解以下…

探索Jellyfin:支持Android的自由开源的媒体服务器平台

探索Jellyfin:支持Android的自由开源的媒体服务器平台 I. 简介 A. 什么是Jellyfin? Jellyfin是一个自由开源的媒体服务器平台,旨在让用户能够自主管理和流式传输他们的媒体内容。与许多闭源的商业媒体服务器解决方案不同,Jelly…

Matlab各个版本介绍、区别分析及推荐

MATLAB,由美国MathWorks公司出品,是一款广泛应用的商业数学软件。自其诞生之初,MATLAB便以其强大的矩阵计算能力、灵活的编程环境以及广泛的应用领域,赢得了全球科研工作者和工程师的青睐。本文将详细介绍MATLAB的各个版本&#x…

ubuntu neo4j 下载与配置(一)

neo4j 官方下载页面 https://neo4j.com/deployment-center/#community 进入页面之后,往下滑 咱们在下载neo4j时,官方可能要咱们填写一下个人信息,比如:姓名组织结构邮箱等: 咱们可以观察一下,ne4j的下载链…

uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之编写语音播放安卓插件

前言 如果你不会编写安卓插件,你可以先看看我之前零基础的文章(uniapp0基础编写安卓原生插件和调用第三方jar包和编写语音播报插件之零基础编写安卓插件), 我们使用android.speech.tts.TextToSpeech进行编写语言播放插件 开始 uniapp <template><view style=&q…

烟雾识别图像处理方法详解---豌豆云

本文详细介绍了烟雾识别图像处理方法的原理、流程和应用场景&#xff0c;帮助读者理解并掌握这一技术&#xff0c;为实际应用提供指导。 随着科技的不断发展&#xff0c;图像处理技术在各个领域得到了广泛应用。 其中&#xff0c;烟雾识别图像处理方法作为一种重要的技术手段…

如何下载钉钉群直播回放:完整步骤解析

在当今快节奏的商业和教育环境中&#xff0c;钉钉群直播已经成为了沟通和学习的重要工具。直播结束后&#xff0c;很多观众都希望回顾内容&#xff0c;但却不知如何开始。如果你错过了实时直播&#xff0c;或者只是想再次观看精彩的演讲和讨论&#xff0c;那么下载钉钉群直播回…

基于ESP32—CAM物联网WIFI小车

一.功能概述 摄像头的画面可以实时的传输到&#xff0c;点灯科技APP的手机端&#xff0c;这样可以实时查看周围环境的状况&#xff0c;灯光不足&#xff0c;画面不清晰时可以打开灯光照明。手机端有左转、右转、前进、后退、停止的按钮。可以根据自己需要&#xff0c;来控制小车…

GitHub Copilot申请和使用

GitHub Copilot申请和使用 文章目录 前言一、申请二、使用总结 前言 之前已经成功进行了Github学生认证&#xff0c;今天邮件通知之前的学生认证已经通过。那么就去进行GitHub Copilot申请和使用。 前面准备&#xff1a;Github学生认证 一、申请 进入github的settings&#x…

git branch与tag操作

1 git新建本地分支并推送到远程 新建本地分支&#xff0c;并切换到新分支上 git checkout -b 新分支名新建一个远程分支&#xff0c;名字一样 git push origin 新分支名:新分支名将本地分支和远程分支合并关联 git push --set-upstream origin 新分支名2 使用Git添加Tag 2…

Eclipse:-Dmaven.multiModuleProjectDirectory system propery is not set.

eclipse中使用maven插件的时候&#xff0c;运行run as maven build的时候报错 -Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable and mvn script match. 可以设一个环境变量M2_HOME指向你的maven安装目录 M2_HOMED:\Apps\…

Deckset for Mac激活版:MD文档转幻灯片软件

Deckset for Mac是一款专为Mac用户打造的Markdown文档转幻灯片软件。它凭借简洁直观的界面和强大的功能&#xff0c;成为许多用户的心头好。 Deckset for Mac激活版下载 Deckset支持Markdown语法&#xff0c;让用户在编辑文档时无需分心于复杂的格式设置&#xff0c;只需专注于…

【Jenkins】持续集成与交付 (九):Maven安装和配置、以及构建项目

🟣【Jenkins】持续集成与交付 (九):Maven安装和配置、以及构建项目 一、Maven简介二、持续集成环境安装Maven2.1 Maven软件包上传2.2 配置环境变量2.3 Jenkins配置关联JDK和Maven2.4 添加Jenkins全局变量2.5 修改Maven的settings.xml2.6 全局工具配置--设置自己的setting.…

【docker 】Windows10安装 Docker

安装 Hyper-V Hyper-V 是微软开发的虚拟机&#xff0c;仅适用于 Windows 10。 按键&#xff1a; win键X &#xff0c;选着程序和功能 在查找设置中输入&#xff1a;启用或关闭Windows功能 选中Hyper-V 点击确定 安装 Docker Desktop for Windows Docker Desktop 官方下载…

2024年 Java 面试八股文——Redis篇

目录 1、介绍下Redis Redis有哪些数据类型 难度系数&#xff1a;⭐ 2、Redis提供了哪几种持久化方式 难度系数&#xff1a;⭐ 3、Redis为什么快 难度系数&#xff1a;⭐ 4、Redis为什么是单线程的 难度系数&#xff1a;⭐ 5、Redis服务器的的内存是多大…

pkpmbs 建设工程质量监督系统 Ajax_operaFile.aspx 文件读取漏洞复现

0x01 产品简介 pkpmbs 建设工程质量监督系统是湖南建研信息技术股份有限公司一个与工程质量检测管理系统相结合的,B/S架构的检测信息监管系统。 0x02 漏洞概述 pkpmbs 建设工程质量监督系统 Ajax_operaFile.aspx接口处存在文件读取漏洞,未经身份认证的攻击者可以利用漏洞读…

RSA实现中弱密钥漏洞分析

RSA实现中弱密钥漏洞分析 “Analyzing Weak Key Vulnerabilities in RSA Implementation” 完整下载链接:RSA实现中弱密钥漏洞分析 文章目录 RSA实现中弱密钥漏洞分析摘要第一章 引言1.1 研究背景1.2 研究目的1.3 研究意义 第二章 RSA算法基础2.1 RSA算法原理2.2 RSA密钥生成…

Java基础知识总结(80)

CLH释放锁的过程 线程A执行完临界区代码后开始unlock&#xff08;释放&#xff09;操作&#xff0c;设置nodeA的前驱引用为null(方便垃圾回收器回收)&#xff0c;锁状态locked为false。 线程B执行抢到锁并且完成临界区代码的执行后&#xff0c;开始unlock&#xff08;释放&am…

LVS/DR工作模式介绍及配置

1.1 LVS/DR模式介绍 双地址配置&#xff1a;所有真实服务器&#xff08;RS&#xff09;都需要配置两个IP地址&#xff1a;一个是真实服务器的IP地址&#xff08;RIP&#xff09;&#xff0c;另一个是虚拟服务器的IP地址&#xff08;VIP&#xff09;&#xff0c;后者与LVS上的VI…

助力企业部署国产云原生数据库 XSKY星辰天合与云猿生完成产品互兼容认证

近日&#xff0c;北京星辰天合科技股份有限公司&#xff08;简称&#xff1a;XSKY 星辰天合&#xff09;与杭州云猿生数据有限公司&#xff08;简称“云猿生”&#xff09;完成了产品互兼容认证&#xff0c;星辰天合企业级分布式统一数据平台 XEDP 与云猿生的开源数据库管控平台…