[翻訳]Golangで良好な一意IDを生成する方法
4464 ワード
手帳アプリを開発していることを想像してみてください.各記事には一意のIDが必要です.調整できれば、一意のIDを生成するのは簡単です.最も簡単な方法は、データベースを使用することです.AUTOINCREMENTプロパティの列を使用して、新しい記事を挿入すると、データベースに一意のIDが生成されます.
しかし、もしあなたが調整できないなら?たとえば、Appがオフラインになったときに一意のIDを生成したい場合は、データベースに接続できません.
協調できない場合に一意のIDを生成する要求は、通常、分散システムから発生する.簡単な解決策はランダムIDを生成することである.16バイトの長さのランダム列を使用すると、同じランダム列を生成する確率はありません.これはよくある問題で、30年以上前にUUID/GUIDという標準を作成しました.
私たちはGUIDよりもっとよくすることができて、1つの良いランダムな一意IDは以下の原則に従います:1、一意性:基本原則、満たさなければなりません.2、並べ替え可能:ランダム一意ID文字列で並べ替え可能.3、時間属性を持つ:同じ時間内に、生成したIDは互いに近い.4、ランダム一意ID文字列は、エスケープすることなくURLの一部とする.5、短いほどいいです.
Goを使用して実装される類似コードは多くなく、1、使用時間をIDの一部とし、IDに時間属性を持たせるというルールに従っている.2、残りの部分をランダムデータで埋めます.3、符号化一意IDは文字列であり、並べ替え可能及びURL安全の条件を満たす.
次に、一意のIDを生成するGoパケットと、生成されたID文字列のフォーマットを示します.
Package
Id
Format
github.com/segmentio/ksuid
0pPKHjWprnVxGH7dEsAoXX2YQvU
4 bytes of time (seconds) + 16 random bytes
github.com/rs/xid
b50vl5e54p1000fo3gh0
4 bytes of time (seconds) + 3 byte machine id + 2 byte process id + 3 bytes random
github.com/kjk/betterguid
-Kmdih_fs4ZZccpx2Hl1
8 bytes of time (milliseconds) + 9 random bytes
github.com/sony/sonyflake
20f8707d6000108
~6 bytes of time (10 ms) + 1 byte sequence + 2 bytes machine id
github.com/oklog/ulid
01BJMVNPBBZC3E36FJTGVF0C4S
6 bytes of time (milliseconds) + 8 bytes random
github.com/chilts/sid
1JADkqpWxPx-4qaWY47~FqI
8 bytes of time (ns) + 8 random bytes
github.com/satori/go.uuid
5b52d72c-82b3-4f8e-beb5-437a974842c
UUIDv4 from
テストページをリフレッシュして、異なる時間IDフォーマットの変化を見ることができます.異なるパッケージを使用して、一意のIDのインスタンスコードを生成します.
完全なインスタンスコードはgenerate-unique-id/mainを参照してください.go
どのバッグを使えばいいですか?
上に列挙されているすべてのバッグはとてもいいです.しかし、個人的には
詳細: https://segment.com/blog/a-brief-history-of-the-uuid/:ksuidの発展の歴史 https://firebase.googleblog.com/2015/02/the-2120-ways-to-ensure-unique_68.html:Betterguidデザインのインスピレーション http://antoniomo.com/blog/2017/05/21/unique-ids-in-golang-part-1/ http://antoniomo.com/blog/2017/05/28/unique-ids-in-golang-part-2/ http://antoniomo.com/blog/2017/06/03/unique-ids-in-golang-part-3/ https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake.html : details of Twitter’s snowflake on which sonyflake is based
本明細書のコード:https://github.com/kjk/go-cookbook/tree/master/generate-unique-idGenerating good unique ids in Go
しかし、もしあなたが調整できないなら?たとえば、Appがオフラインになったときに一意のIDを生成したい場合は、データベースに接続できません.
協調できない場合に一意のIDを生成する要求は、通常、分散システムから発生する.簡単な解決策はランダムIDを生成することである.16バイトの長さのランダム列を使用すると、同じランダム列を生成する確率はありません.これはよくある問題で、30年以上前にUUID/GUIDという標準を作成しました.
私たちはGUIDよりもっとよくすることができて、1つの良いランダムな一意IDは以下の原則に従います:1、一意性:基本原則、満たさなければなりません.2、並べ替え可能:ランダム一意ID文字列で並べ替え可能.3、時間属性を持つ:同じ時間内に、生成したIDは互いに近い.4、ランダム一意ID文字列は、エスケープすることなくURLの一部とする.5、短いほどいいです.
Goを使用して実装される類似コードは多くなく、1、使用時間をIDの一部とし、IDに時間属性を持たせるというルールに従っている.2、残りの部分をランダムデータで埋めます.3、符号化一意IDは文字列であり、並べ替え可能及びURL安全の条件を満たす.
次に、一意のIDを生成するGoパケットと、生成されたID文字列のフォーマットを示します.
Package
Id
Format
github.com/segmentio/ksuid
0pPKHjWprnVxGH7dEsAoXX2YQvU
4 bytes of time (seconds) + 16 random bytes
github.com/rs/xid
b50vl5e54p1000fo3gh0
4 bytes of time (seconds) + 3 byte machine id + 2 byte process id + 3 bytes random
github.com/kjk/betterguid
-Kmdih_fs4ZZccpx2Hl1
8 bytes of time (milliseconds) + 9 random bytes
github.com/sony/sonyflake
20f8707d6000108
~6 bytes of time (10 ms) + 1 byte sequence + 2 bytes machine id
github.com/oklog/ulid
01BJMVNPBBZC3E36FJTGVF0C4S
6 bytes of time (milliseconds) + 8 bytes random
github.com/chilts/sid
1JADkqpWxPx-4qaWY47~FqI
8 bytes of time (ns) + 8 random bytes
github.com/satori/go.uuid
5b52d72c-82b3-4f8e-beb5-437a974842c
UUIDv4 from
テストページをリフレッシュして、異なる時間IDフォーマットの変化を見ることができます.異なるパッケージを使用して、一意のIDのインスタンスコードを生成します.
import (
"github.com/chilts/sid"
"github.com/kjk/betterguid"
"github.com/oklog/ulid"
"github.com/rs/xid"
"github.com/satori/go.uuid"
"github.com/segmentio/ksuid"
"github.com/sony/sonyflake"
)
// To run:
// go run main.go
func genXid() {
id := xid.New()
fmt.Printf("github.com/rs/xid: %s
", id.String())
}
func genKsuid() {
id := ksuid.New()
fmt.Printf("github.com/segmentio/ksuid: %s
", id.String())
}
func genBetterGUID() {
id := betterguid.New()
fmt.Printf("github.com/kjk/betterguid: %s
", id)
}
func genUlid() {
t := time.Now().UTC()
entropy := rand.New(rand.NewSource(t.UnixNano()))
id := ulid.MustNew(ulid.Timestamp(t), entropy)
fmt.Printf("github.com/oklog/ulid: %s
", id.String())
}
func genSonyflake() {
flake := sonyflake.NewSonyflake(sonyflake.Settings{})
id, err := flake.NextID()
if err != nil {
log.Fatalf("flake.NextID() failed with %s
", err)
}
// Note: this is base16, could shorten by encoding as base62 string
fmt.Printf("github.com/sony/sonyflake: %x
", id)
}
func genSid() {
id := sid.Id()
fmt.Printf("github.com/chilts/sid: %s
", id)
}
func genUUIDv4() {
id := uuid.NewV4()
fmt.Printf("github.com/satori/go.uuid: %s
", id)
}
func main() {
genXid()
genKsuid()
genBetterGUID()
genUlid()
genSonyflake()
genSid()
genUUIDv4()
}
完全なインスタンスコードはgenerate-unique-id/mainを参照してください.go
どのバッグを使えばいいですか?
上に列挙されているすべてのバッグはとてもいいです.しかし、個人的には
rs/xid
とsegmentio/ksuid
の2つのバッグが好きです.oklog / ulid
は、カスタムエントロピーの使用を可能にする(ランダム)ソースですが、複雑なAPIを使用する必要があります.sony / sonyflake
は最小ですが最もランダムです.Twitterの設計に基づいて、推文のIDを生成します.簡単にするために、サンプルコードはbase 16のsony / snoflake
をシーケンス化しています.他のライブラリで使用されているbase 62符号化では短くなりますが、他のライブラリではsony / snoflake
に対して開梱即用の機能を提供しています.自分でそれを実現しなければならない.最後の1つは、比較のためにRFC 4112からのUUID v 4である.詳細:
本明細書のコード:https://github.com/kjk/go-cookbook/tree/master/generate-unique-idGenerating good unique ids in Go