基于数据库生成唯一ID有很多手段:oracle有funcNextval等函数,也可以用自增列。
前者依赖于oracle,后者不通用,一张表只能生成一种业务的唯一ID。
我们考虑mysql下的通用写法,要满足的能力如下:
public List<Long> genUniqueIntIds(String category, int num);
其中,category参数代表一种业务类别,num是该次生成唯一ID的个数。
记录唯一ID的数据库表结构如下:
CREATE TABLE `t_idgen` (
`SEQ_NAME` varchar NOT NULL COMMENT '业务类别',
`CURRENT_VAL` bigint NOT NULL COMMENT '当前值',
PRIMARY KEY (`SEQ_NAME`)
)
google了一把,生成唯一ID的SQL可以这么写:
INSERT INTO t_idgen(SEQ_NAME, CURRENT_VAL)
(SELECT #{sequenceName}, @count := #{num})
ON DUPLICATE KEY UPDATE CURRENT_VAL = (SELECT @count := CURRENT_VAL + #{num});
select @count;
这个写法很巧妙,使用了mysql的ON DUPLICATE KEY UPDATE的语法,首次insert,后续每次都是在当前值的基础上update。
当然,使用数据库生成唯一ID的方式是有缺陷的,它只适用于单库单表,如果分库分表,就做不到全系统唯一,可考虑使用redis或雪花算法了。
顺带说一下,基于redis实现全局唯一ID是很容易的,用redisson库的RAtomicLong类即可,而且还可以带超时。