这可能吗?我听说卡桑德拉也有类似的事情:https://datastax.github.io/python-driver/api/cassandra/util.html
我一直在使用一个ISO timestamp
和一个uuid4
相连,但是结果太大了(58个字符),而且可能会过度使用。在
在我的上下文中,保持一个序列号不起作用(DynamoDB NoSQL)
值得注意的是,对于我的应用程序来说,批处理/同一秒创建的项是否是随机顺序并不重要,只要uid
不会崩溃。在
我对最大长度没有具体限制,理想情况下,我希望看到不同长度的不同碰撞概率,但它必须小于58(我最初的尝试)
这将与DynamoDB(NoSQL数据库)一起用作排序键
你应该能够在135年的时间范围内用32位编码精确到秒的时间戳。这将只需要8个字符来表示十六进制。添加到uuid的十六进制表示中(32个十六进制字符),总共只有40个十六进制字符。在
以这种方式编码时间戳需要选择一个基准年(例如2000年)并计算到当前日期为止的天数(时间戳)。用这个天数乘以86400,然后加上从午夜开始的秒数。这将为您提供小于2^32的值,直到您达到2135年。在
请注意,您必须保持时间戳前缀的十六进制编码形式的前导零,以便字母数字排序保留时间顺序。
在时间戳中多加几位,就可以增加时间范围和/或精度。再加上8个比特(两个十六进制字符),你可以用最长270年的时间精确到百分之一秒。
请注意,您不必在以10为基数的范围内对秒数进行建模。对于相同数量的字符,将其分解为128个而不是100个,从而获得最佳的位使用率。随着年份范围的翻倍,它仍然适合8位(2个十六进制字符)
在时间精度(即每秒或每100或128秒)内的碰撞概率由uuid的范围决定,因此对于选定的精度,碰撞概率将为1/2^128。提高时间戳的精度对减少碰撞概率的影响最大。它也是对密钥总大小影响最小的因素。在
更高效的字符编码:27到29个字符键
您可以通过将其编码为64位而不是16位(这将给您27到29个字符)来显著减小密钥的大小(取决于您对精度的选择)
注意,对于时间戳部分,您需要使用一个以整数作为输入并保留数字字符排序序列的编码函数。在
例如:
在编码之前,您可以将时间戳和uuid合并为一个数字,而不是将两个编码的值串联起来,从而节省更多的字符。在
encode64()函数每6位需要一个字符。在
因此,135年来精确到第二位:(32+128)/6=26.7>;27个字符
而不是(32/6=5.3>;6)+(128/6=21.3>;22)==>;28个字符
^{pr2}$有270年的跨度和第128秒的精度:(40+128)/6=28个个字符
使用29字符,您可以将精度提高到秒的1024,年范围提高到2160年。在
UUID屏蔽:17到19个字符的键
为了更高效,您可以去掉uuid的前64位(已经是时间戳)并将其与您自己的时间戳相结合。这将为您提供长度为17到19个字符的密钥,几乎不会丢失避免碰撞的损失(取决于您对精度的选择)。在
整数/数字键?
最后,如果您的数据库支持非常大的整数或数字字段(140位或更多)作为键,则不必将组合的数字转换为字符串。直接用它当钥匙就行了。
timeStamp<<128 | int(uid)
的数字序列将遵循时间顺序。在在您链接的文章中,cassandra.util.uuid_from_time(time_arg, node=None, clock_seq=None)[source]似乎正是您要查找的内容。在
没有什么卡桑德拉是针对1型UUID的。。。在
为什么uuid.uuid1不是连续的
uuid.uuid1(node=None, clock_seq=None)
有效:1582-10-15 00:00:00
之后的100ns间隔数)若不提供任何参数,则调用系统函数生成uuid。在这种情况下:
clock_seq
)。在python3.7中this info is now available。在如果您提供
clock_seq
或node
,那么“使用纯python实现”。在这种情况下,即使是clock_seq
的“固定值”:clock_seq
部分是随机生成的。但这并不是关键的annymore,因为时间戳是连续的和唯一的。在clock_seq, node
调用uuid1
的进程,如果在“相同的100ns时间间隔”内调用,则可能返回冲突的值)重用
uuid.uuid1
的解决方案很容易看出,您可以通过提供}参数(使用python实现)使
clock_seq
或{uuid1
连续。在多流程问题
但是如果在同一台机器上运行一些并行进程,则:
node
默认为uuid.get_node()
对所有进程都是相同的clock_seq
对于某些进程来说,几乎没有相同的机会(几率为1/16384)那可能会导致冲突!这是使用
uuid.uuid1
在同一台机器上的并行进程中,除非您可以从Python3.7访问{a3}。在如果您确保还为运行此代码的每个并行进程将
node
设置为唯一值,则不应发生冲突。在即使您使用的是SafeUUID,并设置了unique
node
,如果它们是在不同的进程中生成的,那么仍然可以有非连续的(但唯一的)id。在如果一些与锁相关的开销是可接受的,那么您可以将
clock_seq
存储在某些外部原子存储器中(例如在"locked"文件中),并在每次调用时递增它:这允许在所有并行进程上对node
具有相同的值,并且还会使id-s连续。对于所有并行进程都是使用multiprocessing
创建的子进程的情况:clock_seq
可以使用multiprocessing.Value
来“共享”因此,您必须始终记住:
如果在同一台计算机上运行多个进程,则必须:
确保
node
的唯一性。这个解决方案的问题是:您不能确定在相同的100ns间隔内从不同的进程中生成顺序id。但这是一个非常“轻”的操作,在进程启动时执行一次,并通过“添加”一些东西到默认节点,例如int(time.time()*1e9) - 0x118494406d1cc000
,或者通过从计算机级原子数据库中添加一些计数器来实现。确保“机器级原子
clock_seq
”和同一台机器上所有进程的node
。这样,您将有一些“锁定”clock_seq
的开销,但是即使在相同的100ns间隔内在不同的进程中生成id-s,id-s也保证是连续的(除非您是从同一进程中的多个线程调用uuid)。对于不同机器上的进程:
要么你必须使用一些“全球柜台服务”;
在同一时间间隔内,在相同的机器上可能生成不同的ID。
缩小id的大小
{30的方法很容易实现{30位,因此从scratch生成id很容易}部件:
^{pr2}$注意事项:
碰撞几率
clock_seq
或唯一node
的多个进程:不可能发生冲突随机集
node
(48位,“固定”时间)的多个进程:有机会在几个进程中发生
node
碰撞:每秒在2个进程中与“碰撞”
node
发生单次碰撞的几率:对于“时间戳”间隔为100ns(默认值为
uuid.uuid1
,在我的代码中,timestamp_multiplier == 1e7
):与3.72e-19 * avg_call_frequency²
成比例对于10 ns(
timestamp_multiplier == 1e8
)的“时间戳”间隔:与3.72e-21 * avg_call_frequency²
相关问题 更多 >
编程相关推荐