全局 ID
一、什么是全局 ID?
一句话:
全局唯一 ID = 整个系统里永远不会重复的 ID。
不管多少台服务器、多少张表、多少服务,生成出来的 ID 都绝对不重复。
比如:
- 订单 ID
- 优惠券 ID
- 用户 ID
- 流水号
这些都必须全局唯一,不能重复。
二、为什么需要全局 ID?(你写的那两个问题是核心)
你学习笔记里写的两点,就是分布式系统必须用全局 ID 的真正原因:
1. 数据库自增 ID 不安全、规律太明显
如果订单 ID 是:
101、102、103、104...
别人一看就能猜到:
- 今天卖了多少单
- 总订单量多少
- 商业机密直接暴露
全局 ID 是乱序的,别人猜不到。
2. 分库分表后,数据库自增 ID 会重复
比如:
- 订单表 1 自增到 100
- 订单表 2 自增也到 100
那就出现两个订单 ID = 100
系统直接乱套!
所以必须用全局唯一 ID。
三、全局 ID 怎么生成?(你给的 Redis 实现就是最经典方案)
你代码里的 Redis 生成方案,结构是:
plaintext
全局ID = 符号位(0) + 时间戳(31位) + 序列号(32位)
1. 时间戳(31 位)
从一个固定时间开始算(比如 2022-01-01)
每秒一个数字,能用 69 年。
作用:保证不同时间生成的 ID 一定不重复。
2. 序列号(32 位)
Redis 里执行:
java
运行
stringRedisTemplate.opsForValue().increment(键);
Redis 自增是原子性的,并发再高也不会重复。
一秒钟最多能生成 2^32 = 42 亿 个 ID,完全够用。
四、最终 ID 怎么拼出来的?(核心代码解释)
java
运行
return timestamp << 32 | count;
这句就是拼接全局 ID的核心:
- timestamp << 32把时间戳往左移 32 位给后面的序列号腾出位置
- | count把 时间戳 和 序列号 按位合并变成一个唯一的 long 数字
最终效果:
时间戳不同 → ID 不同
时间戳相同 → 序列号不同 → ID 也不同
所以永远不会重复!
五、这个 Redis 全局 ID 有什么好处?
- 绝对不重复
- 高并发性能极高
- 不依赖数据库
- 分库分表也能用
- ID 无规律,安全
- 自带时间顺序
- 可以按天统计数量(因为 key 里带日期)
六、怎么使用这个全局 ID?(超简单)
你在代码里需要生成订单 ID 时,直接写:
java
运行
long orderId = redisIdWorker.nextId("order");
生成优惠券 ID:
java
运行
long voucherId = redisIdWorker.nextId("voucher");
生成用户 ID:
java
运行
long userId = redisIdWorker.nextId("user");
不同业务用不同前缀,互不干扰。
七、测试代码里的 CountDownLatch 是什么?
你笔记里写的:
CountDownLatch = 主线程等所有子线程执行完再结束
作用:
- 开 500 个线程
- 每个线程生成 100 个 ID
- 主线程必须等全部完成
- 才能统计总耗时
这样测试出来的时间才准确。
哔哩哔哩公司福利 936人发布