惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
S
SegmentFault 最新的问题
L
LangChain Blog
Simon Willison's Weblog
Simon Willison's Weblog
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
WordPress大学
WordPress大学
M
MIT News - Artificial intelligence
A
About on SuperTechFans
Microsoft Security Blog
Microsoft Security Blog
I
Intezer
Know Your Adversary
Know Your Adversary
H
Heimdal Security Blog
博客园 - 叶小钗
B
Blog RSS Feed
F
Fortinet All Blogs
Hacker News: Ask HN
Hacker News: Ask HN
A
Arctic Wolf
小众软件
小众软件
Help Net Security
Help Net Security
MongoDB | Blog
MongoDB | Blog
aimingoo的专栏
aimingoo的专栏
G
Google Developers Blog
Forbes - Security
Forbes - Security
Latest news
Latest news
AI
AI
I
InfoQ
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
CXSECURITY Database RSS Feed - CXSecurity.com
W
WeLiveSecurity
C
Cybersecurity and Infrastructure Security Agency CISA
人人都是产品经理
人人都是产品经理
Cyberwarzone
Cyberwarzone
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
C
Cyber Attacks, Cyber Crime and Cyber Security
O
OpenAI News
博客园 - 【当耐特】
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
U
Unit 42
D
Darknet – Hacking Tools, Hacker News & Cyber Security
G
GRAHAM CLULEY
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
T
Threatpost
T
The Blog of Author Tim Ferriss
罗磊的独立博客

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes 控制器管理总结 Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Kubernetes - CRI 概述 Golang 编译速度为什么这么快? Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis 业务规则引擎演变过程简述 微服务中的熔断算法 漏桶算法和令牌桶算法 jsonparser 为什么比标准库的 encoding/json 快 10 倍 ? zap 高性能设计与实现 HTTP Router 算法演进 fastcache 高性能设计与实现 Web 常见的三个安全问题 ants Code Reading Go 线程安全 map 方案选型 布隆过滤器 死锁、活锁、饥饿、自旋锁 sync.Pool Code Reading Go 内存管理概述 Go netpoll Code Reading goroutine 泄漏与检测 time/Timer Code Reading GMP Scheduler Code Reading Go channel 的 15 条规则和底层实现 为什么 Linux “一切皆文件” context.Context Code Reading runtime/HACKING.md Goland 最佳实践 互联网开发与金庸武学 为什么 Redis 6.0 引入多线程模型? Kubernetes 应用最佳实践 - 金丝雀发布 容器中如何正确配置 GOMAXPROCS ? singleflight Code Reading sync.Map Code Reading sync.Cond Code Reading sync.WaitGroup Code Reading sync.RWMutex Code Reading sync.Mutex Code Reading sync.Once Code Reading Go 无锁编程 sync/atomic Code Reading goroutine 交替打印奇偶数 GODEBUG Go 并发模式 Go 汇编 Kubernetes 应用最佳实践 - 水平自动伸缩 Go 高性能 Tips fasthttp 为什么比标准库 net/http 快 10 倍 ? 技术文章配图指南 ChatGPT 初体验 Docker 网络原理概览 iptables 的五表五链 Kubernetes 应用最佳实践 - 亲和性和污点容忍度 Go 的反射与三大定律 Docker 官方提供的最佳实践 Go 语言内置的设计模式 HTTP1 到 HTTP3 的工程优化 Kubernetes 应用最佳实践 - Sidecar 模式 Kubernetes 应用最佳实践 - init 容器和钩子函数 为什么 recover 必须在 defer 中调用? 为什么 defer 的执行顺序和注册顺序不同? Go map 设计与实现 Go 切片扩容底层实现 Go 语言中的零拷贝 Go Delve 云原生和边缘计算简介 Kubernetes Pod 服务质量等级 Kubernetes 应用最佳实践 - 探针 Kubernetes 应用最佳实践 - 资源请求和限制 CDN 原理 Kubernetes 应用最佳实践 - 开篇 缓存策略和模式 Go 内存模型 Kubernetes 核心概念 软件版本语义化
UUID 通用技术选型
2023-04-17 · via 蛮荆

2023-04-17 算法 软件工程

概述

分布式唯一 ID 是指在分布式系统中生成的全局唯一标识符。在分布式系统中,由于多个节点同时操作数据可能会导致数据冲突或者重复,因此需要为每个数据对象赋予一个唯一的标识符,以便在系统范围内进行区分。

本文主要介绍 三种 常见类型的实现方案,并简要概述各个方案的优缺点,并在附录部分给出 Go 语言的几个开源组件,读者可以根据自己的业务场景进行技术选型。

1.完全依赖三方组件

ID 的生成规则和读写操作完全由第三方组件控制,例如常见的 MySQL 自增 ID, Redis Incr 序列号, MongoDB ObjectId 等。

