(11)go-micro微服务雪花算法
一 雪花算法介绍
雪花算法是推特开源的分布式ID生成算法,用于在不同的机器上生成唯一的ID的算法。
该算法生成一个64bit的数字作为分布式ID,保证这个ID自增并且全局唯一。
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跨域认证的代码编写了,希望大家关注博主和关注专栏,第一时间获取最新内容,每篇博客都干货满满。
欢迎大家加入 夏沫の梦的学习交流群 进行学习交流经验,点击
(11)go-micro微服务雪花算法的更多相关文章
- 【11】JMicro微服务-配置管理
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 往下看前,建议完成前面1到10小节 JMicro目前仅支持基于Zookeeper做配置管理,全部配置信息可以在ZK做增删改查 ...
- go micro 微服务框架温习
go mod edit -require="github.com/chromedp/chromedp@v0.1.0" @后面加上你需要的版本号.就可以 已经修改go.mod 里的依 ...
- Asp.Net Core微服务再体验
ASP.Net Core的基本配置 .在VS中调试的时候有很多修改Web应用运行端口的方法.但是在开发.调试微服务应用的时候可能需要同时在不同端口上开启多个服务器的实例,因此下面主要看看如何通过命令行 ...
- Asp.Net Core微服务初体验
ASP.Net Core的基本配置 .在VS中调试的时候有很多修改Web应用运行端口的方法.但是在开发.调试微服务应用的时候可能需要同时在不同端口上开启多个服务器的实例,因此下面主要看看如何通过命令行 ...
- 【13】JMicro微服务-ID生成与Redis
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 往下看前,建议完成前面1到12小节 1. 微服务中ID地位 如果说前面小节的功能点是微服务的大脑,那么全局唯一ID则是微服务 ...
- 【12】JMicro微服务-Zookeeper
如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl 往下看前,建议完成前面1到11小节 1. CuratorFramework支持 JMicro目前基于Zookeeper实现统 ...
- SpringBoot+idea搭建微服务简化流程
作者:个人微信公众号:程序猿的月光宝盒 1.新建普通maven工程 2.在父级pom中按需修改 3.删除父级src目录 4.创建公共模块common,里面只有service接口和实体类 5.构建微服务 ...
- 现如今,最热门的13个Java微服务框架
曾经的 服务器领域 有许多不同的芯片架构???有哪些芯片架构???和操作系统???,经过长期发展,Java的“一次编译,到处运行”使得它在服务器领域找到一席之地,成为程序员们的最爱. 本文,我们将和大 ...
- 雪花算法及微服务集群唯一ID解决方案
雪花算法(SnowFlake) 简介 现在的服务基本是分布式.微服务形式的,而且大数据量也导致分库分表的产生,对于水平分表就需要保证表中 id 的全局唯一性. 对于 MySQL 而言,一个表中的主键 ...
- 第2-2-4章 常见组件与中台化-常用组件服务介绍-分布式ID-附Snowflake雪花算法的代码实现
目录 2.3 分布式ID 2.3.1 功能概述 2.3.2 应用场景 2.3.3 使用说明 2.3.4 项目截图 2.3.5 Snowflake雪花算法的代码实现 2.3 分布式ID 2.3.1 功能 ...
随机推荐
- 在vue中_this和this的区别
_this只是一个变量名,this代表父函数,如果在子函数还用this,this的指 向就变成子函数了,_this就是用来存储指向的 普通函数中的this表示调用此函数时的对象,箭头函数里面的this ...
- 齐博X1-栏目的调用1
本节来说明下系统提供的几个栏目调用的方法 一节我们制作了一个公共导航,本节我们在首页index中演示下栏目的相关调用 至于其他的数据内容,参考第二季的标签调用即可,直接{qb:tag}调用就可以调用出 ...
- 【保姆教程】RuoYi-Radius搭建实现portal认证
[保姆教程]RuoYi-Radius搭建实现portal认证 一.简介 以若依后台管理框架V4.6.0做为基础框架,实现了ToughRADIUS大部分功能,支持标准RADIUS协议(RFC 2865, ...
- 使用@Transactional注解的方法所在的类获取不到注解的解决方案
前段时间遇到一个问题,一个service叫做A吧,有多个实现类分别是B,C,D,需要根据前端传的不同参数去匹配不同的实现类,我就自定义了一个注解@OrderDeal放在B,C,D上面,然后匹配前端传的 ...
- AdsStream的使用
本例子是测试ads通信的. 1.首先添加TwinCAT.Ads引用 using System; using System.Collections.Generic; using System.Compo ...
- perl哈希嵌套和引用的使用
数组,哈希嵌套 数组,哈希的引用 1.哈希的嵌套和引用 %hash = ( 'group1', {'fruit', 'banana', 'drink', 'orange juice', 'vegeta ...
- Go语言核心36讲40
我相信,经过上一次的学习,你已经对strings.Builder和strings.Reader这两个类型足够熟悉了. 我上次还建议你去自行查阅strings代码包中的其他程序实体.如果你认真去看了,那 ...
- KubeEdge架构问题汇总
Q1 :KubeEdge云和边的数据协同有什么优势? A : K8s的原生架构中, Node (Kubelet) 是通过List-watch机制主动与Master通信.List-watch机制有几个 ...
- 区分mbr与gpt分区
查看分区类型 [root@localhost ~]# parted -l|egrep 'dev/|Part' Warning: Unable to open /dev/sr0 read-write ( ...
- OSI传输层TCP与UDP协议、应用层简介、socket模块介绍及代码优化、半连接池的概念
目录 传输层之TCP与UDP协议 应用层 socket模块 socket基本使用 代码优化 半连接池的概念 传输层之TCP与UDP协议 TCP与UDP都是用来规定通信方式的 通信的时候可以随心所欲的聊 ...