不是号称 比被陨石砸中都的概率还小么。。。。。
怎么当一年的主键就重复了好几个呢。。。。
各位大大 都用啥当主键的?
难不成真要 各个字段连成一条+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 3
楼主你出门可要小心天上的陨石了~
|
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
重复的概率确实有,如果你的数据量不大,那么应该考虑你的代码是否有问题。
|