一、UUID(通用唯一识别码)#
-
- UUID 是一种由数字和字母组成的 128 位标识符。它通过一定的算法生成,通常基于时间戳、MAC 地址(网卡物理地址)等信息。最常用的 UUID 版本是基于随机数生成的版本 4,其生成的 ID 具有全球唯一性。
-
- 唯一性高:在全球范围内几乎不可能出现重复的 ID,适合用于分布式系统中不同节点产生的标识。
- 简单易用:生成算法相对简单,大多数编程语言都有现成的库来生成 UUID。
-
- 不具备顺序性:生成的 ID 是随机的,没有时间顺序或者其他有意义的顺序。这在一些需要根据 ID 排序的场景下,如数据库索引优化,会带来不便。
- 占用空间较大:128 位的长度在存储和传输时相对占用较多的空间,可能会增加系统的存储成本和网络开销。
二、数据库自增 ID#
-
- 利用数据库(如 MySQL)的自增主键特性。在数据库中创建一个包含自增主键的表,每次需要生成 ID 时,插入一条记录,数据库会自动为其分配一个唯一的自增 ID。这个 ID 可以作为分布式 ID 使用,多个应用节点可以共享这个数据库来获取 ID。
-
- 简单高效:对于小型分布式系统或者对 ID 顺序性有严格要求的场景,数据库自增 ID 是一种简单直接的解决方案。生成的 ID 是顺序递增的,有利于数据库索引和查询性能。
-
- 单点瓶颈:所有 ID 生成请求都依赖于数据库,当系统并发量高时,数据库可能会成为性能瓶颈。因为数据库的写入操作需要加锁来保证自增 ID 的唯一性,大量并发请求可能会导致锁竞争,影响性能。
- 扩展性差:在分布式环境下,随着系统规模的扩大,单个数据库可能无法满足 ID 生成的需求,需要考虑数据库的高可用和横向扩展问题。
三、雪花算法(Snowflake)#
-
- 雪花算法是一种分布式 ID 生成算法,它生成的 ID 是一个 64 位的长整型数字。其结构主要包括以下几个部分:
- 符号位(1 位):最高位是符号位,通常为 0,表示正数。
- 时间戳(41 位):记录了从一个固定的起始时间(如 2016 年 1 月 1 日)到 ID 生成时刻的毫秒数。这部分保证了 ID 的时间顺序性。
- 工作机器 ID(10 位):用于区分不同的工作机器,最多可以支持 1024 台机器。
- 序列号(12 位):在同一毫秒内,同一机器可以生成的不同 ID,最多可以生成 4096 个不同的 ID。
-
- 高并发支持:可以在分布式系统中高并发地生成唯一 ID。在同一毫秒内,不同机器和同一机器都可以生成多个不同的 ID,满足高并发场景的需求。
- 有序性好:生成的 ID 按照时间顺序递增,这对于数据库索引、日志排序等场景非常有利,可以提高系统的查询和处理效率。
-
- 依赖时间戳:如果系统的时钟出现回拨(如服务器时间被手动调整或者时钟同步出现问题),可能会导致生成的 ID 出现重复或者不符合预期的顺序。需要采取一定的措施来应对时钟回拨问题,如使用备用时间源或者拒绝生成 ID 直到时钟恢复正常。
- 机器 ID 分配复杂:在大规模分布式系统中,需要合理地分配工作机器 ID,否则可能会出现机器 ID 冲突或者浪费的情况。
四、Redis 自增 ID#
-
- 利用 Redis 的原子性自增命令(如
INCR)来生成 ID。在 Redis 中设置一个键(Key),每次需要生成 ID 时,通过INCR命令对这个键的值进行自增操作。多个应用节点可以共享这个 Redis 实例来获取 ID。
-
- 性能高:Redis 是基于内存的高性能数据库,
INCR命令是原子操作,能够在高并发环境下快速生成 ID,避免了数据库自增 ID 的锁竞争问题。
- 简单易用:和数据库自增 ID 类似,实现相对简单,只需要调用 Redis 的自增命令即可。
-
- 单点故障风险:如果 Redis 实例出现故障,可能会导致 ID 生成服务中断。虽然可以通过 Redis 的主从复制和哨兵模式来提高可用性,但仍然存在一定的风险。
- 数据持久化问题:如果 Redis 没有正确地进行持久化设置,在重启或者故障恢复后,可能会出现 ID 重复或者丢失的情况。
看个大佬
...