76.Go分布式ID总览

文章目录

  • 简介
  • 一:UUID
  • 二、雪花算法
  • 三:Leaf-snowflake
  • 四:数据库自增ID
  • 五:使用Redis实现分布式ID生成
  • 六:使用数据库分段(Leaf-segment)
  • 七 :增强版Leaf-segment
  • 八:Tinyid
  • 九: 分布式键生成服务(如Zookeeper、etcd)

简介

在分布式系统中,生成唯一的ID是一个核心问题,特别是在需要确保数据完整性和避免冲突的场景中,比如作为链路追踪的trace_id,作为幂等性的主键id, 分布式锁中为了避免释放的是别人的锁时,本地保存的唯一id等。以下是对一些分布式唯一ID生成方法的详细阐述,包括它们的工作原理、优缺点,以及对网络依赖性的考量

一:UUID

实现原理

  • 工作方式:UUID是通过一系列算法生成的128位数字,通常基于时间戳、计算机硬件标识符、随机数等元素。

  • 全局唯一性:算法设计确保了即使在分布式系统中也能生成全局唯一的ID

优缺点

  • 优点:实现简单,无需网络交互,保证了ID的全球唯一性。

  • 缺点:通常不能保证顺序性,ID较长,可能导致存储和索引效率低下。

  • 网络依赖性:无网络依赖。

注意:工作中基本不使用uuid,这里是为了介绍分布式ID的完整性,以及UUID大家都熟知,所以一起介绍一下

uuid有两种包:

  • github.com/google/uuid,仅支持V1V4版本。

  • github.com/gofrs/uuid ,支持全部五个版本。

下面简单说下五种版本的区别:

Version 1,基于mac地址、时间戳。

Version 2,based on timestamp,MAC address and POSIX UID/GID (DCE 1.1)

Version 3,Hash获取入参并对结果进行MD5。

Version 4,纯随机数。

Version 5,based on SHA-1 hashing of a named value。

特点

  • 5个版本可供选择。

  • 定长36字节,偏长。

  • 无序。

package mianimport ("github.com/gofrs/uuid""fmt"
)func main() {// Version 1:时间+Mac地址id, err := uuid.NewV1()if err != nil {fmt.Printf("uuid NewUUID err:%+v", err)}// id: f0629b9a-0cee-11ed-8d44-784f435f60a4 length: 36fmt.Println("id:", id.String(), "length:", len(id.String()))// Version 4:是纯随机数,error会在内部报panicid, err = uuid.NewV4()if err != nil {fmt.Printf("uuid NewUUID err:%+v", err)}// id: 3b4d1268-9150-447c-a0b7-bbf8c271f6a7 length: 36fmt.Println("id:", id.String(), "length:", len(id.String()))
}

二、雪花算法

Twitter开发的一种生成64ID的服务,基于时间戳、节点ID和序列号。

实现原理

  • 工作方式:结合时间戳、工作机器的ID和序列号来生成64位的ID。时间戳保证了ID的唯一性和顺序性,工作机器ID保证了在多机环境下的唯一性。

  • 时间戳:确保ID按时间顺序增长。

优缺点

  • 优点:ID有时间顺序,长度适中,生成速度快。

  • 缺点:对系统时钟有依赖,时钟回拨会导致ID冲突。(时钟回拨:服务器上的时间突然倒退回之前的时间。可能是人为的调整时间;也可能是服务器之间的时间校对。)

  • 网络依赖性:通常无需网络交互,除非在多机器环境中同步机器ID

由于雪花算法工作中还是可能用到的,所以介绍更详细一些。

Snowflake的核心思想是:使用41bit作为毫秒数,10bit作为机器的ID5bit是数据中心(DC,机房)),5bit的机器ID(也可能是容器id)),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是01。这样可以确保每个ID都是唯一的。
图片

package mainimport("fmt""github.com/bwmarrin/snowflake"
)func main() {
// 参数为机器idnode, err := snowflake.NewNode(1)if err != nil {fmt.Println(err)return}id := node.Generate().String()    // id: 1552614118060462080 length: 19fmt.Println("id:", id, "length:", len(id))
}

三:Leaf-snowflake

时钟回拨

服务器上的时间突然倒退回之前的时间。可能是人为的调整时间;也可能是服务器之间的时间校对。

实现方案
在这里插入图片描述

