常见生成唯一资源ID的方式
字数 1509 2025-08-22 12:23:36

唯一资源ID生成方式详解

一、唯一ID的特征要求

在业务开发中,唯一ID需要满足以下关键特征:

  1. 唯一性:生成的ID全局唯一,在特定范围内冲突概率极小
  2. 可用性:可保证高并发下的可用性
  3. 安全性:对生成的ID不能进行预测,不会暴露系统和业务的信息

二、常见生成方式对比

方案 唯一性 有序性 可用性 安全性
雪花算法 较强唯一性 大致有序 高可用 可部分预测
UUID 强唯一性 无序 高可用 不可预测
数据库自增ID 强唯一性 有序 较高可用 可预测
哈希算法 较强唯一性 无序 较高可用 取决于算法

三、雪花算法详解

1. 算法组成

雪花算法生成的ID由以下几部分组成:

  1. 符号位:始终为0,表示正数
  2. 时间戳:占用41位,表示从固定时间点(如2010年1月1日)开始的时间差
  3. 机器标识:包括数据中心ID(5位)和机器ID(5位),用于区分不同服务器节点
  4. 序列号:占用12位,用于同一毫秒内生成的不同ID

2. 安全性分析

理论上可以预测,但实际操作困难:

  • 时间戳采用毫秒级精度
  • 假设5台机器,每毫秒生成1个ID,则每小时可生成1800万个ID(60601000*5)
  • 爆破方式获取信息成本高,容易被发现

3. Python实现示例

import time
import threading

class SnowflakeGenerator:
    def __init__(self, datacenter_id, worker_id):
        self.datacenter_id = datacenter_id
        self.worker_id = worker_id
        self.sequence = 0
        self.last_timestamp = -1
        
        # Bit lengths
        self.datacenter_id_bits = 5
        self.worker_id_bits = 5
        self.sequence_bits = 12
        
        # Maximum values
        self.max_datacenter_id = -1 ^ (-1 << self.datacenter_id_bits)
        self.max_worker_id = -1 ^ (-1 << self.worker_id_bits)
        self.max_sequence = -1 ^ (-1 << self.sequence_bits)
        
        # Shift amounts
        self.worker_id_shift = self.sequence_bits
        self.datacenter_id_shift = self.sequence_bits + self.worker_id_bits
        self.timestamp_shift = self.sequence_bits + self.worker_id_bits + self.datacenter_id_bits
        
        self.lock = threading.Lock()

    def _current_milliseconds(self):
        return int(time.time() * 1000)

    def _til_next_millis(self, last_timestamp):
        timestamp = self._current_milliseconds()
        while timestamp <= last_timestamp:
            timestamp = self._current_milliseconds()
        return timestamp

    def generate_id(self):
        with self.lock:
            timestamp = self._current_milliseconds()
            
            if timestamp < self.last_timestamp:
                raise ValueError("Clock moved backwards. Refusing to generate id.")
            
            if timestamp == self.last_timestamp:
                self.sequence = (self.sequence + 1) & self.max_sequence
                if self.sequence == 0:
                    timestamp = self._til_next_millis(self.last_timestamp)
            else:
                self.sequence = 0
            
            self.last_timestamp = timestamp
            
            return ((timestamp - 1288834974657) << self.timestamp_shift) | \
                   (self.datacenter_id << self.datacenter_id_shift) | \
                   (self.worker_id << self.worker_id_shift) | \
                   self.sequence

def generate_unique_id(prefix: str, datacenter_id: int, worker_id: int) -> str:
    generator = SnowflakeGenerator(datacenter_id, worker_id)
    snowflake_id = generator.generate_id()
    return f"{prefix}{snowflake_id}"

# 使用示例
datacenter_id = 0
worker_id = 1
user_id = generate_unique_id("USER_", datacenter_id, worker_id)
print(f"生成的用户ID: {user_id}")

四、数据库自增ID

1. 基本特性

优点

  • 使用简单,满足基本需求
  • 天然有序

缺点

  1. 并发性不好
  2. 数据库写压力大
  3. 数据库故障后不可使用
  4. 存在数量泄露风险

2. 优化方案

方案一:数据库水平拆分

  • 设置不同的初始值和相同的步长
  • 保证每台数据库生成的ID不冲突
  • 扩容问题
    • 根据扩容考虑决定步长
    • 增加其他位标记区分扩容

方案二:批量生成ID

  • 每次批量生成一批ID给不同机器消费
  • 减小数据库压力到N分之一
  • 缺点:服务器重启、单点故障会造成ID不连续

五、UUID

1. 基本格式

标准形式为32个十六进制数组成的字符串,分隔为五个部分:
467e8542-2275-4163-95d6-7adc205580a9

实际使用中常去掉分隔符:
467e85422275416395d67adc205580a9

2. 特性

  • 唯一性:基于随机数和时间戳组合,生成全局唯一的ID
  • 无序性:随机生成,不具有时间排序性
  • 性能:生成速度快,适合高并发环境
  • 安全性:完全无序,不可猜测,可防止水平越权攻击

