惟一ID算法Snowflake
相信你們都不墨生,他是Twitter公司提出來的算法。很是普遍的應用在各類業務系統裏。也由於Snowflake
的靈活性和缺點,對他的改造層出不窮,比百度的UidGenerator、美團的Leaf、索尼的Sonyflake等等。這篇帖子主要是講一下原生的Snowflake
算法、缺點及改造方案,並分析索尼的Sonyflake源碼對原生Snowflake
的改造,git
原生Snowflake
算法使用一個64 bit
的整型數據,根據當前的時間來生成ID。 原生Snowflake
結構以下:github
原生的Snowflake
算法是徹底依賴於時間的,若是有時鐘回撥的狀況發生,會生成重複的ID,市場上的解決方案也是很是多的:算法
5
毫秒,就等待,而後再生成。或者就直接報錯,交給業務層去處理。我的比較推薦的是最後一個方案服務器
找2bit位做爲時鐘回撥位,發現有時鐘回撥就將回撥位加1,達到最大位後再從0開始進行循環。ui
好比下圖這樣,從機器位上,均出來2位作回撥位:阿里雲
Snowflake
算法是至關靈活的,咱們能夠根據本身的業務須要,對63 bit的的各個部分進行增減。索尼公司的Sonyflake對原生的Snowflake
進行改進,從新分配了各部分的bit位:spa
Snowflake
不一樣的地方是,Sonyflake
是以10毫秒爲單位來保存時間的。這樣的話,可使用的年限爲 174年
比Snowflake
長太多了。const sonyflakeTimeUnit = 1e7 // nsec, i.e. 10 msec func toSonyflakeTime(t time.Time) int64 { return t.UTC().UnixNano() / sonyflakeTimeUnit } func currentElapsedTime(startTime int64) int64 { return toSonyflakeTime(time.Now()) - startTime }
8bit 作爲序列號,每10毫最大生成256個,1秒最多生成25600個,比原生的Snowflake
少好多,若是感受不夠用,目前的解決方案是跑多個實例生成同一業務的ID來彌補。code
16bit 作爲機器號,默認的是當前機器的私有IP的最後兩位blog
sf.machineID, err = lower16BitPrivateIP()
func lower16BitPrivateIP() (uint16, error) { ip, err := privateIPv4() if err != nil { return 0, err } return uint16(ip[2])<<8 + uint16(ip[3]), nil }
對於時間回撥的問題Sonyflake
簡單暴力,就是直接等待 :ip
func (sf *Sonyflake) NextID() (uint64, error) { const maskSequence = uint16(1<<BitLenSequence - 1) sf.mutex.Lock() defer sf.mutex.Unlock() current := currentElapsedTime(sf.startTime) if sf.elapsedTime < current { sf.elapsedTime = current sf.sequence = 0 } else { // sf.elapsedTime >= current sf.sequence = (sf.sequence + 1) & maskSequence if sf.sequence == 0 { sf.elapsedTime++ overtime := sf.elapsedTime - current time.Sleep(sleepTime((overtime))) } } return sf.toID() }