生成的最短唯一ID

问题描述 投票:0回答:3

因此我们可以生成一个带有

str(uuid.uuid4())
的唯一 ID,长度为 36 个字符。

是否有另一种方法来生成字符较短的唯一ID?

编辑:

  • 如果 ID 可以用作主键那就更好了
  • 粒度应优于1ms
  • 此代码可以分发,因此我们不能假设时间独立性。
python python-3.x uniqueidentifier
3个回答
12
投票

如果这是用作数据库中的主键字段,请考虑仅使用自动递增整数。

str(uuid.uuid4())
是 36 个字符,但其中有四个无用的破折号 (
-
),并且仅限于 0-9 a-f。

更好的 uuid4,32 个字符:

>>> uuid.uuid4().hex
'b327fc1b6a2343e48af311343fc3f5a8'

或者只是 b64 编码并切片一些随机字节(由您决定以保证唯一性):

>>> base64.b64encode(os.urandom(32))[:8]
b'iR4hZqs9'

4
投票

TLDR

大多数时候,最好在内部处理数字并在外部将它们编码为短 ID。因此,这里有一个适用于 Python3、PowerShell 和 VBA 的函数,它将把 int32 转换为字母数字 ID。像这样使用它:

int32_to_id(225204568)
'F2AXP8'

对于分布式代码,请使用 ULID:https://github.com/mdipierro/ulid

它们更长,但在不同的机器上是独一无二的。

ID 有多短?

它将用 6 个字符编码大约 5 亿个 ID,因此它尽可能紧凑,同时仍然仅使用非模糊的数字和字母

如何获得更短的ID?

如果您想要更紧凑的 ID/代码/序列号,只需更改

chars="..."
定义即可轻松扩展字符集。例如,如果您允许所有小写和大写字母,则在相同的 6 个字符中可以拥有 560 亿个 ID。添加一些符号(如
~!@#$%^&*()_+-=
)即可获得 2080 亿个 ID。

那么你为什么不选择最短的 ID 呢?

我在代码中使用的字符集有一个优点:它生成的 ID 易于复制粘贴(没有符号,因此双击会选择整个 ID),易于阅读而不会出现错误(没有像

 这样的相似字符) 2
Z
)并且相当容易口头交流(仅限大写字母)。仅使用数字是口头交流的最佳选择,但它们并不紧凑。

我确信:给我看代码

Python 3

def int32_to_id(n):
  if n==0: return "0"
  chars="0123456789ACEFHJKLMNPRTUVWXY"
  length=len(chars)
  result=""
  remain=n
  while remain>0:
    pos = remain % length
    remain = remain // length
    result = chars[pos] + result
  return result

Javascript

function int32ToId(n) {
   if (n === 0) return "0";
   const chars = "0123456789ACEFHJKLMNPRTUVWXY";
   const length = chars.length;
   let result = "";
   let remain = n;

   while (remain > 0) {
      const pos = remain % length;
      remain = Math.floor(remain / length);
      result = chars[pos] + result;
   }

   return result;
}
  

PowerShell

function int32_to_id($n){
   $chars="0123456789ACEFHJKLMNPRTUVWXY"
   $length=$chars.length
   $result=""; $remain=[int]$n
   do {
      $pos = $remain % $length
      $remain = [int][Math]::Floor($remain / $length)
      $result = $chars[$pos] + $result
   } while ($remain -gt 0)
   $result
}

VBA

Function int32_to_id(n)
    Dim chars$, length, result$, remain, pos
    If n = 0 Then int32_to_id = "0": Exit Function
    chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
    length = Len(chars$)
    result$ = ""
    remain = n
    Do While (remain > 0)
        pos = remain Mod length
        remain = Int(remain / length)
        result$ = Mid(chars$, pos + 1, 1) + result$
    Loop
    int32_to_id = result
End Function

Function id_to_int32(id$)
    Dim chars$, length, result, remain, pos, value, power
    chars$ = "0123456789ACEFHJKLMNPRTUVWXY"
    length = Len(chars$)
    result = 0
    power = 1
    For pos = Len(id$) To 1 Step -1
        result = result + (InStr(chars$, Mid(id$, pos, 1)) - 1) * power
        power = power * length
    Next
    id_to_int32 = result
End Function

Public Sub test_id_to_int32()
    Dim i
    For i = 0 To 28 ^ 3
        If id_to_int32(int32_to_id(i)) <> i Then Debug.Print "Error, i=", i, "int32_to_id(i)", int32_to_id(i), "id_to_int32('" & int32_to_id(i) & "')", id_to_int32(int32_to_id(i))
    Next
    Debug.Print "Done testing"
End Sub


0
投票

是的。只需使用当前的 UTC 毫秒即可。这个数字永远不会重复。

const uniqueID = new Date().getTime();

编辑

如果很少需要在同一毫秒内生成多个 ID,则此方法没有用,因为该数字的粒度为 1ms。

© www.soinside.com 2019 - 2024. All rights reserved.