[golang] 分布式ID產生演算法Snowflake

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

大部分分布式系統中,對一些互斥資源通常需要一個叢集唯一的ID,比如訊息id,訂單號等。而且很多業務需求往往要求這些ID必須具有先後順序,以方便分頁或者排序。這就要求ID具有兩個特性:

  • 全域唯一
  • 隨時間遞增

Snowflake

Twitter-Snowflake演算法很好的解決了這種需求,它可以非常高效的產生ID,其核心思想如下(圖片來自網路):


snowflake-64bit.jpg
  • 時間戳記。時間戳記段位共41位,單位毫秒,可以使用約70年。為了增加剩餘可用期限,一般都會把起始日期盡量後移而不是直接使用1970-01-01。(ps:如果是使用1970,你的程式只能支援到2039年了)
  • 機器id。用於區分叢集內不同機器,因為Snowflake產生ID是在每台機器上進行的。一般叢集中每個節點都會有一個自己的id標示,如果實在沒有也可以通過grpc,thrift等由master server產生。我們系統的nodeid是通過zookeeper來產生的。
  • 序號。由於高並發的特性,即使時間戳記精確到了毫秒,也有可能出現重複。序號用於同一時間戳記下產生多個id。12位的長度,可以達到每秒上限1000*(2^12)=400W,完全夠用了。

Golang實現

實現代碼如下:

/** Snowflake** 1                                               42           52             64* +-----------------------------------------------+------------+---------------+* | timestamp(ms)                                 | workerid   | sequence      |* +-----------------------------------------------+------------+---------------+* | 0000000000 0000000000 0000000000 0000000000 0 | 0000000000 | 0000000000 00 |* +-----------------------------------------------+------------+---------------+** 1. 41位時間截(毫秒級),注意這是時間截的差值(目前時間截 - 開始時間截)。可以使用約70年: (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69* 2. 10位元據機器位,可以部署在1024個節點* 3. 12位序列,毫秒內的計數,同一機器,同一時間截並發4096個序號*/const (   twepoch        = int64(1483228800000)             //開始時間截 (2017-01-01)   workeridBits   = uint(10)                         //機器id所佔的位元   sequenceBits   = uint(12)                         //序列所佔的位元   workeridMax    = int64(-1 ^ (-1 << workeridBits)) //支援的最大機器id數量   sequenceMask   = int64(-1 ^ (-1 << sequenceBits)) //   workeridShift  = sequenceBits                     //機器id左移位元   timestampShift = sequenceBits + workeridBits      //時間戳記左移位元)// A Snowflake struct holds the basic information needed for a snowflake generator workertype Snowflake struct {   sync.Mutex   timestamp int64   workerid  int64   sequence  int64}// NewNode returns a new snowflake worker that can be used to generate snowflake IDsfunc NewSnowflake(workerid int64) (*Snowflake, error) {   if workerid < 0 || workerid > workeridMax {       return nil, errors.New("workerid must be between 0 and 1023")   }   return &Snowflake{       timestamp: 0,       workerid:  workerid,       sequence:  0,   }, nil}// Generate creates and returns a unique snowflake IDfunc (s *Snowflake) Generate() int64 {   s.Lock()   now := time.Now().UnixNano() / 1000000   if s.timestamp == now {       s.sequence = (s.sequence + 1) & sequenceMask       if s.sequence == 0 {           for now <= s.timestamp {               now = time.Now().UnixNano() / 1000000           }       }   } else {       s.sequence = 0   }   s.timestamp = now   r := int64((now-twepoch)<<timestampShift | (s.workerid << workeridShift) | (s.sequence))   s.Unlock()   return r}

參考資料:https://github.com/twitter/snowflake

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.