下面对 MySQL, Redis, MongoDB 方案做一个简单的概括,读者了解即可 (因为生产环境中不会这么使用)。

方案 优点 缺点
MySQL 自增 ID 简单易维护,单表保证 ID 唯一性 性能较低,扩展性差,主从同步或切换时数据生成过程不可控,依赖于 MySQL 可用性
Redis 自增 ID 简单易维护,性能比数据库高,保证 ID 唯一性 扩展性差,需要做好对应的配置和应用层代码,依赖于 Redis 可用性
MongoDB 简单易维护,保证 ID 唯一性 扩展性差,存储空间占用多 (128 bit),依赖于 MongoDB 可用性

2.不完全依赖三方组件

ID 的生成规则有部分因子取决于数据源或配置信息,例如常见的 Snowflake 雪花算法。

Snowflake (雪花算法) 是一种生成分布式全局唯一 ID 的算法,生成的 ID 称为 Snowflake IDs 或 snowflakes。这种算法由 Twitter 创建, 并用于推文的 ID, Go 语言生态可以看看 这个组件

图片来源: https://atakde.medium.com/twitter-snowflake-approach-is-cool-3156f78017cb

bits 作用
1 未使用,保留
41 时间戳
10 服务器标识
12 序列号

Snowflake 算法的 ID 理论生成速度峰值为:

2^10 * 2^12 = 2^22 = 4194304/秒

实际应用中,可以进行具体的 bit 调整,例如可以将服务器标识中的一部分 bit 取出作为数据中心标识。

优点

  • 生成速度快,不依赖其他组件,独立生成
  • 高可用,不依赖于单点,每个服务器都可以独立生成 ID
  • ID 辨识度高,天然支持排序
  • 扩展性强

缺点

  • 时钟回拨 (很严重)
  • 能够表达的时间有限,最多 ≈ 70 年
  • 生成的 ID 可以根据时间往后推算和预测

时钟回拨是指在特定的情况下,系统时钟或者计算机的时间被意外地向后调整了一段时间,导致系统中某些时间相关的操作出现异常。

时钟回拨通常发生在网络时间同步出现故障或者手动修改系统时间的情况下,如果发生时钟回拨,整个 uuid 可能会出现重复,直接影响到一些和时间相关的关键程序的正确运行,比如金融交易、时间序列、安全协议等。 针对上述 Snowflake 算法存在的缺点和问题,百度开源了解决方案 UidGenerator

3.完全独立实现

ID 的生成规则由运行进程独立完成,不依赖任何第三方组件和配置信息,例如 UUID, GUID 等,本文以 UUID 为例分析下,对 GUID 感兴趣的读者,可以参考附录列表的 GUID 开源组件。

UUID 是通用唯一识别码(Universally Unique Identifier) 的缩写,开放软件基金会 (OSF) 规范定义了使用网卡、 MAC 地址、时间戳、命名空间(Namespace)、随机或伪随机数、序列号等元素来生成 UUID。

UUID 有 5 个版本,每个版本都有不同的生成规则:

  1. V1: 基于时间戳和 MAC 地址生成,MAC 地址包括网卡的物理地址和一个伪随机数
  2. V2: 将版本 V1 的时间戳前四位换为 POSIX 的 UID 或 GID,基本不使用
  3. V3: 基于命名空间和名称生成,使用 MD5 哈希算法,不推荐使用
  4. V4: 使用伪随机数完全随机生成,重复概率与随机数种子、生成器质量相关
  5. V5: 类似于版本 V3,使用 SHA-1 哈希算法代替 MD5

目前主流使用的是版本 4,Go 语言生态可以看看 这个组件

在 Linux 系统中,可以直接使用命令生成 uuid:

$ uuidgen

a6ba6a13-c5ee-4eef-a7d4-3410b1fc7098

也可以使用 这个网站 在线生成。

在线生成 UUID

优点

  • 生成速度快,不依赖其他组件,独立生成
  • 无序,避免按照时间顺序递增或递减 (当然这也可以被认为是一个缺点)
  • 扩展性强

缺点

  • 存储空间占用多 (128 bit) 以及写入时的性能较低
  • 可读性低,常见的业务场景需要二次转换 (例如邀请拉新活动需要根据二维码中的 UUID 找到对应的用户 ID)
  • 应用服务容器化后,主机名、网卡可能高度相似,提高了重复概率

小结

本文主要介绍了关于 分布式唯一 ID 三种实现方案以及各自的优缺点,综上所述,笔者比较推荐的方案是 Snowflake 算法,毕竟大多数服务还是运行在云服务商提供的基础设施上, 时钟回拨 这个问题基本可以被完全规避。最后,希望这篇文章可以帮助读者在做对应的技术选型时提供帮助。

附录

Reference