Zookeeper顺序增、全局唯一的节点版本号,替换了原有的机器地址。解决了时钟回拨的问题。强依赖ZooKeeper、大流量下可能存在网络瓶颈。下图的方案在Leaf-snowflake 中通过缓存一个ZooKeeper文件夹,提高可用性。运行时,时差小于5ms会等待时差两倍时间,如果时差大于5ms报警并停止启动。

在这里插入图片描述

四:数据库自增ID

实现原理

  • 工作方式:基于中央数据库的序列生成器,如自增主键ID,每次请求时递增序列值。

  • 顺序性:保证了生成ID的顺序性和唯一性。

优缺点

  • 优点:简单可靠,保证顺序性。

  • 缺点:

    • 可能成为系统的单点故障,对数据库有较高的依赖。
    • 由于有序递增,易暴露业务量。受到数据库性能限制,对高并发场景不友好。
    • bigint最大是2^64-1,但是数据库单表肯定放不了这么多,那么就涉及到分表。
    • 如果业务量真的太大了,主键的自增id涨到头了,会发生什么?报错:主键冲突。
    • 网络依赖性:高度依赖网络,所有ID生成请求都需要访问中央数据库。

正是由于这众多缺点,所以工作中是不用它的,不过可以作为一种思路。

五:使用Redis实现分布式ID生成

Redis是一个高性能的键值数据库,它可以用于生成分布式唯一标识符。

实现原理

  • 利用Redis的原子操作:Redis提供了原子性的INCRINCRBY命令,可用于生成唯一的递增数值。这些数值可以作为唯一ID

  • 分布式环境中的应用:在分布式环境中,可以部署多个Redis实例。每个实例可以独立生成ID,或者通过配置不同的起始值和步长来确保ID的全局唯一性。

  • 高性能和可靠性:Redis的高性能确保了即使在高负载下也能快速生成ID,同时Redis的持久化和复制特性提高了系统的可靠性。

优缺点分析

  • 优点:快速、简单且易于扩展;支持高并发环境。

  • 缺点:依赖于外部服务(Redis),需要管理和维护额外的基础设施。

  • 网络依赖性:高度依赖网络。

六:使用数据库分段(Leaf-segment)

这种方法涉及到使用数据库来生成和管理ID段,以实现分布式ID的生成。

实现原理

  • ID段的分配:在数据库中预设一个起始ID和步长,每个应用实例或服务节点从数据库中获取一个ID段,然后在本地生成ID,直到该段用完再从数据库获取新的段。

  • 减少数据库交互:每个节点在消耗完一个ID段之前不需要与数据库交互,这减少了数据库的负载,并提高了ID生成的效率。

  • 避免冲突:通过确保每个节点获取的ID段不重叠,可以保证生成的ID在全系统范围内是唯一的。

优缺点分析

  • 优点:减少了对数据库的频繁访问,提高了性能;适合在分布式系统中使用。

  • 缺点:管理复杂性:管理不同的ID段需要额外的逻辑和数据库设计。可能的ID浪费:如果某个服务或实例在用完其ID段之前下线或重启,可能导致分配的ID未被完全使用。

  • 网络依赖性:对网络的依赖相对较低,只在申请新的ID段时需要访问数据库。

实际例子
把数据库自增主键换成了计数法。每个业务分配一个biz_tag、并记录各业务最大id(max_id)、号段跨度(step)等数据。这样每次取号只需要更新biz_tag对应的max_id,就可以拿到stepid。比如业务business_a当前max_id3000,取了1000个号在本地使用,使用完后,可以更新DB中对应的max_id4000,这样business_a本地就有1000个新的id可以用了

在这里插入图片描述

优点

  1. 除了拥有自增ID的优点之外,在性能上比自增ID更好,扩展灵活。
  2. 使用灵活、可配置性强。
  3. 缓存机制,突发状况下短时间内能保证服务正常运转。

缺点

  1. id是有序自增,容易暴露信息,不可用于订单。
  2. leaf的缓存ID用完再去获取新号段的间隙,性能会有波动。
  3. 强依赖DB

七 :增强版Leaf-segment

增强版是对上面描述的缺点2进行的改进——双cache。在leafID消耗到一定百分比时,常驻的后台进程会预先去号段服务获取新的号段并缓存。具体消耗百分比、及号段step根据业务消耗速度来定。

