add FlexIDKeyGenerator

This commit is contained in:
开源海哥 2023-04-02 15:08:11 +08:00
parent 132dcc6498
commit 5c4430e8d2
2 changed files with 99 additions and 0 deletions

View File

@ -15,6 +15,7 @@
*/
package com.mybatisflex.core.keygen;
import com.mybatisflex.core.keygen.impl.FlexIDKeyGenerator;
import com.mybatisflex.core.keygen.impl.UUIDKeyGenerator;
import java.util.HashMap;
@ -28,6 +29,7 @@ public class KeyGeneratorFactory {
* {@link com.mybatisflex.annotation.Id}
*/
register("uuid", new UUIDKeyGenerator());
register("flex", new FlexIDKeyGenerator());
}

View File

@ -0,0 +1,97 @@
/**
* Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.keygen.impl;
import com.mybatisflex.core.keygen.IKeyGenerator;
import java.util.concurrent.ThreadLocalRandom;
/**
* 独创的 FlexID 算法简单好用:
* <p>
* 特点
* 1保证 id 生成的顺序为时间顺序越往后生成的 ID 值越大
* 2运行时单台机器并发量在每秒钟 10w 以内
* 3运行时无视时间回拨
* 4最大支持 99 台机器
* 5够用大概 300 年左右的时间
* <p>
* 缺点
* 1每台机器允许最大的并发量为 10w/s
* 2出现时间回拨重启机器时在时间回拨未恢复的情况下可能出现 id 重复
* <p>
* ID组成时间7+| 毫秒内的时间自增 00~992| 机器ID01 ~ 992| 随机数000~9993用于分库分表时通过 id 取模保证分布均衡
*/
public class FlexIDKeyGenerator implements IKeyGenerator {
private static final long INITIAL_TIMESTAMP = 1680411660000L;
private static final long MAX_CLOCK_SEQ = 99;
private long lastTimeMillis = 0;//最后一次生成 ID 的时间
private long clockSeq = 0; //时间序列
private long workId = 1; //机器 ID
public FlexIDKeyGenerator() {
}
public FlexIDKeyGenerator(long workId) {
this.workId = workId;
}
@Override
public Object generate(Object entity, String keyColumn) {
return nextId();
}
private synchronized long nextId() {
//当前时间
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis == lastTimeMillis) {
clockSeq++;
if (clockSeq > MAX_CLOCK_SEQ) {
clockSeq = 0;
currentTimeMillis++;
}
}
//出现时间回拨
else if (currentTimeMillis < lastTimeMillis) {
currentTimeMillis = lastTimeMillis;
clockSeq++;
if (clockSeq > MAX_CLOCK_SEQ) {
clockSeq = 0;
currentTimeMillis++;
}
} else {
clockSeq = 0;
}
lastTimeMillis = currentTimeMillis;
long diffTimeMillis = currentTimeMillis - INITIAL_TIMESTAMP;
return diffTimeMillis * 1000000 + clockSeq * 10000 + workId * 1000 + getRandomInt();
}
private int getRandomInt() {
return ThreadLocalRandom.current().nextInt(1000);
}
}