命名空间uuid在多个goroutines中

时间:2014-12-21 17:50:00

标签: go uuid rfc4122

我想创建一个"无碰撞" go语言中的唯一ID,用于高度可扩展的应用程序。

维基百科推荐UUID的命名空间变体(我只能假设参考版本3或5) Wikipedia具体说明:

  

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

我对此有一些困难

  1. 第3版和第5版要求对数据进行哈希处理,这似乎是一个不必要的事情,因为它有以下几个原因:

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

    1.2。我假设在数据泄漏术语中内部随机()熵被认为是安全的我不明白为什么需要进行密码学散列(因为散列我猜想需要更多的资源然后进行一些种子计算)。

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

  3. 如果事实上维基百科逆转到版本4(随机)与命名空间组件,我如何生成这样的guid? docs没有显示此类选项

  4. TL; DR: 如何在GOLang中正确安全地,可靠地生成独特的ID?

1 个答案:

答案 0 :(得分: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 uuids。就个人而言,如果实施中没有任何错误,我相信除非我每天产生数十亿的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)

}