在这里插入图片描述

八:Tinyid

和增强版Leaf-segment类似,也是号段模式,提前加载号段。

在这里插入图片描述

九: 分布式键生成服务(如Zookeeper、etcd)

分布式协调服务在集群中生成唯一ID

ZooKeeper是使用了Znode结构中的Zxid实现顺序增IDZookeeper类似一个文件系统,每个节点都有唯一路径名(Znode),Zxid是个全局事务计数器,每个节点发生变化都会记录响应的版本(Zxid),这个版本号是全局唯一且顺序递增的。这种架构还是出现了ZooKeeper的单点问题。

实现原理

  • 工作方式:这些服务提供了分布式锁和原子性操作来生成唯一的ID

  • 协调机制:通过集群协调机制保证ID的唯一性和顺序性。

优缺点

  • 优点:提供了更加灵活和可控的ID生成方式,适合分布式环境。

  • 缺点:引入外部依赖,增加了系统的复杂性。

  • 网络依赖性:高度依赖网络,因为它们需要在多个节点之间协调ID的生成。

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

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

相关文章

Vue实现图片预览,侧边栏懒加载,不用任何插件,简单好用

实现样式 需求 实现PDF上传预览,并且不能下载 第一次实现:用vue-pdf,将上传的文件用base64传给前端展示 问题: 水印第一次加载有后面又没有了。当上传大的pdf文件后,前端获取和渲染又长又慢,甚至不能用 修…

Docker K8s-存储相关概念

Docker中的存储有两个概念:存储驱动程序Storage Driver和卷驱动程序Volumes Drivers。 存储驱动 Storage Driver 首先我们来看一下安装docker以后,docker的文件夹下面有哪些内容: cd /var/lib/docker && ll这里存储了所有的数据&a…

力扣hot100 轮转数组 一题多解 翻转数组

