python uuid1作为时间戳是连续的吗?

python uuid1作为时间戳是连续的吗?,python,uuid,Python,Uuid,Python声明uuid1使用当前时间来形成uuid值。但我找不到确保UUID1是顺序的引用 >>> import uuid >>> u1 = uuid.uuid1() >>> u2 = uuid.uuid1() >>> u1 < u2 True >>> 导入uuid >>>u1=uuid.uuid1() >>>u2=uuid.uuid1() >>>u1>> 来自: 根据主机ID、序列号和当前时

Python声明uuid1使用当前时间来形成uuid值。但我找不到确保UUID1是顺序的引用

>>> import uuid
>>> u1 = uuid.uuid1()
>>> u2 = uuid.uuid1()
>>> u1 < u2
True
>>> 
导入uuid >>>u1=uuid.uuid1() >>>u2=uuid.uuid1() >>>u1>> 来自:

根据主机ID、序列号和当前时间生成UUID。如果未指定节点,则使用getnode()获取硬件地址。如果给定时钟顺序,则将其用作序列号;否则,选择随机14位序列号

由此,我推断MAC地址首先是一个(可能是随机的)序列号,然后是当前时间。因此,即使对于由同一台机器/进程生成的UUID,我也不希望保证它们是单调递增的。

但并非总是:

>>> def test(n):
...     old = uuid.uuid1()
...     print old
...     for x in range(n):
...             new = uuid.uuid1()
...             if old >= new:
...                     print "OOops"
...                     break
...             old = new
...     print new
>>> test(1000000)
fd4ae687-3619-11e1-8801-c82a1450e52f
OOops
00000035-361a-11e1-bc9f-c82a1450e52f
UUID不连续 不,标准UUID并不意味着是顺序的

显然,有人尝试使用guid(微软对uuid的扭曲)使它们按顺序排列,以帮助在某些数据库场景中提高性能。但是,连续性并不是UUID的意图。

MAC是最后一个,不是第一个 不,在标准UUID中,MAC地址不是第一个组件。MAC地址是版本1 UUID中的最后一个组件。

不要假设UUID是哪种类型的 UUID的各种版本旨在相互兼容。因此,期望您始终拥有版本1 UUID可能是不合理的。其他程序员可能会使用其他版本

规范
请阅读UUID规范。只有十几页长

我偶然发现了一个可能的答案,来自

字典时间序 在所有原语类型中,Cassandra支持类型1(基于时间和服务器)和类型4(随机)的UUID值

UUID(唯一通用标识符)的主要用途是在潜在的分布式环境中获得真正唯一的标识符

Cassandra确实支持版本1 UUID。它通过结合计算机的MAC地址和自公历开始以来的100纳秒间隔数,为您提供一个唯一标识符

正如您所见,精度仅为100纳秒,但幸运的是,它与时钟序列混合,增加了随机性。此外,MAC地址还用于计算UUID,因此在一个计算机集群上发生冲突的可能性很小,除非您需要处理大量数据(别忘了,不是每个人都是Twitter或Facebook)

UUID(尤其是TimeUUID)最相关的用例之一是将其用作列键。由于Cassandra列键是排序的,因此我们可以利用此功能对列族进行自然排序

Hector客户端提供的默认com.eaio.uuid.uuid的问题是,它不容易使用。作为一个ID,您可能需要将这个值从服务器带到视图层,这就是问题所在

基本上,com.eaio.uuid.uuid重写toString()以提供uuid的字符串表示形式。但是,此字符串格式无法按字典顺序排序

下面是一些连续生成的TimeUUID:

8e4cab00-c481-11e1-983b-20cf309ff6dc在一些t1
2b6e3160-c482-11e1-addf-20cf309ff6dc在t2>t1的一些t2处
“2b6e3160-c482-11e1-addf-20cf309ff6dc”。相比(“8e4cab00-c481-11e1-983b-20cf309ff6dc”)
给出了-6的含义,即“2b6e3160-c482-11e1-addf-20cf309ff6dc”“8e4cab00-c481-11e1-983b-20cf309ff6dc”少,这是不正确的

TimeUUID的当前文本显示拆分如下:

time\u low–time\u mid–time\u high\u和\u version–variant\u和\u sequence–节点
如果我们从time\u high\u和\u version开始重新排序,那么我们可以按字典顺序对其排序:

time\u high\u和\u version–time\u mid–time\u low–variant\u和\u sequence–节点
实用程序类别如下所示:

public static String reorderTimeUUId(String originalTimeUUID)
    {
        StringTokenizer tokens = new StringTokenizer(originalTimeUUID, "-");
        if (tokens.countTokens() == 5)
        {
            String time_low = tokens.nextToken();
            String time_mid = tokens.nextToken();
            String time_high_and_version = tokens.nextToken();
            String variant_and_sequence = tokens.nextToken();
            String node = tokens.nextToken();

            return time_high_and_version + '-' + time_mid + '-' + time_low + '-' + variant_and_sequence + '-' + node;

        }

        return originalTimeUUID;
    }
时间UUID变为:

11e1-c481-8e4cab00-983b-20cf309ff6dc
11e1-c482-2b6e3160-addf-20cf309ff6dc
现在我们得到:

"11e1-c481-8e4cab00-983b-20cf309ff6dc".compareTo("11e1-c482-2b6e3160-addf-20cf309ff6dc") = -1

无参数使用
uuid.uuid1()
会给出非顺序的结果(),但如果设置
clock_seq
node
参数,则可以很容易地将其设置为顺序(因为在这种情况下
uuid1
使用python实现,保证在当前进程中有
时间戳
部分uuid):

导入时间
从uuid导入uuid1,获取节点
从随机导入getrandbits
_my_clock_seq=getrandbits(14)
_my_node=getnode()
def顺序_uuid(节点=无):
返回uuid1(节点=节点,时钟顺序=\u我的时钟顺序)
def alt_sequential_uuid(时钟顺序=无):
返回uuid1(节点=_我的节点,时钟顺序=时钟顺序)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
从itertools导入计数
old_n=uuid1()#“本机”
old_s=顺序的_uuid()#顺序的
本机冲突索引=无
t_0=时间。时间()
对于计数()中的x:
new_n=uuid1()
new_s=顺序_uuid()
如果旧索引>新索引而非本机冲突索引:
本机冲突索引=x
如果旧的>=新的:
打印(“OOops:'sequential_uuid()`'的非顺序结果”)
打破
如果(x>=10*0x3fff和time.time()-t\u 0>30)或(本机冲突索引和x>2*本机冲突索引):
打印('sequential_uuid()`'没有问题)
打破
旧的=新的
旧的=新的
打印(f'Conflicts for`uuid.uuid1()`:{bool(原生冲突索引)}')
打印(f“尝试:{x}”)
多流程问题 但是如果您在同一台机器上运行一些并行进程,那么:

  • 默认为
    uuid.get\u node()
    node
    对于所有进程都是相同的
  • clock_seq
    的成功几率很小