前言

项目中主键ID生成方式比较多,但是哪种方式更能提高的我们的工作效率、项目质量、代码实用性以及健壮性呢,下面作了一下比较,目前雪花算法的优点还是很明显的。

优缺点比较

  • UUID(缺点:太长、没法排序、使数据库性能降低)
  • Redis(缺点:必须依赖Redis)
  • Oracle序列号(缺点:用Oracle才能使用)
  • Snowflake雪花算法,优点:生成有顺序的id,提高数据库的性能

Snowflake雪花算法解析

雪花算法解析 结构 snowflake的结构如下(每部分用-分开):
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
第一位为未使用,接下来的41位为毫秒级时间(41位的长度可以使用69年),

然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点) ,

最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

一共加起来刚好64位,为一个Long型。(转换成字符串长度为18)。

Snowflake算法核心把时间戳,工作机器id,序列号组合在一起。

整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),

并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。

分布式Snowflake雪花算法代码

 public class SnowFlakeGenerator {

     public static class Factory {
/**
* 每一部分占用位数的默认值
*/
private final static int DEFAULT_MACHINE_BIT_NUM = 5; //机器标识占用的位数
private final static int DEFAULT_IDC_BIT_NUM = 5;//数据中心占用的位数 private int machineBitNum;
private int idcBitNum; public Factory() {
this.idcBitNum = DEFAULT_IDC_BIT_NUM;
this.machineBitNum = DEFAULT_MACHINE_BIT_NUM;
} public Factory(int machineBitNum, int idcBitNum) {
this.idcBitNum = idcBitNum;
this.machineBitNum = machineBitNum;
} public SnowFlakeGenerator create(long idcId, long machineId) {
return new SnowFlakeGenerator(this.idcBitNum, this.machineBitNum, idcId, machineId);
}
} /**
* 起始的时间戳
* 作者写代码时的时间戳
*/
private final static long START_STAMP = 1508143349995L; /**
* 可分配的位数
*/
private final static int REMAIN_BIT_NUM = 22; /**
* idc编号
*/
private long idcId; /**
* 机器编号
*/
private long machineId; /**
* 当前序列号
*/
private long sequence = 0L; /**
* 上次最新时间戳
*/
private long lastStamp = -1L; /**
* idc偏移量:一次计算出,避免重复计算
*/
private int idcBitLeftOffset; /**
* 机器id偏移量:一次计算出,避免重复计算
*/
private int machineBitLeftOffset; /**
* 时间戳偏移量:一次计算出,避免重复计算
*/
private int timestampBitLeftOffset; /**
* 最大序列值:一次计算出,避免重复计算
*/
private int maxSequenceValue; private SnowFlakeGenerator(int idcBitNum, int machineBitNum, long idcId, long machineId) {
int sequenceBitNum = REMAIN_BIT_NUM - idcBitNum - machineBitNum; if (idcBitNum <= 0 || machineBitNum <= 0 || sequenceBitNum <= 0) {
throw new IllegalArgumentException("error bit number");
} this.maxSequenceValue = ~(-1 << sequenceBitNum); machineBitLeftOffset = sequenceBitNum;
idcBitLeftOffset = idcBitNum + sequenceBitNum;
timestampBitLeftOffset = idcBitNum + machineBitNum + sequenceBitNum; this.idcId = idcId;
this.machineId = machineId;
} /**
* 产生下一个ID
*/
public synchronized long nextId() {
long currentStamp = getTimeMill();
if (currentStamp < lastStamp) {
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastStamp - currentStamp));
} //新的毫秒,序列从0开始,否则序列自增
if (currentStamp == lastStamp) {
sequence = (sequence + 1) & this.maxSequenceValue;
if (sequence == 0L) {
//Twitter源代码中的逻辑是循环,直到下一个毫秒
lastStamp = tilNextMillis();
// throw new IllegalStateException("sequence over flow");
}
} else {
sequence = 0L;
} lastStamp = currentStamp; return (currentStamp - START_STAMP) << timestampBitLeftOffset | idcId << idcBitLeftOffset | machineId << machineBitLeftOffset | sequence;
} private long getTimeMill() {
return System.currentTimeMillis();
} private long tilNextMillis() {
long timestamp = getTimeMill();
while (timestamp <= lastStamp) {
timestamp = getTimeMill();
}
return timestamp;
}
}