Problem: 189. 轮转数组 文章目录 思路复杂度Code 思路 👨‍🏫 参考 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( 1 ) O(1) O(1) Code class Solution {public void rotate(int[] nums, int k){int n nums.length;k k % n;reverse(…

Git搭建

文件格式 <VirtuaHost * 80> nginx </virtualHost> pache xml server {} nginx conf格式 [xx] 配置内容 代码开发中版本控制,项目代码编译构建,项目版本迭代全流程 命令300条 Hospital Information System 开发语言分类: 编译型: C nginx ma…

ArcEngine添加点要素、线要素、面要素及学习总结

基于C#的ArcEngine二次开发教程&#xff08;13&#xff09;&#xff1a;点、线、面要素的绘制_arcengine onmousedown-CSDN博客 https://www.cnblogs.com/cannel/p/11074343.html ArcEngine绘制点、线、多边形、矩形、圆形、椭圆的代码_arcengine 开发 生成矩形-CSDN博客 https…

DocsOpenApi自动化校验

一、背景 生产环境的文档中心的OpenApi和Kong服务配置的OpenApi可能存在不一致的情况&#xff0c;比如生产环境的文档中心有某个OpenApi&#xff0c;但是Kong服务没有配置到&#xff0c;那客户使用就会有问题。所以&#xff0c;前段时间&#xff08;M09版本&#xff09;花了4个…

MS7256C:L1 频段卫星导航射频前端低噪声放大器芯片

1、描述 MS7256C 是一款具有高增益、低噪声系数的低噪声放 大器&#xff08;LNA&#xff09;芯片&#xff0c;支持 L1 频段多模式全球卫星定位&#xff0c;可 以应用于 GPS、北斗二代、伽利略、Glonass 等 GNSS 导航 接收机中。芯片采用先进工艺制造&#xff0c;封装采用 1…

HDD的烦恼:HAMR会让SMR黯然失色吗?

HDD相关阅读参考&#xff1a; HDD回暖于2024&#xff0c;与SSD决战于2028 HDD最后的冲刺&#xff1a;大容量硬盘的奋力一搏 叠瓦式磁记录技术&#xff08;SMR&#xff09;自20世纪90年代起开始研究&#xff0c;于2010年后逐渐商业化应用于高密度硬盘。该技术的核心理念在于通…

从一个简单的Ping案例来分析二层,三层的数据包封装过程

1. 应用程序生成数据DATA&#xff0c;加上传输层报文头(TCP/UDP Head),调用网络层服务&#xff08;IP包头中的源地址由主机网卡直接得到&#xff0c;目的IP则由我们在使用应用程序时输入得到&#xff0c;如果是基于域名&#xff0c;调用一个通信过程DNS来获得目的IP&#xff0…

便捷接口调测:API 开发工具大比拼 | 开源专题 No.62

hoppscotch/hoppscotch Stars: 56.1k License: MIT Hoppscotch 是一个开源的 API 开发生态系统&#xff0c;主要功能包括发送请求和获取实时响应。该项目具有以下核心优势&#xff1a; 轻量级&#xff1a;采用简约的 UI 设计。快速&#xff1a;实时发送请求并获得响应。支持多…

独立站怎么建设对seo好?

现如今市面上就有不少开源的建站程序可供挑选&#xff0c;哪怕你不懂技术&#xff0c;不懂代码&#xff0c;也能建自己的独立站&#xff0c;效果比不少所谓的用自己技术开发的站都要好&#xff0c;本身做一个网站不难&#xff0c;但你做网站的目的是什么&#xff1f;是为了在搜…

【开源】基于JAVA语言的人事管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员功能模块2.2 普通员工功能模块2.3 答辩文案 三、系统展示四、核心代码4.1 查询职称4.2 新增留言回复4.3 工资申请4.4 工资审核4.5 员工请假 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的人…

Spring 声明式事务 @Transactional(详解)【面试重点,小林出品】

关于 Transactional 注解的基本使用&#xff0c;推荐看Spring 声明式事务 Transactional&#xff08;基本使用&#xff09; 概述 本篇博客主要学习 Transactional 注解当中的三个常⻅属性: 1. rollbackFor:异常回滚属性.指定能够触发事务回滚的异常类型.可以指定多个异常类型 …

AIGC是什么?GPT-4.0、DALL·E以及Midjourney等多种智能服务

AIGC&#xff08;人工智能生成内容&#xff0c;Artificial Intelligence Generated Content&#xff09;是指利用人工智能技术自动生成的文本、图像、音频和视频等内容。随着技术的进步&#xff0c;AIGC已经成为创意产业和内容创作领域的一股新兴力量。MidTool作为一款集成了多…

qml与C++的交互

qml端使用C对象类型、qml端调用C函数/c端调用qml端函数、qml端发信号-连接C端槽函数、C端发信号-连接qml端函数等。 代码资源下载&#xff1a; https://download.csdn.net/download/TianYanRen111/88779433 若无法下载&#xff0c;直接拷贝以下代码测试即可。 main.cpp #incl…

mmpose 2d姿态预测值转json文件

目录 效果图: 参考 模板文件下载地址: python预测代码: 效果图: <

51单片机ESP8266

一、MQTT透传AT固件 安信可提供的烧录WiFi固件工具&#xff1a; 链接: https://docs.ai-thinker.com/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B72 安信可提供的固件库链接: https://docs.ai-thinker.com/%E5%9B%BA%E4%BB%B6%E6%B1%87%E6%80%BB 经过测试&#xff0c;选择这个不可以…

Zephyr 源码调试

背景 调试环境对于学习源码非常重要&#xff0c;但嵌入式系统的调试环境搭建稍微有点复杂&#xff0c;需要的条件略多。本文章介绍如何在 Zephyr 提供的 qemu 上调试 Zephyr 源码&#xff0c;为后续分析 Zephyr OS 相关原理做铺垫。 环境 我的开发环境为 wsl ubuntu&#xf…

Redis 击穿、穿透、雪崩产生原因解决思路

大家都知道&#xff0c;计算机的瓶颈之一就是IO&#xff0c;为了解决内存与磁盘速度不匹配的问题&#xff0c;产生了缓存&#xff0c;将一些热点数据放在内存中&#xff0c;随用随取&#xff0c;降低连接到数据库的请求链接,避免数据库挂掉。需要注意的是&#xff0c;无论是击穿…

逻辑回归中的损失函数梯度下降

一、引言 逻辑回归中的损失函数通常采用的是交叉熵损失函数&#xff08;cross-entropy loss function&#xff09;。在逻辑回归中&#xff0c;我们通常使用sigmoid函数将线性模型的输出转换为概率值&#xff0c;然后将这些概率值与实际标签进行比较&#xff0c;从而计算损失。 …