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考虑过 ...
随机推荐
- 教你如何安装和使用Python pip
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:Starshot PS:如有需要Python学习资料的小伙伴可以加点击 ...
- PHP 将字符串转换为字符集格式UTF8/GB2312/GBK 函数iconv()
iconv()介绍 iconv函数可以将一种已知的字符集文件转换成另一种已知的字符集文件 iconv('要转化的格式',‘转化后的格式’,‘转化的数据’); 但是转化是经常出错,一般需要在转成的编码 ...
- 深度剖析前端JavaScript中的原型(JS的对象原型)
这张图片有点劝退了,哈哈哈~ 通过原型机制,JavaScript 中的对象从其他对象继承功能特性:这种继承机制与经典的面向对象编程语言的继承机制不同.本文将探讨这些差别,解释原型链如 ...
- Python 如何移除旧的版本特性,如何迎接新的特性?
2020 年 4 月 20 日,Python 2 的最后一个版本 2.7.18 发布了,这意味着 Python 2 是真正的 EOL(end of life)了,一个时代终于落幕了. Python 2 ...
- ISWC 2018概览:知识图谱与机器学习
语义网的愿景活跃且良好,广泛应用于行业 语义网的愿景是「对计算机有意义」的数据网络(正如 Tim Berners Lee.James Hendler 和 Ora Lassila 在<科学美国人& ...
- 数值分析实验之曲线最小二乘拟合含有噪声扰动(python实现)
一.实验目的 掌握最小二乘法拟合离散数据,多项式函数形式拟合曲线以及可以其他可以通过变量变换转化为多项式的拟合曲线目前待实现功能: 1. 最小二乘法的基本实现. 2. 用不同数据量,不同参数,不同的多 ...
- UML由浅入深
在UML 2.0的13种图形中,类图是使用频率最高的UML图之一.Martin Fowler在其著作<UML Distilled: A Brief Guide to the Standard O ...
- StringRedisTemplate的常用操作
stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向r ...
- Scala教程之:深入理解协变和逆变
文章目录 函数的参数和返回值 可变类型的变异 在之前的文章中我们简单的介绍过scala中的协变和逆变,我们使用+ 来表示协变类型:使用-表示逆变类型:非转化类型不需要添加标记. 假如我们定义一个cla ...
- css套路学习(一)
css3信息获取方法 文档搜索:Google css spec; Google: 关键词 MDN; css tricks成熟css代码块sinppets; Google: center css tri ...