六、哈希算法

1. 基本原理

  • 将任意长度输入转化为固定长度哈希值
  • 相同输入始终生成相同哈希值
  • 单向性:无法从哈希值还原原始数据

2. 唯一性考虑

  • 哈希冲突:不同输入可能生成相同哈希值
  • 解决方案
    • 添加随机性减少冲突概率
    • 使用唯一性索引验证ID是否已存在

3. 常见应用场景

  • 密码学
  • 数据完整性验证
  • 数据检索
  • 数字签名
  • 哈希表等数据结构
  • 信息安全领域

七、安全测试注意事项

在测试权限问题时,需充分了解资源ID的生成方式:

  1. 可预测性分析:判断ID是否可被猜测
  2. 越权测试:针对不同生成方式采取不同测试策略
    • 有序ID(如自增ID)较易进行越权测试
    • 无序ID(如UUID)较难进行越权测试
  3. 成本效益评估:爆破方式需考虑成本与收益比

八、方案选择建议

  1. 高并发+安全性:优先考虑UUID
  2. 需要有序性:考虑雪花算法
  3. 简单业务场景:可使用数据库自增ID(配合优化方案)
  4. 数据指纹需求:考虑哈希算法

没有绝对最好的方案,应根据具体业务需求选择最适合的ID生成方式。

唯一资源ID生成方式详解 一、唯一ID的特征要求 在业务开发中,唯一ID需要满足以下关键特征: 唯一性 :生成的ID全局唯一,在特定范围内冲突概率极小 可用性 :可保证高并发下的可用性 安全性 :对生成的ID不能进行预测,不会暴露系统和业务的信息 二、常见生成方式对比 | 方案 | 唯一性 | 有序性 | 可用性 | 安全性 | |------|--------|--------|--------|--------| | 雪花算法 | 较强唯一性 | 大致有序 | 高可用 | 可部分预测 | | UUID | 强唯一性 | 无序 | 高可用 | 不可预测 | | 数据库自增ID | 强唯一性 | 有序 | 较高可用 | 可预测 | | 哈希算法 | 较强唯一性 | 无序 | 较高可用 | 取决于算法 | 三、雪花算法详解 1. 算法组成 雪花算法生成的ID由以下几部分组成: 符号位 :始终为0,表示正数 时间戳 :占用41位,表示从固定时间点(如2010年1月1日)开始的时间差 机器标识 :包括数据中心ID(5位)和机器ID(5位),用于区分不同服务器节点 序列号 :占用12位,用于同一毫秒内生成的不同ID 2. 安全性分析 理论上可以预测,但实际操作困难: 时间戳采用毫秒级精度 假设5台机器,每毫秒生成1个ID,则每小时可生成1800万个ID(60 60 1000* 5) 爆破方式获取信息成本高,容易被发现 3. Python实现示例 四、数据库自增ID 1. 基本特性 优点 : 使用简单,满足基本需求 天然有序 缺点 : 并发性不好 数据库写压力大 数据库故障后不可使用 存在数量泄露风险 2. 优化方案 方案一:数据库水平拆分 设置不同的初始值和相同的步长 保证每台数据库生成的ID不冲突 扩容问题 : 根据扩容考虑决定步长 增加其他位标记区分扩容 方案二:批量生成ID 每次批量生成一批ID给不同机器消费 减小数据库压力到N分之一 缺点 :服务器重启、单点故障会造成ID不连续 五、UUID 1. 基本格式 标准形式为32个十六进制数组成的字符串,分隔为五个部分: 467e8542-2275-4163-95d6-7adc205580a9 实际使用中常去掉分隔符: 467e85422275416395d67adc205580a9 2. 特性 唯一性 :基于随机数和时间戳组合,生成全局唯一的ID 无序性 :随机生成,不具有时间排序性 性能 :生成速度快,适合高并发环境 安全性 :完全无序,不可猜测,可防止水平越权攻击 六、哈希算法 1. 基本原理 将任意长度输入转化为固定长度哈希值 相同输入始终生成相同哈希值 单向性:无法从哈希值还原原始数据 2. 唯一性考虑 哈希冲突 :不同输入可能生成相同哈希值 解决方案 : 添加随机性减少冲突概率 使用唯一性索引验证ID是否已存在 3. 常见应用场景 密码学 数据完整性验证 数据检索 数字签名 哈希表等数据结构 信息安全领域 七、安全测试注意事项 在测试权限问题时,需充分了解资源ID的生成方式: 可预测性分析 :判断ID是否可被猜测 越权测试 :针对不同生成方式采取不同测试策略 有序ID(如自增ID)较易进行越权测试 无序ID(如UUID)较难进行越权测试 成本效益评估 :爆破方式需考虑成本与收益比 八、方案选择建议 高并发+安全性 :优先考虑UUID 需要有序性 :考虑雪花算法 简单业务场景 :可使用数据库自增ID(配合优化方案) 数据指纹需求 :考虑哈希算法 没有绝对最好的方案,应根据具体业务需求选择最适合的ID生成方式。