(11)go-micro微服务雪花算法

一 雪花算法介绍

雪花算法是推特开源的分布式ID生成算法,用于在不同的机器上生成唯一的ID的算法。
该算法生成一个64bit的数字作为分布式ID,保证这个ID自增并且全局唯一。

image.png
1.第一位占用1bit,其值始终是0,没有实际作用。

2.时间戳占用41bit,单位为毫秒,总共可以容纳约69年的时间。当然,我们的时间毫秒计数不会真的
从1970年开始记,那样我们的系统跑到2039/9/7 23:47:35 就不能用了,所以这里的时间戳只是相对
于某个时间的增量,比如我们的系统上线是2020-07-01,那么我们完全可以把这个timestamp当作是
从2022-10-01 00:00: 00.000的偏移量。

3.工作机器id占用10bit,其中高位5bit是数据中心ID,低位5bit是 工作节点ID,最多可以容纳1024个节
点。

4.序列号占用12bit,用来记录同毫秒内产生的不同id。每个节点每毫秒0开始不断累加,最多可以累加
到4095,同一毫秒-共可以产生4096个ID。
SnowFlake算法在同- -毫秒内最多可以生成多少个全局唯- -ID呢?
同-毫秒的ID数量= 1024 X 4096 = 4194304

二 雪花算法优缺点

  • 雪花算法有以下几个优点:

    • 高并发分布式环境下生成不重复 id,每秒可生成百万个不重复 id。

    • 基于时间戳,以及同一时间戳下序列号自增,基本保证 id 有序递增。

    • 不依赖第三方库或者中间件。

    • 算法简单,在内存中进行,效率高。

  • 雪花算法有如下缺点:

    • 依赖服务器时间,服务器时钟回拨时可能会生成重复 id。

三 雪花算法实现

package snow_flake

import (
   "github.com/golang/glog"
   "sync"
   "time"
)


type Snowflake struct {
   sync.Mutex         // 锁
   timestamp    int64 // 时间戳 ,毫秒
   workerid     int64 // 工作节点
   datacenterid int64 // 数据中心机房id
   sequence     int64 // 序列号
}

const (
   epoch             = int64(1577808000000)                           // 设置起始时间(时间戳/毫秒):2020-01-01 00:00:00,有效期69年
   timestampBits     = uint(41)                                       // 时间戳占用位数
   datacenteridBits  = uint(2)                                        // 数据中心id所占位数
   workeridBits      = uint(7)                                        // 机器id所占位数
   sequenceBits      = uint(12)                                       // 序列所占的位数
   timestampMax      = int64(-1 ^ (-1 << timestampBits))              // 时间戳最大值
   datacenteridMax   = int64(-1 ^ (-1 << datacenteridBits))           // 支持的最大数据中心id数量
   workeridMax       = int64(-1 ^ (-1 << workeridBits))               // 支持的最大机器id数量
   sequenceMask      = int64(-1 ^ (-1 << sequenceBits))               // 支持的最大序列id数量
   workeridShift     = sequenceBits                                   // 机器id左移位数
   datacenteridShift = sequenceBits + workeridBits                    // 数据中心id左移位数
   timestampShift    = sequenceBits + workeridBits + datacenteridBits // 时间戳左移位数
)

func (s *Snowflake) NextVal() int64 {
   s.Lock()
   now := time.Now().UnixNano() / 1000000 // 转毫秒
   if s.timestamp == now {
      // 当同一时间戳(精度:毫秒)下多次生成id会增加序列号
      s.sequence = (s.sequence + 1) & sequenceMask
      if s.sequence == 0 {
         // 如果当前序列超出12bit长度,则需要等待下一毫秒
         // 下一毫秒将使用sequence:0
         for now <= s.timestamp {
            now = time.Now().UnixNano() / 1000000
         }
      }
   } else {
      // 不同时间戳(精度:毫秒)下直接使用序列号:0
      s.sequence = 0
   }
   t := now - epoch
   if t > timestampMax {
      s.Unlock()
      glog.Errorf("epoch must be between 0 and %d", timestampMax-1)
      return 0
   }
   s.timestamp = now
   r := int64((t)<<timestampShift | (s.datacenterid << datacenteridShift) | (s.workerid << workeridShift) | (s.sequence))
   s.Unlock()
   return r
}

四 最后

  • 至此,go-micro微服务雪花算法开发工作就正式完成。

  • 接下来就开始JWT跨域认证的代码编写了,希望大家关注博主和关注专栏,第一时间获取最新内容,每篇博客都干货满满。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏沫の梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值