基于DB的全局唯一id

来源:互联网 发布:php生成8位唯一邀请码 编辑:程序博客网 时间:2024/05/18 01:43

基于DB的全局唯一id

同一个jvm内使用atomicLong保证,非同一个jvm内使用db的乐观锁保证。
当id超过设置的最大值后,自动归零复位。
格式为yymmdd+ 业务码 + id

代码如下

/** * 内部id生成器 * Created by carey on 2017/5/26. */@Componentpublic class InnerIdemIdGen {    private Map<InnerBusinessEnum, IdGenerator> bizGenCache = new HashMap<>();    private Logger logger = LoggerFactory.getLogger("biz");    /**     * id步长控制     */    private final long StepSize = 200;    /**     * 最大的步长,10?的格式     */    private final long MaxCount = 1000000;    @Resource    private IdGenMapper idGenMapper;    /**     * 初始化,从db加载     */    @PostConstruct    private void init() {        for (InnerBusinessEnum innerBusinessEnum : InnerBusinessEnum.values()) {            IdGenerator idGenerator = new IdGenerator(innerBusinessEnum.getName());            idGenerator.init();            bizGenCache.put(innerBusinessEnum, idGenerator);        }        logger.info("主键生成器注册完成");    }    /**     * 生成全局幂等id     * yymmdd + bizcode(3位) + 6位id     * @param innerBusinessEnum 内部定义的业务线     * @return     */    public long gen(InnerBusinessEnum innerBusinessEnum) {        IdGenerator idGenerator = bizGenCache.get(innerBusinessEnum);        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");        String time = sdf.format(new Date()).concat(innerBusinessEnum.getCode());        return Long.valueOf(time) * MaxCount + idGenerator.next();    }    /**     * 生成器     * 同jvm内使用atomic保证     * 非jvm内使用乐观锁保证     */    private class IdGenerator {        /**         * 表中的名字         */        private String key;        private AtomicLong count = new AtomicLong();        /**         * 下一次的天花板 需要重新从db中获取         */        private volatile long nextGenTop;        IdGenerator(String key) {            this.key = key;        }        /**         * 使用乐观锁         */        private void init() {            int changeSize;            long curCount;            do {                curCount = idGenMapper.getIndex(key);                changeSize = idGenMapper.updateIndex(key, curCount, StepSize);            } while (changeSize != 1);            count.set(curCount);            nextGenTop = curCount + StepSize;        }        /**         * 获取下一个id         * @return         */        private long next() {            long curCount = count.incrementAndGet();            if (curCount <= nextGenTop) {                return curCount;            }            synchronized (count) {                curCount = count.incrementAndGet();                if (curCount < nextGenTop) {                    return curCount;                }                init();                curCount = count.incrementAndGet();                if (curCount > MaxCount) {                    reset(nextGenTop);                    return count.incrementAndGet();                }                return curCount;            }        }        /**         * id达到了上限, 复位         * @param topCount         */        private void reset(long topCount) {            int changeSize = idGenMapper.reset(key, topCount);            if (0 == changeSize) {                init();            } else {                nextGenTop = StepSize;                count.set(0);            }        }    }    public enum InnerBusinessEnum {        PICC_ID("picc", "001"),        Test("test", "002");        /**         * 表中的名字         */        private String name;        /**         * 业务标识码         * yymmdd + bizCode + id         */        private String code;        private InnerBusinessEnum(String name, String code) {            this.name = name;            this.code = code;        }        public String getName() {            return name;        }        public String getCode() {            return code;        }    }}

db的部分

    <select id="getIndex" resultType="java.lang.Long">        select cur_count from cop_id_gen where biz_key = '${key}';    </select>    <update id="updateIndex">        update  cop_id_gen set cur_count = cur_count + ${stepSize} WHERE biz_key = '${key}' and cur_count = ${cur_count};    </update>    <update id="reset">        update  cop_id_gen set cur_count = 0 WHERE biz_key = '${key}' and cur_count = ${cur_count};    </update>
原创粉丝点击