谈谈常用的分布式ID的设计方案?

典型回答

首先,我们需要明确通常的分布式ID定义,基本的要求包括:

  • 全局唯一,区别于单点系统的唯一,全局是要求分布式系统内唯一。

  • 有序性,通常都需要保证生成的ID是有序递增的。例如,在数据库存储等场景中,有序ID便于确定数据位置,往往更加高效。

目前业界的方案很多,典型方案包括:

  • 基于数据库自增序列的实现。这种方式优缺点都非常明显,好处是简单易用,但是在扩展性和可靠性等方面存在局限性。

  • 基于Twitter早期开源的Snowflake的实现,以及相关改动方案。这是目前应用相对比较广泛的一种方式,其结构定义你可以参考下面的示意图。

  • 在这里插入图片描述整体长度通常是64 (1 + 41 + 10+ 12 = 64)位,适合使用Java语言中的long类型来存储。

头部是1位的正负标识位。

紧跟着的高位部分包含41位时间戳,通常使用System.currentTimeMillis()。

后面是10位的WorkerID,标准定义是5位数据中心 + 5位机器ID,组成了机器编号,以区分不同的集群节点。

最后的12位就是单位毫秒内可生成的序列号数目的理论极限。
Snowflake的官方版本是基于Scala语言,Java等其他语言的参考实现有很多,是一种非常简单实用的方式,具体位数的定义是可以根据分布式系统的真实场景进行修改的,并不一定要严格按照示意图中的设计。

  • Redis、ZooKeeper、MongoDB等中间件,也都有各种唯一ID解决方案。其中一些设计也可以算作是Snowflake方案的变种。例如,MongoDB的ObjectId提供了一个12 byte(96位)的ID定义,其中32位用于记录以秒为单位的时间,机器ID则为24位,16位用作进程ID,24位随机起始的计数序列。

  • 国内的一些大厂开源了其自身的部分分布式ID实现,InfoQ就曾经介绍过微信的seqsvr,它采取了相对复杂的两层架构,并根据社交应用的数据特点进行了针对性设计,具体请参考相关代码实现。另外,百度、美团等也都有开源或者分享了不同的分布式ID实现,都可以进行参考。

考点分析

涉及分布式,很多单机模式下的简单问题突然就变得复杂了,这是分布式天然的复杂性,需要从不同角度去理解适用场景、架构和细节算法,我会从下面的角度进行适当解读:

  • 我们的业务到底需要什么样的分布式ID,除了唯一和有序,还有哪些必须要考虑的要素?

  • 在实际场景中,针对典型的方案,有哪些可能的局限性或者问题,可以采取什么办法解决呢?

知识扩展

如果试图深入回答这个问题,首先需要明确业务场景的需求要点,我们到底需要一个什么样的分布式ID?

需求要点

除了唯一和有序,考虑到分布式系统的功能需要,通常还会额外希望分布式ID保证:

  • 有意义,或者说包含更多信息,例如时间、业务等信息。这一点和有序性要求存在一定关联,如果ID中包含时间,本身就能保证一定程度的有序,虽然并不能绝对保证。ID中包含额外信息,在分布式数据存储等场合中,有助于进一步优化数据访问的效率。

  • 高可用性,这是分布式系统的必然要求。前面谈到的方案中,有的是真正意义上的分布式,有得还是传统主从的思路,这一点没有绝对的对错,取决于我们业务对扩展性、性能等方面的要求。

  • 紧凑性,ID的大小可能受到实际应用的制约,例如数据库存储往往对长ID不友好,太长的ID会降低MySQL等数据库索引的性能;编程语言在处理时也可能受数据类型长度限制。

在具体的生产环境中,还有可能提出对QPS等方面的具体要求,尤其是在国内一线互联网公司的业务规模下,更是需要考虑峰值业务场景的数量级层次需求。

主流方案的优缺点分析

对于数据库自增方案,除了实现简单,它生成的ID还能够保证固定步长的递增,使用很方便。

但是,因为每获取一个ID就会触发数据库的写请求,是一个代价高昂的操作,构建高扩展性、高性能解决方案比较复杂,性能上限明显,更不要谈扩容等场景的难度了。与此同时,保证数据库方案的高可用性也存在挑战,数据库可能发生宕机,即使采取主从热备等各种措施,也可能出现ID重复等问题。

实际大厂商往往是构建了多层的复合架构,例如美团公开的数据库方案Leaf-Segment,引入了起到缓存等作用的Leaf层,对数据库操作则是通过数据库中间件提供的批量操作,这样既能保证性能、扩展性,也能保证高可用。但是,这种方案对基础架构层面的要求很多,未必适合普通业务规模的需求。

