全局唯一标识符
全局唯一标识符,简称GUID,是一种由算法生成的唯一标识,通常表示成32个16进制数字(0-9,A-F)组成的字符串,如:{21EC2020-3AEA-1069-A2DD-08002B30309D},它实质上是一个128位长的二进制整数。GUID一词有时也专指微软对UUID标准的实现。
GUID的主要目的是产生完全唯一的数字。在理想情况下,任何计算机和计算机集群都不会生成两个相同的GUID。GUID的总数也足够大,达到了2^128个,所以随机生成两个相同GUID的可能性是非常小的,但并不为0。
由于GUID生成的算法和内部组成结构有多种,且网络上很难找到它详细的生成算法,所以这里将不做介绍。
MongoDB的ObjectId
1) Time
时间戳。将objectid的前4位进行提取,然后按照十六进制转为十进制,这个数字就是一个时间戳。通过时间戳的转换,可以很容易看清时间格式。
2) Machine
机器。接下来的三个字节是所在主机的唯一标识符,一般是机器主机名的散列值,这样就确保了不同主机生成不同的机器hash值,确保在分布式中不造成冲突,这也就是在同一台机器生成的objectId中间的字符串都是一模一样的原因。
3) PID
进程ID。上面的Machine是为了确保在不同机器产生的objectId不冲突,而pid就是为了在同一台机器不同的mongodb进程产生了objectId不冲突,接下来的两位就是产生objectId的进程标识符。
4) INC
自增计数器。前面的九个字节是保证了一秒内不同机器不同进程生成objectId不冲突,最后面的三个字节是一个自动增加的计数器,用来确保在同一秒内产生的objectId也不会发现冲突,允许2^24等于16777216条记录的唯一性。
总的来看,objectId的前4个字节时间戳,记录了数据创建的时间;接下来3个字节代表了所在主机的唯一标识符,确定了不同主机间产生不同的objectId;后2个字节的进程id,决定了在同一台机器下,不同mongodb进程产生不同的objectId;最后通过3个字节的自增计数器,确保同一秒内产生objectId的唯一性。ObjectId的这个主键生成策略,很好地解决了在分布式环境下高并发情况主键唯一性问题。
学习借鉴
由objectId生成规则,我们可以根据实际需求来创建自己的唯一标识,比如:如果不需要考虑并发情况下,我们可以按时间戳四字节,自增ID五字节这样来组织生成唯一标识。
数据的展示
我们知道,二进制转8进制,可以使用421法,转16进制可以使用8421法,八进制由0-7数字组成,16进制由0-9 A-F组成,如:(10111010)2=(272)8=(BA)16。同理,我们可以推出有7进制(周一到周天),26进制(a-z),52进制(a-z A-Z),64进制(a-z,A-Z,0-9,/,+)等及其计算方法。
由转换规则,可以知道,2转8即3位对1位,2转16即4位对1位,2转32,就是5位对1位,2转64就是6位对1位,掌握这个规则对我为接下来减少数据表现位数很有用。我们知道,GUID是用128位二进制表示的(16字节),可以转换成32位16进制表示的字符串或22位64进制表示的字符串,就是这样得出来的。
GUID无损压缩
网络上流行一种做法:
byte[] buffer = Guid.NewGuid().ToByteArray();
long long_guid=BitConverter.ToInt64(buffer, 0)
这样就会得到一个类似于 5472976187161141196 的19位长度的数字序列。对这串十进制数还可以在转换,转换成64进制数表示,可以缩到12位。
两个疑问:
l 既是无损压缩,那么可以还原吗?
l 由上一章节的推理,怎么可以缩到用19位数字表示呢?
MSDN查找BitConverter.ToInt64方法,我们发现这样一段话:
ToInt64 方法将字节转换为索引中startIndex到startIndex + 7,以Int64的值。字节数组中的顺序必须反映字节排序方式的计算机系统的体系结构 ; 有关详细信息,请参阅注解部分中的BitConverter类主题。
真现大白了,原来ToInt64方法,只取buffer从startIndex开始向后加7个字节的值。也就是说,我们16字节的高8个字节被忽略掉了。GUID理想情况下,要2^128个数据才会出现冲突,而转换后,把字节数减半,也就是2^64数据就会出现冲突。
使用低8字节的“GUID”,我的机器运行1个多小时,计算2千万以上数据,没有出现过冲突。
总结
1. 如果低八字节的GUID能满足需求,那我们可以使用低八字节来表示唯一标识,位数我们可以转换成64进制表示,也就是12位就可以了。
2. 某些系统,需要并发产生唯一标识,我们可以根据objectid生成规则,在根据实际需求生成唯一标识。