ZBLOG

golang 实现雪花Id

雪花Id是Twitter提出的一种分布式唯一ID生成算法,可以使用golang实现。

具体实现如下:

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "strconv"
  6. "sync"
  7. "time"
  8. )
  9. // 定义常量
  10. const (
  11. workerIdBits = 5
  12. datacenterIdBits = 5
  13. sequenceBits = 12
  14. maxWorkerId = -1 ^ (-1 << workerIdBits) // 31
  15. maxDatacenterId = -1 ^ (-1 << datacenterIdBits) // 31
  16. timeLeftShift = sequenceBits + workerIdBits + datacenterIdBits
  17. workerLeftShift = sequenceBits
  18. datacenterLeftShift = sequenceBits + workerIdBits
  19. sequenceMask = -1 ^ (-1 << sequenceBits) // 4095
  20. )
  21. type Snowflake struct {
  22. mutex sync.Mutex
  23. startTime int64
  24. datacenterId int64
  25. workerId int64
  26. sequence int64
  27. }
  28. func NewSnowflake(datacenterId, workerId int64) *Snowflake {
  29. if datacenterId < 0 || datacenterId > maxDatacenterId {
  30. panic(fmt.Sprintf("datacenter Id can't be greater than %d or less than 0", maxDatacenterId))
  31. }
  32. if workerId < 0 || workerId > maxWorkerId {
  33. panic(fmt.Sprintf("worker Id can't be greater than %d or less than 0", maxWorkerId))
  34. }
  35. return &Snowflake{
  36. startTime: getTime(),
  37. datacenterId: datacenterId,
  38. workerId: workerId,
  39. sequence: 0,
  40. }
  41. }
  42. func (sf *Snowflake) GetId() int64 {
  43. sf.mutex.Lock()
  44. defer sf.mutex.Unlock()
  45. now := getTime()
  46. if now < sf.startTime {
  47. panic(fmt.Sprintf("Clock moved backwards. Refusing to generate id for %d milliseconds", sf.startTime-now))
  48. }
  49. if now == sf.startTime {
  50. sf.sequence = (sf.sequence + 1) & sequenceMask
  51. if sf.sequence == 0 {
  52. now = getNextTime(sf.startTime)
  53. }
  54. } else {
  55. sf.sequence = 0
  56. }
  57. sf.startTime = now
  58. return (now-sf.startTime)<<timeLeftShift | sf.datacenterId<<datacenterLeftShift |
  59. sf.workerId<<workerLeftShift | sf.sequence
  60. }
  61. func getTime() int64 {
  62. return time.Now().UnixNano() / int64(time.Millisecond)
  63. }
  64. func getNextTime(startTime int64) int64 {
  65. timestamp := getTime()
  66. for timestamp <= startTime {
  67. timestamp = getTime()
  68. }
  69. return timestamp
  70. }
  71. func main() {
  72. rand.Seed(time.Now().UnixNano())
  73. datacenterId := rand.Int63n(maxDatacenterId)
  74. workerId := rand.Int63n(maxWorkerId)
  75. snowflake := NewSnowflake(datacenterId, workerId)
  76. for i := 0; i < 10; i++ {
  77. fmt.Println(strconv.FormatInt(snowflake.GetId(), 10))
  78. }
  79. }

在main函数中,我们使用rand模块来随机生成datacenterId和workerId。然后通过NewSnowflake方法创建一个新的Snowflake实例。

调用GetId方法可以获得一个新的雪花ID。

注意:本示例中,为了方便演示,我们将时间戳精确到毫秒级别,但实际应用中建议将时间戳精确到微秒或纳秒级别来提高ID的唯一性。

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=2424

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?