千家信息网

java如何使用预分配法生成唯一ID

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,小编给大家分享一下java如何使用预分配法生成唯一ID,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在项目中经常有生成唯一
千家信息网最后更新 2026年11月01日java如何使用预分配法生成唯一ID

小编给大家分享一下java如何使用预分配法生成唯一ID,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

在项目中经常有生成唯一ID的业务需求。作为唯一标识方便后续查找和追踪。网上也有很多实现方案。比如:数据库自增主键,数据库批量生成ID,UUID,时间戳方法,zookeeper生成ID,redis生成唯一ID,snowflake算法等等。这些解决方案各有优缺点。我在游戏项目常用的解决方案是:预分配法生成唯一ID。其原理简单,利于扩展,具有较强的适用性。

预分配法生成唯一ID原理:数据库中存储每种类型最后的预分配dbUniqueId值。数据库实体对象上增加当前分配的
useDbUniqueId。预分配步长DBUNIQUEID_M可根据类型和业务量自定义。当useDbUniqueId大于等于dbUniqueId时就预分配出DBUNIQUEID_M个唯一ID。

角色ID生成:要求7位连续的唯一ID。则DBUNIQUEID_M=1。1000000+dbUniqueId格式化成7位数字。

本服唯一ID:则DBUNIQUEID_M=10000。(1000000+dbUniqueId)*10000+serverId格式化而成。其中serverId游戏服ID定义为4位

