网站优化

网站优化

Products

当前位置:首页 > 网站优化 >

如何巧妙运用号段模式,实现分布式ID的?

GG网络技术分享 2026-04-16 09:09 2


如何通过号段模式实现分布式ID

我CPU干烧了。 哎, 说起分布式ID,那真是个让人头疼的问题。以前在单体系统里数据库自增ID多方便啊!可是一旦业务起来了分库分表、微服务一堆,这ID就成了一个大麻烦。我跟你说当初为了这玩意儿,我差点没头发了!

一开始的困惑:为啥自增ID不行了?

想想看,咱们以前用数据库自增ID多好?简单、高效、有序。可是现在呢?服务拆开了每个服务都想生成全局唯一的ID,直接用自增ID肯定不行了。 换个赛道。 分库之后每个库都有自己的自增ID,冲突是必然的。所以必须得找个办法来生成全局唯一的ID。

UUID?算了吧…

有人说用UUID!UUID嘛,按道理讲是全局唯一的。但是UUID长得太丑了!而且它是无序的,插入数据的时候容易导致页分裂,性能太差了!我跟你说啊,数据库可不喜欢无序的数据插入。

号段模式:一个看似完美的解决方案

后来我听说号段模式了。听起来挺靠谱的嘛!就是从数据库里批量获取一段ID,然后服务自己内部按照顺序使用。 靠谱。 这样既保证了全局唯一性,又避免了频繁访问数据库。

核心思想:预分配与本地缓存

简单来说就是这样:每次从数据库拿一个“号段”,然后把这个号段缓存到内存里。需要生成ID的时候就从内存里取就行了。等内存里的号段用完了再到数据库申请新的号段,我明白了。。

方案名称 优点 缺点 适用场景
UUID 简单易实现 无序、 性能差 对性能要求不高的小项目
Redis incr 高并发、性能好 依赖Redis、可能存在空洞 对一致性要求不高的情况
号段模式 相对高效、易 需要考虑步长配置、可能存在阻塞 大多数中大型分布式系统

代码示例 :创建全局序列表

CREATE TABLE `common_sequence` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,    `name` varchar NOT NULL DEFAULT '',     `value` bigint NOT NULL,                `gmt_modified` date NOT NULL,           PRIMARY KEY ,                   UNIQUE KEY `name`           ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

步长的艺术:太小太快用完,太大又浪费

这个“步长”很重要!步长就是一次从数据库获取多少个ID。如果步长太小了频繁访问数据库效率低;如果步长太大了呢?又容易造成浪费啊!特别是当某个服务重启的时候,“未来”的那些没用到的 ID 就白白浪费掉了。

外步长和内步长:精细化管理

为了解决这个问题,我们引入了“外步长”和“内步长”。外步长是指多个服务器共同分配的总量;内步长是指单个服务器可以使用的量。举个例子:假设外步长是1000,内步长也是1000。那么每个服务器可以申请1000个ID,在我看来...。

遇到的坑:并发与阻塞

悲观锁与乐观锁:两种选择

  • 悲观锁: 直接上行锁! 虽然简单粗暴, 但是容易造成阻塞.
  • 乐观锁: 通过版本号来控制更新. 先读取版本号, 更新的时候检查版本号是否一致. 如果一致则更新成功, 否则失败.

双号段缓存:化解危机

提升稳定性与性能的关键

  • 降低数据库压力
  • 避免因等待新号段而导致的阻塞

再说说的思考: 信息平安问题

: 号段模式并非万能钥匙

总而言之 , 号段模式是一种比较实用的分布式 ID 生成方案 . 但是它也不是万能的 . 需要根据具体的业务场景来权衡各种优缺点 , 选择最适合自己的方案 .,开搞。


提交需求或反馈

Demand feedback