1. 设计目标
- ID唯一不重复
- 高性能
2. 架构图
Server1 Server2 Server3
\ | /
Mysql
Server要生成唯一ID,先从Mysql一次性申请若干个独占ID,如500个,Server用完这500个后,一次性去Mysql再申请500个,依次类推,Mysql保证每批分配的ID不重复。
具体实现:
- ID为long型整数,mysql保存可分配的最小ID
- Server从mysql获取可分配的最小ID,然后可生成[最小ID, 最小ID+499] 共500个ID,用完了再去mysql申请下一批ID;
3. Mysql
建表并设置最小可分配的ID
create table tablename(maxId bigint);
insert into tablename values(0);
4. Server实现
初始化:
long curID = 0;
long maxID = -1;
生成唯一ID
lock();
// 无可用ID或最近一次申请的ID已经用完
if (curID > maxID) {
向Mysql申请ID;
}
return curID++;
unlock();
向Mysql申请ID:
事务 {
select maxID from tablename for update; //得到maxid
update tablename set maxID=maxID + 500; // 申请了[maxid,maxid+499]范围的ID,下一次可配的最小ID变为maxid+500
}
curID = maxid;
maxID = maxid + 499;
唯一性
- 因myslq行锁,每个Server从Mysql获取的id范围不重复
- Server内部如果多线程,可向上面伪码那样使用互斥机制
Server宕机会如何?
最多损失500个可分配ID,关系不大
性能
一次mysql网络交互,然后缓存maxID值,性能高,500个ID只需一次mysql交互,mysql压力小。 mysql一般也是系统已有组件,意味着一般来说系统无需增加新组建。
随机的、不可预测ID
上面生成的ID为递增long型,有一定的可预测性,可在上面ID的基础上,拼接上随机数或者UUID之类生成随机不可预测ID。