golang 分散式id生成器
阿新 • • 發佈:2022-04-10
在高併發場景中,通常需要像mysql中那樣的自增主鍵一樣的不會重複且自增的id生成
twitter的snowflake就是一種典型的解法,id數值長64位,是一個int64型別,被分為四個部分:
- 最高位不使用
- 41位表示收到請求的時間戳,單位為毫秒
- 5位表示資料中心的id
- 5位表示機器例項的id
- 12位迴圈自增id,1111,1111,1111後歸零
這樣的機制可以保證一臺機器在一毫秒內產生4096條訊息,一秒總共409.6萬條訊息
資料中心id配合例項id一共有10位,每個資料中心可以部署32臺例項,搭建32個數據中心,所以一共存在1024個例項
41位時間戳可以使用69年
1. github.com/bwmarrin/snowflake
github.com/bwmarrin/snowflake是一個輕量級的snowflake實現
首先需要引入依賴
go get github.com/bwmarrin/snowflake
這個庫使用起來也非常簡單
func main(){ node,err:=snowflak.NewNode(1) if err!=nil{ println(err.Error()) os.Exit(1) } for i:=0;i<20;i++{ id:=node.Generate() fmt.Printf("int64 ID: %d\n",id) fmt.Printf("string ID: %s\n",id) fmt.Printf("base2 ID: %s\n",id.Base2()) fmt.Printf("base64 ID: %s\n",id.Base64()) fmt.Printf("ID time: %d\n",id.Time()) fmt.Printf("ID node: %d\n",id.Node()) fmt.Printf("ID step: %d\n",id.Step()) fmt.Println("--------------------------------") } }
這個庫是一個單檔案,其中提供了我們可以定製的引數
其中Epoch是起始時間、NodeBits是例項id的長度,預設10位、StepBits是自增id的長度,預設12位
2. github.com/sony/sonyflake
snoyflake側重於多主機多例項的生命週期和效能,所以與snowflake使用了不同的位分配:
- 比snowflake更長的生命週期,174年
- 能執行在更多的例項上,216個
- 生成id的速度比snowflake慢,10ms內最多生成28個
snoyflake在啟動階段需要配置引數,主要是一個Setting結構體
type Settings struct { StartTime time.Time // 起始時間,預設2014-09-01 00:00:00 +0000 UTC MachineID func() (uint16, error) // 返回例項ID的函式,如果不定義此函外,預設用本機ip的低16位 CheckMachineID func(uint16) bool // 驗證例項ID/計算機ID的唯一性,返回true時才建立 }
我們需要自己實現這兩個函式:
func getMachineID() (uint16, error) { var machineID uint16 = 6 return machineID, nil } func checkMachineID(machineID uint16) bool { existsMachines := []uint16{1, 2, 3, 4, 5} for _, v := range existsMachines { if v == machineID { return false } } return true }
func main() { t, _ := time.Parse("2006-01-02", "2021-01-01") settings := sonyflake.Settings{ StartTime: t, MachineID: getMachineID, CheckMachineID: checkMachineID, } sf := sonyflake.NewSonyflake(settings) for i := 0; i < 10; i++ { id, err := sf.NextID() if err != nil { fmt.Println(err) os.Exit(1) } fmt.Println(id) } }