go实现SnowFlake
package main import (
"errors"
"fmt"
"strconv"
"sync"
"time"
) /*
* 算法解释
* SnowFlake的结构如下(每部分用-分开):<br>
* 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
* 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
* 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
* 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下的epoch属性)。
* 41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
* 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
* 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
* 加起来刚好64位,为一个Long型。<br>
* SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
*/
const (
//t := time.Date(2015, 1, 1, 00, 00, 00, 00, time.Local).UnixNano() / 1e6;//获取时间戳 毫秒
//开始时间戳 2015-1-1
epoch int64 = 1420041600000
// 机器id所占的位数
workerIdBits int64 = 5
// 数据标识id所占的位数
datacenterIdBits int64 = 5
//支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)
maxWorkerId int64 = -1 ^ (-1 << workerIdBits)
// 支持的最大数据标识id,结果是31
maxDatacenterId int64 = -1 ^ (-1 << datacenterIdBits)
//序列在id中占的位数
sequenceBits int64 = 12
// 机器ID向左移12位
workerIdShift int64 = sequenceBits;
// 数据标识id向左移17位(12+5)
datacenterIdShift int64 = sequenceBits + workerIdBits;
// 时间截向左移22位(5+5+12)
timestampLeftShift int64 = sequenceBits + workerIdBits + datacenterIdBits
// 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
sequenceMask int64 = -1 ^ (-1 << sequenceBits)
) /*
* 构造
*/
type SnowflakeIdWorker struct {
mutex sync.Mutex // 添加互斥锁 确保并发安全
lastTimestamp int64 // 上次生成ID的时间截
workerId int64 // 工作机器ID(0~31)
datacenterId int64 //数据中心ID(0~31)
sequence int64 // 毫秒内序列(0~4095)
} /*
* 创建SnowflakeIdWorker
* workerId 工作ID (0~31)
* datacenterId 数据中心ID (0~31)
*/
func createWorker(wId int64,dId int64)(*SnowflakeIdWorker,error){
if wId < 0 || wId > maxWorkerId {
return nil, errors.New("Worker ID excess of quantity")
}
if dId < 0 || dId > maxDatacenterId {
return nil, errors.New("Datacenter ID excess of quantity")
}
// 生成一个新节点
return &SnowflakeIdWorker{
lastTimestamp: 0,
workerId: wId,
datacenterId: dId,
sequence: 0,
}, nil
} /*
* 获取ID
*/
func (w *SnowflakeIdWorker) nextId() int64 {
// 保障线程安全 加锁
w.mutex.Lock()
// 生成完成后 解锁
defer w.mutex.Unlock()
// 获取生成时的时间戳 毫秒
now := time.Now().UnixNano() / 1e6
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
if now < w.lastTimestamp {
errors.New("Clock moved backwards")
//根据需要自定义错误码
return 3001
}
if w.lastTimestamp == now {
w.sequence = (w.sequence + 1) & sequenceMask
if w.sequence == 0 {
// 阻塞到下一个毫秒,直到获得新的时间戳
for now <= w.lastTimestamp {
now = time.Now().UnixNano() / 1e6
}
}
}else {
// 当前时间与工作节点上一次生成ID的时间不一致 则需要重置工作节点生成ID的序号
w.sequence = 0
}
// 将机器上一次生成ID的时间更新为当前时间
w.lastTimestamp = now
ID := int64((now - epoch) << timestampLeftShift | w.datacenterId << datacenterIdShift | (w.workerId << workerIdShift) | w.sequence)
return ID
} /*
* 将十进制数字转化为二进制字符串
*/
func convertToBin(num int64) string {
s := ""
if num == 0 {
return "0"
}
// num /= 2 每次循环的时候 都将num除以2 再把结果赋值给 num
for ;num > 0 ; num /= 2 {
lsb := num % 2
// 将数字强制性转化为字符串
s = strconv.FormatInt(lsb,10) + s
}
return s
} func main() {
worker,err := createWorker(0,0)
if err != nil {
fmt.Println(err)
return
}
ch := make(chan int64)
count := 100
// 并发 goroutine ID生成
for i := 0; i < count; i++ {
go func() {
id := worker.nextId()
ch <- id
}()
}
defer close(ch)
m := make(map[int64]int)
for i := 0; i < count; i++ {
id := <- ch
// map中存在为id的key,说明生成的 ID有重复
_, ok := m[id]
if ok {
fmt.Println("ID is not unique!")
}
// id作为key存入map
m[id] = i
fmt.Println(id)
fmt.Println(convertToBin(id))
}
}
go实现SnowFlake的更多相关文章
- 关于全局ID,雪花(snowflake)算法的说明
上次简单的说一下:http://www.cnblogs.com/dunitian/p/6041745.html#uid C#版本的国外朋友已经封装了,大家可以去看看:https://github.co ...
- Snowflake 全局唯一Id 生成
/// <summary> /// From: https://github.com/twitter/snowflake /// An object that generates IDs. ...
- POJ 3349 Snowflake Snow Snowflakes(简单哈希)
Snowflake Snow Snowflakes Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 39324 Accep ...
- Twitter的分布式自增ID算法snowflake (Java版)
概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...
- Twitter Snowflake 的Java实现
在关闭显示的情况下, 可以达到每毫秒3万个的生成速度 /** * An Implementation of Twitter Snowflake ID Generator */ public class ...
- C# 实现 Snowflake算法 ID生成
http://blog.csdn.net/w200221626/article/details/52064976 C# 实现 Snowflake算法 /// <summary> /// 动 ...
- 【hiho一下第77周】递归-减而治之 (MS面试题:Koch Snowflake)
本题是一道微软面试题,看起来复杂,解出来会发现其实是一个很简单的递归问题,但是这道题的递归思路是很值得我们反复推敲的. 原题为hihocoder第77周的题目. 描述 Koch Snowflake i ...
- Snowflake Snow Snowflakes(哈希表的应用)
Snowflake Snow Snowflakes Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 27312 Accep ...
- poj 3349:Snowflake Snow Snowflakes(哈希查找,求和取余法+拉链法)
Snowflake Snow Snowflakes Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 30529 Accep ...
- PHP使用SnowFlake算法生成唯一ID
前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的.文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过 ...
随机推荐
- stand up meeting 12-9
今天项目小组本已约好在今天下午四点半进行今天的daily scrum: 但是在四点半的时候,天赋和士杰同学均因组内项目会议延时,导致今天的daily scrum只能在晚上进行,但静雯同学因身体不舒服无 ...
- 无序map 记录一下
unordered_map<int ,int >mp; unordered_map是基于hash表实现的,查找元素的复杂度可以达到o(1),查找n个元素,复杂度为o(n). map是基于红 ...
- css 样式中 margin padding和top类定位的区别
1 margin margin 是外边距的意思,是边框到外部另一元素之间的距离,允许使用负值 语法结构: margin:5px auto; 意思上下为5,左右平均居中 ...
- Mybatis源码详解系列(三)--从Mapper接口开始看Mybatis的执行逻辑
简介 Mybatis 是一个持久层框架,它对 JDBC 进行了高级封装,使我们的代码中不会出现任何的 JDBC 代码,另外,它还通过 xml 或注解的方式将 sql 从 DAO/Repository ...
- react-i8n
1. 在项目中安装 npm install react-intl --save 2.兼容Safari各个版本需要安装intl npm install intl --save 3.编写语言包 1.)新建 ...
- 01、Hibernate安装配置
1.查看你的Eclipse的版本:Help | About Eclipse Version: 2018-12 (4.10.0) 2.HibernateTools的下载地址为:http:// ...
- git在用https进行push时候免输账密的方法
先新建一个文件 $ touch ~/.git-credentials $ vim ~/.git-credentials 进去添加内容(github为github.com,码云为gitee.com) h ...
- 通过注册表查询 .Net Framework 的版本
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full 注意:即使卸载 .Net Framework 这些注册表依然 ...
- pynlpir.License过期问题解决方案
报错信息:pynlpir.LicenseError: Your license appears to have expired. Try running "pynlpir update&qu ...
- JavaWEB开发时FCKeditor类似office界面的ajax框架,加入后就能做界面类似office,能进行简单的文本编辑操作+配置手册...
2019独角兽企业重金招聘Python工程师标准>>> FCKeditor是一款功能强大的开源在线文本编辑器(DHTML editor),它使你在web上可以使用类似微软Word 的 ...