yuhuan66666
V2EX  ›  Java

Java 生成的 UUID 出现了重复?! 什么鬼??

  •  
  •   yuhuan66666 · May 22, 2017 · 22783 views
    This topic created in 3460 days ago, the information mentioned may be changed or developed.

    不是号称 比被陨石砸中都的概率还小么。。。。。

    怎么当一年的主键就重复了好几个呢。。。。

    各位大大 都用啥当主键的?

    难不成真要 各个字段连成一条+UUID 生成的字符串,再算成 SHA512 当主键吗???

    太复杂了吧。。。。

    Supplement 1  ·  May 22, 2017
    用的就是 UUID.randomUUID()方法生成的 UUID
    Supplement 2  ·  May 22, 2017
    请问使用 java 怎样可以生成一个时间基于时间的唯一性 UUID 呢 我现在用的全是版本 4 的
    27 replies  •  2017-07-12 00:10:20 +08:00
    knightdf
    knightdf
    May 22, 2017
    1
    没人说不重复啊。。。
    lonenol
    lonenol
    May 22, 2017
    2
    各种算法一大堆,随便 Goolebaidubing 一下
    congeec
    congeec
    May 22, 2017
    3
    出现重复的就二次 hash 呗
    oh
    oh
    May 22, 2017 via iPhone
    4
    好想知道楼主的业务一年业务量是多少,出现了好几条重复
    watzds
    watzds
    May 22, 2017 via Android
    5
    也可能代码有 bug
    wu1990
    wu1990
    May 22, 2017
    6
    数据量多大
    zjsxwc
    zjsxwc
    May 22, 2017
    7
    只能相对地说不会重复,具体还是要看使用环境:
    https://zhihu.com/question/34876910/answer/88924223
    honeycomb
    honeycomb
    May 22, 2017 via Android
    8
    你是生成了哪种 UUID ?
    类型 1 还是类型 4 ?

    类型 4 是全随机的,要考虑随机数生成器的用法有没有问题。
    类型 1 和时间有关,每秒钟有 1630 亿个可用。
    nanpuyue
    nanpuyue
    May 22, 2017❤️3
    9
    楼主你出门可要小心天上的陨石了~
    tomczhen
    tomczhen
    May 22, 2017 via iPhone
    11
    uuid 也分好几种的,而且多线程并行生成不用一些方法的话也有生成相同 uuid 的可能。
    bozong
    bozong
    May 22, 2017
    12
    Tb 级别数据量?
    ytmsdy
    ytmsdy
    May 22, 2017
    13
    快去买彩票!
    yuhuan66666
    yuhuan66666
    OP
    May 22, 2017
    14
    @honeycomb #8 用的最简单的 UUID.randomUUID()生成的
    icedx
    icedx
    May 22, 2017
    15
    和时间戳绑定一下就好了
    xmh51
    xmh51
    May 22, 2017
    16
    多线程 下 使用?
    jason19659
    jason19659
    May 22, 2017
    17
    找个按照时间戳生成的工具类
    angelface
    angelface
    May 22, 2017
    18
    @yuhuan66666 Type 4 类的是随机数,是有可能重复的。可以换一个 Time-Based 的工具包。
    ooTwToo
    ooTwToo
    May 22, 2017
    20
    试试 twitter 的 snowflake
    honeycomb
    honeycomb
    May 22, 2017
    21
    用版本 1 就可以了

    看到一个类似例子:
    http://bbs.csdn.net/topics/390434666

    按理说 getUUID 背后用的是 UUID 类里一个静态 SecureRandom,随机数的来源是 SecureRandom.nextBytes,不该出现重复问题
    yuhuan66666
    yuhuan66666
    OP
    May 22, 2017
    22
    @honeycomb #21 请问 怎么才能生成版本 1 的 UUID 呢 我看 java API 没提供对应的方法
    momocraft
    momocraft
    May 22, 2017
    23
    @honeycomb "Secure" 的要求是无法预测。在长度有限时要求不重复是不现实的。
    superadmin
    superadmin
    May 22, 2017
    24
    Twitter-Snowflake
    参考:
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    /**
    * tweeter 的 snowflake 移植到 Java:
    * (a) id 构成: 42 位的时间前缀 + 10 位的节点标识 + 12 位的 sequence 避免并发的数字(12 位不够用时强制得到新的时间前缀)
    * 注意这里进行了小改动: snowkflake 是 5 位的 datacenter 加 5 位的机器 id; 这里变成使用 10 位的机器 id
    * (b) 对系统时间的依赖性非常强,需关闭 ntp 的时间同步功能。当检测到 ntp 时间调整后,将会拒绝分配 id
    */

    public class IdWorker {

    private final static Logger logger = LoggerFactory.getLogger(IdWorker.class);

    private final long workerId;
    private final long epoch = 1403854494756L; // 时间起始标记点,作为基准,一般取系统的最近时间
    private final long workerIdBits = 10L; // 机器标识位数
    private final long maxWorkerId = -1L ^ -1L << this.workerIdBits;// 机器 ID 最大值: 1023
    private long sequence = 0L; // 0,并发控制
    private final long sequenceBits = 12L; //毫秒内自增位

    private final long workerIdShift = this.sequenceBits; // 12
    private final long timestampLeftShift = this.sequenceBits + this.workerIdBits;// 22
    private final long sequenceMask = -1L ^ -1L << this.sequenceBits; // 4095,111111111111,12 位
    private long lastTimestamp = -1L;

    private IdWorker(long workerId) {
    if (workerId > this.maxWorkerId || workerId < 0) {
    throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));
    }
    this.workerId = workerId;
    }

    public synchronized long nextId() throws Exception {
    long timestamp = this.timeGen();
    if (this.lastTimestamp == timestamp) { // 如果上一个 timestamp 与新产生的相等,则 sequence 加一(0-4095 循环); 对新的 timestamp,sequence 从 0 开始
    this.sequence = this.sequence + 1 & this.sequenceMask;
    if (this.sequence == 0) {
    timestamp = this.tilNextMillis(this.lastTimestamp);// 重新生成 timestamp
    }
    } else {
    this.sequence = 0;
    }

    if (timestamp < this.lastTimestamp) {
    logger.error(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
    throw new Exception(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
    }

    this.lastTimestamp = timestamp;
    return timestamp - this.epoch << this.timestampLeftShift | this.workerId << this.workerIdShift | this.sequence;
    }

    private static IdWorker flowIdWorker = new IdWorker(1);
    public static IdWorker getFlowIdWorkerInstance() {
    return flowIdWorker;
    }



    /**
    * 等待下一个毫秒的到来, 保证返回的毫秒数在参数 lastTimestamp 之后
    */
    private long tilNextMillis(long lastTimestamp) {
    long timestamp = this.timeGen();
    while (timestamp <= lastTimestamp) {
    timestamp = this.timeGen();
    }
    return timestamp;
    }

    /**
    * 获得系统当前毫秒数
    */
    private static long timeGen() {
    return System.currentTimeMillis();
    }

    public static void main(String[] args) throws Exception {
    System.out.println(timeGen());

    IdWorker idWorker = IdWorker.getFlowIdWorkerInstance();
    // System.out.println(Long.toBinaryString(idWorker.nextId()));
    System.out.println(idWorker.nextId());
    System.out.println(idWorker.nextId());
    }

    }
    aksoft
    aksoft
    May 23, 2017
    25
    啥事也没有绝对的
    julyclyde
    julyclyde
    May 23, 2017
    26
    只要数量有限,那将来必然重复
    无非你比别人早点碰上了而已,有啥好大惊小怪的
    xufeng
    xufeng
    Jul 12, 2017
    27
    重复的概率确实有,如果你的数据量不大,那么应该考虑你的代码是否有问题。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1073 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 68ms · UTC 23:07 · PVG 07:07 · LAX 15:07 · JFK 18:07
    ♥ Do have faith in what you're doing.