不是号称 比被陨石砸中都的概率还小么。。。。。
怎么当一年的主键就重复了好几个呢。。。。
各位大大 都用啥当主键的?
难不成真要 各个字段连成一条+UUID 生成的字符串,再算成 SHA512 当主键吗???
太复杂了吧。。。。
![]() | 1 knightdf 2017-05-22 13:28:48 +08:00 没人说不重复啊。。。 |
![]() | 2 lonenol 2017-05-22 13:30:33 +08:00 各种算法一大堆,随便 Goolebaidubing 一下 |
![]() | 3 congeec 2017-05-22 13:34:18 +08:00 出现重复的就二次 hash 呗 |
![]() | 4 oh 2017-05-22 13:34:33 +08:00 via iPhone 好想知道楼主的业务一年业务量是多少,出现了好几条重复 |
![]() | 5 watzds 2017-05-22 13:36:48 +08:00 via Android 也可能代码有 bug |
![]() | 6 wu1990 2017-05-22 13:38:14 +08:00 数据量多大 |
![]() | 7 zjsxwc 2017-05-22 13:38:33 +08:00 只能相对地说不会重复,具体还是要看使用环境: https://zhihu.com/question/34876910/answer/88924223 |
8 honeycomb 2017-05-22 13:38:49 +08:00 via Android 你是生成了哪种 UUID ? 类型 1 还是类型 4 ? 类型 4 是全随机的,要考虑随机数生成器的用法有没有问题。 类型 1 和时间有关,每秒钟有 1630 亿个可用。 |
![]() | 9 nanpuyue 2017-05-22 13:39:04 +08:00 ![]() 楼主你出门可要小心天上的陨石了~ |
![]() | 10 denghongcai 2017-05-22 13:41:12 +08:00 |
![]() | 11 tomczhen 2017-05-22 13:48:27 +08:00 via iPhone uuid 也分好几种的,而且多线程并行生成不用一些方法的话也有生成相同 uuid 的可能。 |
![]() | 12 bozong 2017-05-22 13:56:35 +08:00 Tb 级别数据量? |
![]() | 13 ytmsdy 2017-05-22 14:01:22 +08:00 快去买彩票! |
14 yuhuan66666 OP @honeycomb #8 用的最简单的 UUID.randomUUID()生成的 |
15 icedx 2017-05-22 14:11:39 +08:00 和时间戳绑定一下就好了 |
![]() | 16 xmh51 2017-05-22 14:22:35 +08:00 多线程 下 使用? |
![]() | 17 jason19659 2017-05-22 14:35:12 +08:00 找个按照时间戳生成的工具类 |
![]() | 18 angelface 2017-05-22 14:41:41 +08:00 @yuhuan66666 Type 4 类的是随机数,是有可能重复的。可以换一个 Time-Based 的工具包。 |
![]() | 19 magicdawn 2017-05-22 14:43:38 +08:00 |
![]() | 20 ooTwToo 2017-05-22 14:53:55 +08:00 试试 twitter 的 snowflake |
21 honeycomb 2017-05-22 16:16:36 +08:00 用版本 1 就可以了 看到一个类似例子: http://bbs.csdn.net/topics/390434666 按理说 getUUID 背后用的是 UUID 类里一个静态 SecureRandom,随机数的来源是 SecureRandom.nextBytes,不该出现重复问题 |
22 yuhuan66666 OP @honeycomb #21 请问 怎么才能生成版本 1 的 UUID 呢 我看 java API 没提供对应的方法 |
![]() | 24 superadmin 2017-05-22 17:41:46 +08:00 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()); } } |
25 aksoft 2017-05-23 08:32:14 +08:00 啥事也没有绝对的 |
26 julyclyde 2017-05-23 14:58:15 +08:00 只要数量有限,那将来必然重复 无非你比别人早点碰上了而已,有啥好大惊小怪的 |
![]() | 27 xufeng 2017-07-12 00:10:20 +08:00 重复的概率确实有,如果你的数据量不大,那么应该考虑你的代码是否有问题。 |