要求:
UUID 是 32 位的,short UUID 总觉得有坑。。
是否有什么好的实现方式?
1
Chyroc 2018-05-28 18:57:35 +08:00 2
uuid 是 16 字节,如果是 16 进制( 0-9a-f )的,会有 32 个字符,有点长;所以考虑使用 64 进制,这样的话只有 16 个字符串;
可以参考这个文章: https://blog.chyroc.cn/articles/2017-8-2-247355155.html |
2
lurenw 2018-05-28 20:16:53 +08:00 1
snowflake,64bit,刚好可以压缩成 16 个字符( 16 进制)
|
3
beginor 2018-05-28 20:28:38 +08:00 via Android
mark,期待万能的 V 友
|
4
lukefan 2018-05-28 20:31:03 +08:00 1
mongodb 的 objectid, 12bit
|
5
MiffyLiye 2018-05-28 20:41:17 +08:00 1
UUID 类型是 128 bit,即 16 byte,并不是 32 个字符。
你如果用 MySQL 没有原生 UUID 类型的话,我还可以推荐一下 https://www.npmjs.com/package/snowflake-codon PostgreSQL 原生支持 UUID 就直接用吧。 |
6
ericls 2018-05-28 20:45:41 +08:00 via iPhone 1
hashids?
|
7
fuyufjh 2018-05-28 20:49:06 +08:00 1
snowflake +1
|
8
changnet 2018-05-28 23:47:45 +08:00 via Android 1
我之前设计这个东西也想了很久。16bit 基本不可能做出来,在单一数据库里从 0 自增都不够用,算上分布式更加不够。最简单的方法就是 uuid 转 64 进制,随处可用。mongodb 的 object id 只是做集群还行。我做游戏的还要考虑合服,只能用数字,不支持 int64 这些,没有一个适用的。自己按具体需要设计一个,无非就是把时间戳,自增,业务唯一标识拼接一下,然后压缩处理,比如转 64 进制,时间戳不从 1970 算。
网上还有些从概率上算的,认为碰撞概率小于多少便是唯一,那个确实比较短,看你的业务是不是能用 |
9
sutra 2018-05-29 00:10:35 +08:00 1
曾经拿 Javascript 写了一段让它表现得更短的代码,思路也就是 #1 的用更多的字符来编码:
通常我们用 0-F 16 个字符来编码,我这里改成了用 62 个字符来编码: (不过由于 Javascript 浮点数最大能表达的数字的问题,我这段代码并不是最佳的) // var DIGITS = "0123456789ABCDEF" // var DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$&'()*+/:;=?@._~" var DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var BASE = DIGITS.length var SEPARATOR = '-' function encodeNumber(num) { var digit var residual = Math.floor(num) var result = '' do { digit = residual % BASE result = DIGITS.charAt(digit) + result residual = Math.floor(residual / BASE) } while (residual > 0) return result } function decodeNumber(str) { var result = 0 var digits = str.split('') var e, l = digits.length for (e = 0; e < l; e++) { result = (result * BASE) + DIGITS.indexOf(digits[e]) } return result } function encodeUUID(uuid) { var results = [] var s = uuid.replace(/-/g, '').toUpperCase() var uuidInts = [ parseInt(s.substring(0, 8), 16), parseInt(s.substring(8, 16), 16), parseInt(s.substring(16, 24), 16), parseInt(s.substring(24, 32), 16) ] var i, l = uuidInts.length for (i = 0; i < l; i++) { results.push(encodeNumber(uuidInts[i])) } return results.join(SEPARATOR) } function decodeUUID(str) { var uuidStrs = str.split(SEPARATOR) var i, l = uuidStrs.length var result = '' var pad = '00000000' var s for (i = 0; i < l; i++) { s = decodeNumber(uuidStrs[i]).toString(16) s = pad.substring(0, pad.length - s.length) + s result += s } return result.replace(/([A-Za-z0-9]{8})([A-Za-z0-9]{4})([A-Za-z0-9]{4})([A-Za-z0-9]{4})([A-Za-z0-9]{12})/, "$1-$2-$3-$4-$5").toUpperCase() } module.exports = { encodeUUID: encodeUUID, decodeUUID: decodeUUID } |
10
owt5008137 2018-05-29 00:41:00 +08:00 via Android 1
https://github.com/atframework/atsf4g-co/blob/sample_solution/src/server_frame/rpc/db/uuid.cpp#L79
一级池 id 使用数据库自增,二级自己分配的一种方法。uint64,单个 type_id 内唯一 |
11
honeycomb 2018-05-29 08:23:59 +08:00 via Android 1
snowflake 8 字节,mongo 的 object 12 字节,udid (储存成 binary 的话) 16 字节
|
12
sujin190 2018-05-29 09:30:02 +08:00 1
snowflake 麻烦是节点位太小了,很难自动根据当前部署机器和进程信息自动生成节点 id,在自动化分布式部署的时候可能会很麻烦
mongodb 的 bson objectid 是 12 自己,base64 编码之后就是 16 字符啊,这就好了啊 |
13
Chyroc 2018-06-01 17:33:15 +08:00
|