与其相比,Snowflake方案的好处是算法简单,依赖也非常少,生成的序列可预测,性能也非常好,比如Twitter的峰值超过10万/s。

但是,它也存在一定的不足,例如:

  • 时钟偏斜问题(Clock Skew)。我们知道普通的计算机系统时钟并不能保证长久的一致性,可能发生时钟回拨等问题,这就会导致时间戳不准确,进而产生重复ID。
    针对这一点,Twitter曾经在文档中建议开启NTP,毕竟Snowflake对时间存在依赖,但是也有人提议关闭NTP。我个人认为还是应该开启NTP,只是可以考虑将stepback设置为0,以禁止回调。
    从设计和具体编码的角度,还有一个很有效的措施就是缓存历史时间戳,然后在序列生成之前进行检验,如果出现当前时间落后于历史时间的不合理情况,可以采取相应的动作,要么重试、等待时钟重新一致,或者就直接提示服务不可用。

  • 另外,序列号的可预测性是把双刃剑,虽然简化了一些工程问题,但很多业务场景并不适合可预测的ID。如果你用它作为安全令牌之类,则是非常危险的,很容易被黑客猜测并利用。

  • ID设计阶段需要谨慎考虑暴露出的信息。例如,Erlang版本的flake实现基于MAC地址计算WorkerID,在安全敏感的领域往往是不可以这样使用的

  • 从理论上来说,类似Snowflake的方案由于时间数据位数的限制,存在与2038年问题相似的理论极限。虽然目前的系统设计考虑数十年后的问题还太早,但是理解这些可能的极限是有必要的,也许会成为面试的过程中的考察点

如果更加深入到时钟和分布式系统时序的问题,还有与分布式ID相关但又有所区别的问题,比如在分布式系统中,不同机器的时间很可能是不一致的,如何保证事件的有序性?Lamport在1978年的论文(Time, Clocks, and the Ording of Events in a Distributed System)中就有很深入的阐述,有兴趣的同学可以去查找相应的翻译和解读。

最后,再补充一些当前分布式领域的面试热点,例如:

分布式事务,包括其产生原因、业务背景、主流的解决方案等。

理解CAP、BASE等理论,懂得从最终一致性等角度来思考问题,理解Paxos、Raft等一致性算法。

理解典型的分布式锁实现,例如最常见的Redis分布式锁。

负载均衡等分布式领域的典型算法,至少要了解主要方案的原理。

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

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

相关文章

iframe 与主应用页面之间如何互相通信传递数据

背景 当我们的Web页面需要复用现有网站的页面时,我们通常会考虑代码层面的抽离引用,但是对于一些过于复杂的页面,通过 iframe 嵌套现有的网站页面也是一种不错的方式,。目前我就职的项目组就有多个业务利用 iframe 完成业务的复用…

springboot整合websocket实现控制输入流

WebSocket 是一种在客户端和服务器之间进行实时双向通信的协议。它提供了一种更高效、更可靠的替代方案,以替代传统的HTTP请求-响应模式。 WebSocket 的特点包括: 双向通信:客户端和服务器可以同时发送和接收消息,而不像HTTP一样需…

QT 基础篇

目录 QPushButton QT帮助文档 QT 对象树 QPushButton QPushButton是Qt图形界面控件中的一种,看英文的意思,他就是按钮,是最基本的图形控件之一。在我们的最基本的项目中,运行: 是一个空白的窗体,里面什么也没有&am…

云原生之深入解析如何在Kubernetes中快速启用Cgroup V2支持

一、cgroup v2 有哪些优势? Linux 中有两个 cgroup 版本:cgroup v1 和 cgroup v2。cgroup v2 是新一代的 cgroup API。Kubernetes 自 v1.25 起 cgroup2 特性正式 stable。cgroup v2 提供了一个具有增强资源管理能力的统一控制系统,cgroup v2…

在Node.js中使用MongoDB连接数据库、创建集合

本文主要介绍在Node.js中使用MongoDB连接数据库、创建集合的方法。 目录 连接数据库使用原生驱动程序连接MongoDB数据库使用Mongoose连接MongoDB数据库 创建集合使用mongodb驱动程序 连接数据库 在Node.js中使用MongoDB连接数据库有两种方式:使用原生驱动程序和使用…

静态HTTP应用的性能优化技巧

在Web开发中,静态HTTP应用以其简单、快速和安全的特点受到了广泛欢迎。然而,随着Web应用的规模不断扩大,性能问题也日益突出。本文将为你介绍一些静态HTTP应用的性能优化技巧,让你的应用飞得更快、更稳定。 一、压缩文件 文件压…

以pycharm为例,生成Python项目所需要的依赖库/包文档:requirements.txt

