Пространство имен uuid в нескольких goroutines
Я хотел бы создать уникальный идентификатор без столкновений на языке go для масштабируемого приложения.
Википедия рекомендует вариацию UUID в пространстве имен (что я могу предположить только применительно к версии 3 или 5). Википедия конкретно заявляет:
Если для распределенных приложений требуются уникальные идентификаторы, чтобы идентификаторы UUID не конфликтовали даже при объединении данных со многих устройств, случайность начальных чисел и генераторов, используемых на каждом устройстве, должна быть надежной в течение всего срока службы приложения. Если это невозможно, RFC4122 рекомендует использовать вместо этого вариант пространства имен.
У меня есть несколько трудностей с этим
Версии 3 и 5 требуют хеширования данных, что кажется ненужным по следующим причинам:
1.1. Если приложение может использовать те же данные (для которых мне нужен другой идентификатор)
1.2. Я предполагаю, что в терминах утечки данных внутренняя энтропия random() считается защищенной. Я не понимаю, почему криптографическое хеширование необходимо (поскольку, как я полагаю, хеширование требует НАМНОГО больше ресурсов, чем некоторые начальные вычисления).
Пространство имен должно быть значением, которое защитит от коллизий, которые могут возникнуть в среде с высокой степенью параллелизма. В GO рутина может работать параллельно и может использовать тот же начальный размер из-за высокой производительности сервера (как упоминалось в Википедии). Я предполагаю, что лучшим значением для пространства имен является идентификатор программы, поэтому можно избежать коллизий на одной и той же машине. Я не могу найти какой-либо правильный способ получить уникальный идентификатор для текущего выполнения программы.
Если на самом деле Википедия возвращается к версии 4 (случайной) с компонентом пространства имен, как мне создать такое руководство? документы не показывают такой вариант
TL;DR: Как правильно и безопасно генерировать уникальные идентификаторы в GOLang?
1 ответ
Документ утверждает, что: 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.
Это означает, что этот пакет использует случайную силу криптографии / ранда для генерации UUID типа 4. Лично, если бы в реализации не было ошибок, я бы поверил в это, если бы я не генерировал миллиарды идентификаторов в день.
Другой вариант - использовать версию 5: func NewSHA1(space UUID, data []byte) UUID
и передайте ему UUID Vesion 1 в качестве пространства имен и данные из crypto/random в качестве "данных". т.е. как то так:
// 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)
}