一、场景
某表保存时,其自增ID需要同时作为其他表的外键同时保存,如果用MySql的自增ID,意味着只能分步操作,且出现异常时无法保证数据一致性,决定在代码中用AumicInteger实现自增ID,同时给多表用。
二、功能实现
因为是分布式,服务部署多个点,为保证ID的一致性,so将init的ID在数据库持久化,当然也可用redis或其他数据库或文件的方式,实质是一样的。
1、首先init当前ID及最大ID,并设定一次取ID的量,用完后再重新取;
private static AtomicInteger maxVal = new AtomicInteger(200000);
private static AtomicInteger currenVal = new AtomicInteger(200000);
//每次生成ID数量
private static final Integer FETCH_SIZE = 3;
2、获取自增ID,并将其持久化,直至与max相等
/**
* 获取自增ID序列
*/
public Integer nextId() {
//当前ID取完后,重新去DB取号段
if (currenVal.get() >= maxVal.get()) {
synchronized (this) {
if (currenVal.get() >= maxVal.get()) {
fecth();
}
}
}
//否则在当前号段中取
Integer alterId = currenVal.incrementAndGet();
Db.use(Zz.DS_FCC).update("update gen_id set last_id = ? where type = 1", alterId);
return alterId;
}
3、取库中最新ID
private void fecth() {
Integer lastId = Db.use(Zz.DS_FCC).findFirst("select last_id from gen_id where type = 1").getInt("last_id");
currenVal.set(lastId);
maxVal.set(lastId + FETCH_SIZE);
}
4、使用方法
GenerateIdUtils generateIdUtils = new GenerateIdUtils();
Integer alterId = generateIdUtils.nextId();
5、附建表脚本
CREATE TABLE `gen_id` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '序号',
`last_id` int(11) DEFAULT NULL COMMENT '最新的ID',
`type` int(11) DEFAULT NULL COMMENT 'ID类型:1falterid,2other',
`update_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

本文介绍了在Java中如何使用AtomicInteger来实现分布式环境下的自增ID生成,以解决MySQL自增ID在分布式场景下数据一致性的难题。通过初始化ID并在数据库中持久化,确保了多点部署的服务间ID的一致性。
9724

被折叠的 条评论
为什么被折叠?



