全局唯一id生成策略

最近在做项目,当你数据库表中的id要向用户展示时,或者在分布式系统中,如果只用数据库id自增作为唯一id的策略的话,会出现一系列问题,比如安全性问题、数据冲突问题(在分布式系统中)等,所以需要一种方法来生成全局唯一id并且可以避免这些问题。全局唯一 ID(GUID/UUID)是许多系统开发中需要解决的问题,尤其是在分布式系统中,必须保证生成的 ID 不重复且高效。下面我总结了一下常见的几种策略。

1. 基于 UUID

UUID(Universally Unique Identifier)是一个通用的唯一标识符,通常用于生成 128 位的唯一 ID。

特点

  • 无需依赖中心化服务。
  • 快速生成且唯一性高。
  • 格式如:550e8400-e29b-41d4-a716-446655440000

 实现方式

import java.util.UUID;

public class UUIDExample {
    public static void main(String[] args) {
        // 生成一个 UUID
        String uniqueID = UUID.randomUUID().toString();
        System.out.println(uniqueID);  // 输出类似于:550e8400-e29b-41d4-a716-446655440000
    }
}

 优缺点

  • 优点
    • 无需中心化依赖,分布式系统中可独立生成。
    • 实现简单,生成速度快。
  • 缺点
    • UUID 较长(128 位),不适合用于高并发环境中的排序场景。
    • 可读性差。

 2. 基于数据库的自增 ID

通过数据库的自增字段实现唯一 ID。

特点

  • 依赖数据库,自增字段能保证唯一性。
  • ID 格式整齐(如:1、2、3、4……)。

 实现方式

MySQL 示例:

创建一个表,利用自增主键:

CREATE TABLE unique_id (
    id BIGINT AUTO_INCREMENT PRIMARY KEY
);

每次需要生成 ID 时,插入一条记录,获取自增 ID:

INSERT INTO unique_id () VALUES ();
SELECT LAST_INSERT_ID();

优缺点

  • 优点
    • 实现简单,生成的 ID 连续且有序。
  • 缺点
    • 数据库成为性能瓶颈,不适合高并发场景。
    • 分布式场景下需要额外设计解决方案(如:分库分表的 ID 生成)。

 3. 基于 Redis 的自增键

利用 Redis 的原子性自增操作生成全局唯一 ID。

特点

  • INCR 是 Redis 的原子操作,可以在分布式系统中安全使用。
  • Redis 性能高,适合高并发场景。

 实现方式

import redis.clients.jedis.Jedis;

public class RedisIncrExample {
    public static void main(String[] args) {
        // 连接 Redis
        Jedis jedis = new Jedis("localhost", 6379);

        // 自增键
        Long uniqueId = jedis.incr("global_id");
        System.out.println(uniqueId);  // 输出递增的整数

        jedis.close();
    }
}

优缺点

  • 优点
    • 性能高,适合分布式系统。
    • 生成的 ID 简单、递增,便于排序。
  • 缺点
    • 需要依赖 Redis 服务。

 4. 雪花算法(Snowflake)

 雪花算法是 Twitter 提出的分布式唯一 ID 生成算法,生成 64 位的整型 ID,结构如下:

 1 bit 符号位 | 41 bit 时间戳 | 10 bit 机器 ID | 12 bit 序列号

  • 时间戳:表示从某个时间点到当前时间的毫秒数,41 位可用 69 年。
  • 机器 ID:用于区分不同节点或机器,10 位支持最多 1024 个节点。
  • 序列号:支持每毫秒生成最多 4096 个 ID。

 实现方式

 使用 Hutool 工具库:

import cn.hutool.core.util.IdUtil;

public class SnowflakeExample {
    public static void main(String[] args) {
        // 创建雪花算法生成器
        long workerId = 1;  // 机器 ID
        long datacenterId = 1;  // 数据中心 ID
        cn.hutool.core.lang.Snowflake snowflake = IdUtil.createSnowflake(workerId, datacenterId);

        // 生成唯一 ID
        long uniqueId = snowflake.nextId();
        System.out.println(uniqueId);  // 输出类似:123456789012345678
    }
}

优缺点

  • 优点
    • 高性能,适合高并发场景。
    • ID 是时间有序的,方便排序。
  • 缺点
    • 实现复杂,需要管理机器 ID。

 5. 基于时间戳与随机数

 将时间戳和随机数结合生成唯一 ID。

特点

  • 时间戳保证了唯一性,随机数降低了冲突概率。
  • 简单易实现。

 实现方式

import java.util.Random;

public class TimestampRandomExample {
    public static void main(String[] args) {
        long timestamp = System.currentTimeMillis();  // 当前时间戳
        int randomNum = new Random().nextInt(9000) + 1000;  // 4 位随机数
        String uniqueId = timestamp + "" + randomNum;
        System.out.println(uniqueId);  // 输出类似:167223867512345
    }
}

优缺点

  • 优点
    • 简单易用,不依赖外部服务。
  • 缺点
    • 不适合极高并发场景(可能会有冲突)。

 6.总结

生成策略优点缺点适用场景
UUID无需中心化、实现简单长度较大,排序困难普通系统中标识符生成
数据库自增简单有序、连续数据库性能瓶颈,分布式支持较差小型系统或单点系统
Redis 自增高性能、支持分布式依赖 Redis 服务分布式系统,高并发场景
雪花算法高性能、时间有序、分布式支持好实现复杂高并发分布式系统
时间戳+随机数简单易实现冲突概率较高,排序困难普通系统,低并发环境

以上是总结的一些方案,最近看了一下黑马点评生成全局 唯一id的策略,感觉不错,以后有机会单独写一期,over!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值