-1

我想用 go 语言创建一个“无冲突”的唯一 id,用于高度可扩展的应用程序。

维基百科推荐 UUID 的命名空间变体(我只能假设是指版本 3 或 5) 维基百科特别指出:

在分布式应用程序需要唯一标识符的情况下,即使合并来自多个设备的数据,UUID 也不会发生冲突,每个设备上使用的种子和生成器的随机性在应用程序的生命周期内必须是可靠的。如果这不可行,RFC4122 建议使用命名空间变体。

我在这方面遇到了一些困难

  1. 版本 3 和 5 需要对数据进行哈希处理,这似乎是不必要的事情,原因如下:

    1.1。我的应用程序可能使用相同的数据(我想要不同的 id)

    1.2. 我假设在数据泄漏方面,内部 random() 熵被认为是安全的,我不明白为什么需要加密散列(因为我猜散列需要比一些种子计算更多的资源)。

  2. 命名空间应该是一个值,可以防止在高并发环境中可能出现的冲突。在 GO 中,goroutine 可以并行运行,并且由于服务器性能高可能使用相同的种子(如维基百科所述)。我假设命名空间的最佳值是 goroutine 的 id,因此可以避免在同一台机器上发生冲突。我找不到任何正确的方法来检索当前 goroutine 执行的唯一 id。

  3. 如果实际上维基百科使用命名空间组件恢复到版本 4(随机),我该如何生成这样的 guid?文档没有显示这种选项

TL;DR: 如何在 GOLang 中正确安全且可扩展地生成唯一 ID?

4

1 回答 1

2

该文档指出:func NewRandom() - returns a Random (Version 4) UUID or panics. The strength of the UUIDs is based on the strength of the crypto/rand package.

这意味着这个包正在使用 crypto/rand 加密强度随机来生成类型 4 uuid。就个人而言,如果实现中没有错误,我相信除非我每天生成数十亿个 id。

另一种选择是使用版本 5: func NewSHA1(space UUID, data []byte) UUID,并将 Vesion 1 UUID 作为命名空间,并将来自加密/随机的数据作为“数据”。即是这样的:

// this is a static namespace for this machine, say
var namespace = uuid.NewUUID()


// generate a random UUID with the global namespace
func NewNamespacedRandom() (uuid.UUID, error) {

    // read 16 crypto-random bytes
    rnd := make([]byte, 16)
    if _, err := rand.Read(rnd); err != nil {
        return nil, err
    }

    return uuid.NewSHA1(namespace, rnd), nil
}

func main() {

    u, err := NewNamespacedRandom()
    if err != nil {
        panic(err)
    }
    fmt.Println(u)

}
于 2014-12-21T18:25:05.053 回答