平时我们在编写或者使用别人的Python项目时,往往会看到一个文档requirements.txt,该文档是描述一个Python项目中的第三方库的名称以及版本。本文介绍导出python当前项目依赖包requirements.txt的操作步骤。 方法一:如果每个项目有对应的虚拟…

Sumdiv

title: Sumdiv date: 2023-12-12 21:45:09 tags: 分治 categories: 算法进阶指南 题目大意 求 A B A^B AB 的所有约数之和 m o d mod mod 9901 9901 9901( 1 1 1 ≤ \leq ≤ A , B A,B A,B ≤ \leq ≤ 5 ∗ 1 0 7 5 * 10 ^ 7 5∗107) 解题思路 将 A A A 分解质因数&…

4-Docker命令之docker export

1.docker export介绍 docker export命令是用来将docker容器中的文件系统导出为一个tar归档文件 2.docker export用法 docker export [参数] container [rootcentos79 ~]# docker export --helpUsage: docker export [OPTIONS] CONTAINERExport a containers filesystem a…

开源工业以太网现场总线协议栈汇总

开源现场总线协议栈 EtherNet/IP、EtherCAT master、Profinet开源汇总: EtherNet/IP:https://github.com/EIPStackGroup/OpENer EtherCAT master:https://gitlab.com/etherlab.org/ethercat EtherCAT master:https://github.com/OpenEtherCATsociety/soem http…

【C++】哈希表

文章目录 哈希概念哈希冲突哈希函数哈希表闭散列开散列 开散列与闭散列比较 正文开始前给大家推荐个网站,前些天发现了一个巨牛的 人工智能学习网站, 通俗易懂,风趣幽默,忍不住分享一下给大家。 点击跳转到网站。 哈希概念 顺…

PHP基础 - 数据类型

数据类型 序号数据类型描述1字符串(String)用于表示文本数据2整型(Integer)用于表示整数数据3浮点型(Float)用于表示带有小数部分的数值4布尔型(Boolean)用于表示真或假两个状态5数组(Array)用于存储多个值的有序集合6对象类型(Object)用于表示自定义的复杂数据结构…

CPython(将Python编译为so)

环境 先配一下环境,我使用的是python3.8.5 pip install Cython 编译过程 我们准备一个要编译的文件 test.py def xor(input_string): output_string "" for char in input_string: output_string chr(ord(char) ^ 0x66) return output_string…

Redis - 事务隔离机制

Redis 的事务的本质是 一组命令的批处理 。这组命令在执行过程中会被顺序地、一次性 全部执行完毕,只要没有出现语法错误,这组命令在执行期间是不会被中断。 当事务中的命令出现语法错误时,整个事务在 exec 执行时会被取消。 如果事务中的…

C++入门【7-C++ 存储类】

C 存储类 存储类定义 C 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前。下面列出 C 程序中可用的存储类: autoregisterstaticexternmutablethread_local (C11) 从 C 17 开始,auto 关键字不再…

PyTorch深度学习实战(25)——自编码器

PyTorch深度学习实战(25)——自编码器 0. 前言1. 自编码器2. 使用 PyTorch 实现自编码器小结系列链接 0. 前言 自编码器 (Autoencoder) 是一种无监督学习的神经网络模型,用于数据的特征提取和降维,它由一个编码器 (Encoder) 和一…

20分钟部署ChatGLM3-6B

准备工作 1.下载源代码: https://github.com/THUDM/ChatGLM3 2.下载预训练模型: https://modelscope.cn/models/ZhipuAI/chatglm3-6b/files 可以创建一个py文件,直接使用如下代码下载到本地: from modelscope.hub.snapshot_dow…

python实现形态学建筑物指数MBI提取建筑物及数据获取

前言 形态学建筑物指数MBI通过建立建筑物的隐式特征和形态学算子之间的关系进行建筑物的提取[1]。 原理 上图源自[2]。 实验数据 简单找了一张小图片: test.jpg 代码 为了支持遥感图像,读写数据函数都是利用GDAL写的。 import numpy as np import …

重建大师里能不能用kml圈出一块出来空三?

答:这个功能暂时还没有,可以先空三,然后导入范围kml去进行重建。 重建大师是一款专为超大规模实景三维数据生产而设计的集群并行处理软件,输入倾斜照片,激光点云,POS信息及像控点,输出高精度彩色…

LNMP网站架构分布式搭建部署

1. 数据库的编译安装 1. 安装软件包 2. 安装所需要环境依赖包 3. 解压缩到软件解压缩目录,使用cmake进行编译安装以及模块选项配置(预计等待20分钟左右),再编译及安装 4. 创建mysql用户 5. 修改mysql配置文件,删除…