全局唯一ID:则DBUNIQUEID_M=10000。((100000000000L+dbUniqueId)100+gameCode10000+workerId;格式化而成。其中gameCode游戏编码定义为2位。

具体实现请参阅代码。非常方便的移植到项目工程中。

IdWorkerEnum.java

package com.game.common.db;import java.util.List;import com.core.enums.LLIndexedEnum;/** * ID枚举类型 * @author Thinker */public enum IdWorkerEnum implements LLIndexedEnum{    /** 角色ID */    IDWORKER_HUMANID(1,"角色ID"),    /** 数据库ID */    IDWORKER_DBID(2,"数据库ID"),    /** 工会ID */    IDWORKER_CLUBID(3,"工会ID"),    /** 收集ID */    IDWORKER_COLLECTID(4,"收集ID"),;    /** 枚举的索引 */    public final int index;    /** 名称的key */    private final String nameKey;    /** 按索引顺序存放的枚举数组 */    private static final List indexes=LLIndexedEnum.IndexedEnumUtil.toIndexes(IdWorkerEnum.values());    private IdWorkerEnum(int index,String nameKey)    {        this.index=index;        this.nameKey=nameKey;    }    /**     * 获取索引     */    @Override    public int getIndex()    {        return index;    }    /**     * 取得名称key     */    public String getNameKey()    {        return this.nameKey;    }    /**     * 根据指定的索引获取枚举的定义     */    public static IdWorkerEnum valueOf(final int index)    {        return LLIndexedEnum.IndexedEnumUtil.valueOf(indexes,index);    }}

DbUniqueIdEntity.java

package com.game.common.db;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import org.eclipse.persistence.annotations.HashPartitioning;import org.eclipse.persistence.annotations.Partitioned;import com.game.common.db.dao.BaseDbBean;/** * 数据库唯一KEY实体类 * @author Thinker */@Entity(name="t_dbUniqueId")@HashPartitioning(name="HashPartitionByDbUniqueCacheId",partitionColumn=@Column(name="dbUniqueCacheId"))@Partitioned("HashPartitionByDbUniqueCacheId")public class DbUniqueIdEntity extends BaseDbBean{    /** 数据库唯一缓存ID **/    @Id    @Column(length=20)    private long dbUniqueCacheId;    /** 数据库唯一ID **/    @Column(length=20)    private long dbUniqueId;    /** 最后更新的时间 **/    @Column(length=20)    private long createTime;    // ////////////////内部数据//////////////////    /** 已经使用过的数据库唯一ID(唯一ID) */    @Column(length=20)    private long useDbUniqueId;    @Override    public long getId()    {        return dbUniqueCacheId;    }    @Override    public void setId(long id)    {    }    public long getDbUniqueCacheId()    {        return dbUniqueCacheId;    }    public void setDbUniqueCacheId(long dbUniqueCacheId)    {        this.dbUniqueCacheId=dbUniqueCacheId;    }    public long getDbUniqueId()    {        return dbUniqueId;    }    public void setDbUniqueId(long dbUniqueId)    {        this.dbUniqueId=dbUniqueId;    }    public long getCreateTime()    {        return createTime;    }    public void setCreateTime(long createTime)    {        this.createTime=createTime;    }    public long getUseDbUniqueId()    {        return useDbUniqueId;    }    public void setUseDbUniqueId(long useDbUniqueId)    {        this.useDbUniqueId=useDbUniqueId;    }}

IdWorker.java

package com.game.common.db;import com.game.common.Globals;import com.game.common.entityProxy.EntityProxy;import com.game.core.appConfig.AppConfigServ;import com.game.core.utils.LoggerUtils;/** * 唯一ID生成器 *  * @author Thinker */public class IdWorker{    public final static IdWorker OBJ=new IdWorker(AppConfigServ.OBJ.getAppConfigBean().getServerNo());    private int DBUNIQUEID_M=2000;    private final long workerId;    /** 数据库连接池 */    private DbUniqueIdEntity[] szDbUniqueIdEntity=new DbUniqueIdEntity[5];    public IdWorker(long workerId)    {        this.workerId=workerId;    }    /**     * 生成系统唯一ID:采用隐性锁方式     */    public synchronized long nextId()    {        IdWorkerEnum idWorkerEnum=IdWorkerEnum.IDWORKER_DBID;        int dbUniqueCacheId=idWorkerEnum.getIndex();        loadDbUniqueId(idWorkerEnum);        DbUniqueIdEntity dbUniqueIdEntity=szDbUniqueIdEntity[dbUniqueCacheId];        long dbUniqueId=0;        // 需要重新分配Id:每次分配 M个        if(dbUniqueIdEntity.getUseDbUniqueId()>=dbUniqueIdEntity.getDbUniqueId())        {            dbUniqueIdEntity.setDbUniqueId(dbUniqueIdEntity.getDbUniqueId()+DBUNIQUEID_M);            EntityProxy.OBJ.update((long) dbUniqueCacheId,dbUniqueIdEntity);            LoggerUtils.serverLogger.info("IdWorker DbId:update dbUniqueId="+dbUniqueIdEntity.getDbUniqueId());        }        dbUniqueId=dbUniqueIdEntity.getUseDbUniqueId()+1;        dbUniqueIdEntity.setUseDbUniqueId(dbUniqueId);        // 11位UUID        return (1000000+dbUniqueId)*10000+workerId;    }    /**     * 生成系统唯一HumanID:采用隐性锁方式     */    public synchronized long nextHumanId()    {        IdWorkerEnum idWorkerEnum=IdWorkerEnum.IDWORKER_HUMANID;        int dbUniqueCacheId=idWorkerEnum.getIndex();        loadDbUniqueId(idWorkerEnum);        DbUniqueIdEntity dbUniqueIdEntity=szDbUniqueIdEntity[dbUniqueCacheId];        long dbUniqueId=0;        // 需要重新分配Id:每次分配 M个        if(dbUniqueIdEntity.getUseDbUniqueId()>=dbUniqueIdEntity.getDbUniqueId())        {            dbUniqueIdEntity.setDbUniqueId(dbUniqueIdEntity.getDbUniqueId()+1);            EntityProxy.OBJ.update((long) dbUniqueCacheId,dbUniqueIdEntity);            LoggerUtils.serverLogger.info("IdWorker HumanId:update dbUniqueId="+dbUniqueIdEntity.getDbUniqueId());        }        dbUniqueId=dbUniqueIdEntity.getUseDbUniqueId()+1;        dbUniqueIdEntity.setUseDbUniqueId(dbUniqueId);        // 7位UUID        return (1000000+dbUniqueId);    }    /**     * 生成系统唯一ClubID:采用隐性锁方式     */    public synchronized long nextClubId()    {        IdWorkerEnum idWorkerEnum=IdWorkerEnum.IDWORKER_CLUBID;        int dbUniqueCacheId=idWorkerEnum.getIndex();        loadDbUniqueId(idWorkerEnum);        DbUniqueIdEntity dbUniqueIdEntity=szDbUniqueIdEntity[dbUniqueCacheId];        long dbUniqueId=0;        // 需要重新分配Id:每次分配 M个        if(dbUniqueIdEntity.getUseDbUniqueId()>=dbUniqueIdEntity.getDbUniqueId())        {            dbUniqueIdEntity.setDbUniqueId(dbUniqueIdEntity.getDbUniqueId()+1);            EntityProxy.OBJ.update((long) dbUniqueCacheId,dbUniqueIdEntity);            LoggerUtils.serverLogger.info("IdWorker clubId:update dbUniqueId="+dbUniqueIdEntity.getDbUniqueId());        }        dbUniqueId=dbUniqueIdEntity.getUseDbUniqueId()+1;        dbUniqueIdEntity.setUseDbUniqueId(dbUniqueId);        // 5位UUID        return (10000+dbUniqueId);    }    /**     * 生成系统唯一ID:采用隐性锁方式     */    public synchronized long nextCollectId()    {        IdWorkerEnum idWorkerEnum=IdWorkerEnum.IDWORKER_COLLECTID;        int dbUniqueCacheId=idWorkerEnum.getIndex();        loadDbUniqueId(idWorkerEnum);        DbUniqueIdEntity dbUniqueIdEntity=szDbUniqueIdEntity[dbUniqueCacheId];        long dbUniqueId=0;        // 需要重新分配Id:每次分配 M个        if(dbUniqueIdEntity.getUseDbUniqueId()>=dbUniqueIdEntity.getDbUniqueId())        {            dbUniqueIdEntity.setDbUniqueId(dbUniqueIdEntity.getDbUniqueId()+DBUNIQUEID_M);            EntityProxy.OBJ.update((long) dbUniqueCacheId,dbUniqueIdEntity);            LoggerUtils.serverLogger.info("IdWorker DbId:update dbUniqueId="+dbUniqueIdEntity.getDbUniqueId());        }        dbUniqueId=dbUniqueIdEntity.getUseDbUniqueId()+1;        dbUniqueIdEntity.setUseDbUniqueId(dbUniqueId);        // 18位UUID:游戏ID+服务器ID。确保支持多游戏不重复的ID。便于兼容统计        return ((100000000000L+dbUniqueId)*100+AppConfigServ.OBJ.getAppConfigBean().getGameCode())*10000+workerId;    }    /**     * 加载唯一ID     */    public void loadDbUniqueId(IdWorkerEnum idWorkerEnum)    {        int dbUniqueCacheId=idWorkerEnum.getIndex();        if(szDbUniqueIdEntity[dbUniqueCacheId]!=null) return;        DbUniqueIdEntity dbUniqueIdEntity=EntityProxy.OBJ.get((long) dbUniqueCacheId,(long) dbUniqueCacheId,DbUniqueIdEntity.class);        if(dbUniqueIdEntity==null)        {            dbUniqueIdEntity=new DbUniqueIdEntity();            dbUniqueIdEntity.setDbUniqueCacheId(dbUniqueCacheId);            dbUniqueIdEntity.setDbUniqueId(0);            dbUniqueIdEntity.setCreateTime(Globals.getTimeService().now());            dbUniqueIdEntity.setUseDbUniqueId(0);            EntityProxy.OBJ.insert((long) dbUniqueCacheId,dbUniqueIdEntity);        }        dbUniqueIdEntity.setUseDbUniqueId(dbUniqueIdEntity.getDbUniqueId());        szDbUniqueIdEntity[dbUniqueCacheId]=dbUniqueIdEntity;        LoggerUtils.serverLogger.info("IdWorker:load dbUniqueId="+dbUniqueIdEntity.getDbUniqueId());    }}

以上是"java如何使用预分配法生成唯一ID"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

分配 生成 数据 数据库 方式 系统 索引 隐性 方案 格式 篇文章 类型 角色 项目 业务 内容 原理 名称 实体 工会 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技海报 苏州找大状互联网科技有限公司 互联网科技工作委员会毛军 互联网最新的科技有限公司 科技与互联网发展 善班互联网科技 电子科技大学互联网 海南购全球互联网科技 北京华百购互联网科技有限公司 科技与互联网哪个更好 金融科技与互联网金融相同和不同 中化能源互联网科技招聘 中国互联网公司排名锤子科技 互联网科技如何创业 卓翼科技产业互联网合作 云南互联网科技学费 互联网领先科技活动 保山互联网科技靠谱吗 北京军民互联网科技公司 科技互联网专业工作会议发言稿 中智农互联网科技 互联网是第几次科技革命的成果 世界互联网领先科技成果 苏州互联网科技贷款公司 搜狐科技互联网 中国科技创新与世界互联网大会 天津腾达互联网科技有限公司 滨湖区互联网智能科技产品有哪些 半导体是互联网高科技吗 易企秀互联网科技是做什么的
0