分布式Snowflake雪花算法的更多相关文章

  1. 分布式ID生成器 snowflake(雪花)算法

    在springboot的启动类中引入 @Bean public IdWorker idWorkker(){ return new IdWorker(1, 1); } 在代码中调用 @Autowired ...

  2. 说起分布式自增ID只知道UUID?SnowFlake(雪花)算法了解一下(Python3.0实现)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_155 但凡说起分布式系统,我们肯定会对一些海量级的业务进行分拆,比如:用户表,订单表.因为数据量巨大一张表完全无法支撑,就会对其进 ...

  3. .Net Core ORM选择之路,哪个才适合你 通用查询类封装之Mongodb篇 Snowflake(雪花算法)的JavaScript实现 【开发记录】如何在B/S项目中使用中国天气的实时天气功能 【开发记录】微信小游戏开发入门——俄罗斯方块

    .Net Core ORM选择之路,哪个才适合你   因为老板的一句话公司项目需要迁移到.Net Core ,但是以前同事用的ORM不支持.Net Core 开发过程也遇到了各种坑,插入条数多了也特别 ...

  4. 第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 功能 ...

  5. 分布式主键解决方案之--Snowflake雪花算法

    0--前言 对于分布式系统环境,主键ID的设计很关键,什么自增intID那些是绝对不用的,比较早的时候,大部分系统都用UUID/GUID来作为主键,优点是方便又能解决问题,缺点是插入时因为UUID/G ...

  6. snowflake 雪花算法 分布式实现全局id生成

    snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID. 这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案 ...

  7. Snowflake(雪花算法)的JavaScript实现

    现在好多的ID都是服务器端生成的,当然JS也可以生成GUID或者UUID之类的,但是如果想要有序……这时就想到了雪花算法,但是都知道JS中Number的最大值为Number.MAX_SAFE_INTE ...

  8. Go语言实现Snowflake雪花算法

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/527 每次放长假的在家里的时候,总想找点简单的例子来看看实现原理,这 ...

  9. 【spring cloud】分布式ID,雪花算法

    分布式ID生成服务 参考地址:https://blog.csdn.net/wangkang80/article/details/77914849 算法描述: 最高位是符号位,始终为0,不可用. 41位 ...

随机推荐

  1. 算法笔记 3.2 codeup1935 查找学生信息

    #include <stdio.h> #include <string.h> const int maxn = 1e3; struct student{ ]; ]; //!!! ...

  2. git grep的一些用法

    https://www.kernel.org/pub/software/scm/git/docs/git-grep.html   把所有本地分支包含某个字符的行列出来,把含有master的列出来 gi ...

  3. [转]C#程序性能优化

    C#程序性能优化 1.显式注册的EvenHandler要显式注销以避免内存泄漏 将一个成员方法注册到某个对象的事件会造成后者持有前者的引用.在事件注销之前,前者不会被垃圾回收.   private v ...

  4. windows下使用vscode编写运行以及调试C/C++

    未经允许,禁止转载,唯一出处:tangming博客园 最后更新于2019年4月4日: 多次更新,内容较多,篇幅较大,但如果是喜欢visual stdio code这款编辑器的话建议仔细阅读,有疑问的地 ...

  5. 【mysql】批量更新数据

    概述 批量更新mysql数据表数据,上网搜索基本都会说4~5方法,本人使用的更新方式为: INSERT ... ON DUPLICATE KEY UPDATE Syntax 可参见官方网站:inser ...

  6. 猴子选大王的c#实现

    原文地址:猴子选大王的c#实现作者:余文 今天被问到了猴子选大王的意思,题目大意就是说有n只猴子围坐成一个圈,按顺时针方向从1到n编号.然后从1号猴子开始沿顺时针方向从1开始报数,报到m的猴子出局,再 ...

  7. spring boot 常见三十四问

    Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...

  8. 表单:!!!常用JS: form 表单代码

    手机(文本框): <input type="text" name="" maxlength="11" placeholder=&quo ...

  9. python3 pyinstaller生成exe文件过程问题解决记录

    1.使用pip安装pyinstaller 2.在cmd打开需生成可执行文件的python文件所在文件夹 3.使用命令pyinstaller -F -w **.py (代码中有import其他模块的,只 ...

  10. leetcode56

    public class Solution { public IList<Interval> Merge(IList<Interval> intervals) { var le ...