雪花算法snowflake

news/2024/11/24 2:21:18/

snowflake中文的意思是 雪花,雪片,所以翻译成雪花算法。它最早是twitter内部使用的分布式环境下的唯一ID生成算法。在2014年开源。

雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求,得益于twitter内部高超的技术,雪花算法流传至今并被广泛使用。它至少有如下几个特点:

  • 能满足高并发分布式系统环境下ID不重复

  • 基于时间戳,可以保证基本有序递增(有些业务场景对这个又要求)

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

  • 生成效率极高

雪花算法原理


10位的数据机器位,所以可以部署在1024个节点。

12位的序列,在毫秒的时间戳内计数。支持每个节点每毫秒产生4096个ID序号,所以最大可以支持单节点大概四百万的并发量,这个妥妥的够用了。

雪花算法java实现


public class SnowflakeIdWorker {/** 开始时间截 (这个用自己业务系统上线的时间) */private final long twepoch = 1575365018000L;/** 机器id所占的位数 */private final long workerIdBits = 10L;/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */private final long maxWorkerId = -1L ^ (-1L << workerIdBits);/** 序列在id中占的位数 */private final long sequenceBits = 12L;/** 机器ID向左移12位 */private final long workerIdShift = sequenceBits;/** 时间截向左移22位(10+12) */private final long timestampLeftShift = sequenceBits + workerIdBits;/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */private final long sequenceMask = -1L ^ (-1L << sequenceBits);/** 工作机器ID(0~1024) */private long workerId;/** 毫秒内序列(0~4095) */private long sequence = 0L;/** 上次生成ID的时间截 */private long lastTimestamp = -1L;//==============================Constructors=====================================/*** 构造函数* @param workerId 工作ID (0~1024)*/public SnowflakeIdWorker(long workerId) {if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));}this.workerId = workerId;}// ==============================Methods==========================================/*** 获得下一个ID (该方法是线程安全的)* @return SnowflakeId*/public synchronized long nextId() {long timestamp = timeGen();//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}//如果是同一时间生成的,则进行毫秒内序列if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;//毫秒内序列溢出if (sequence == 0) {//阻塞到下一个毫秒,获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}}//时间戳改变,毫秒内序列重置else {sequence = 0L;}//上次生成ID的时间截lastTimestamp = timestamp;//移位并通过或运算拼到一起组成64位的IDreturn ((timestamp - twepoch) << timestampLeftShift) //| (workerId << workerIdShift) //| sequence;}/*** 阻塞到下一个毫秒,直到获得新的时间戳* @param lastTimestamp 上次生成ID的时间截* @return 当前时间戳*/protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 返回以毫秒为单位的当前时间* @return 当前时间(毫秒)*/protected long timeGen() {return System.currentTimeMillis();}
}

上面第一部分说到雪花算法的性能比较高,接下来我们测试下性能:

public static void main(String[] args) {SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1);long start = System.currentTimeMillis();int count = 0;for (int i = 0; System.currentTimeMillis()-start<1000; i++,count=i) {idWorker.nextId();}long end = System.currentTimeMillis()-start;System.out.println(end);System.out.println(count);}

其可以产生400w+的id,效率还是相当高的。

调整比特位分布

很多公司会根据 snowflake 算法,根据自己的业务做二次改造。举个例子。你们公司的业务评估不需要运行69年,可能10年就够了。但是集群的节点可能会超过1024个,这种情况下,你就可以把时间戳调整成39bit,然后workerid调整为12比特。同时,workerid也可以拆分下,比如根据业务拆分或者根据机房拆分等。类似如下:

源码

twitter的雪花算法:https://github.com/twitter-archive/snowflake


http://www.ppmy.cn/news/23630.html

相关文章

【逐步剖C】-第六章-结构体初阶

一、结构体的声明 1. 结构体的基本概念 结构体是一些值的集合&#xff0c;这些值称为成员变量。结构体的每个成员可以是不同类型的变量。结构体使得C语言有能力描述复杂类型。 如学生&#xff0c;有姓名、学号、性别等&#xff1b;如书&#xff0c;有作者&#xff0c;出版日期…

冷知识|鹤顶红还能用来修长城?

大家好&#xff0c;我是建模助手。 在上篇浅浅地蹭了波热点之后&#xff0c;我灵机一动&#xff0c;倒不如也搞一搞建筑方面的冷知识&#xff1f;冷热搭配&#xff0c;事半功倍... 问问大家&#xff0c;如果谈起古建筑&#xff0c;关键词都有什么&#xff1f;是庄严、震撼、壮…

计算机入门基础知识大全

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽…

MySQL8.0之前实现row_number以及计算玩家连续登录天数

使用MySQL 5.7版本统计 玩家连续登录天数 原始数据 玩家同一天多次登录只保留一条 select DISTINCT(FROM_UNIXTIME(login_time,%Y-%m-%d)) as login_date,rid from t_log_login order by rid; 借助两个变量统计每个玩家登录日期对应的次数 SELECT * FROM(SELECT DISTINCT …

【代码随想录二刷】Day9-字符串-C++

代码随想录二刷Day9 今日任务 28.找出字符串中第一个匹配项的下标 459.重复的子字符串 字符串总结 双指针总结 语言&#xff1a;C KMP 链接&#xff1a;https://programmercarl.com/0459.重复的子字符串.html#kmp 用处&#xff1a;当出现字符串不匹配时&#xff0c;可以利…

差分模拟信号转单端输出电路设计

需求分析&#xff1a; 1.差分输入0~16V -Vpp电压量&#xff1b; 2.输入频率0~1.2KHz&#xff1b; 3.单端对应输出0~3V的模拟量&#xff1b; 4.输出频率对应0~1.2KHz&#xff1b; 5.供电范围3~5V。 针对以上需求&#xff0c;设计如下图所示电路。 1.电路功能&#xff1a; …

nvidia设置wifi和接口

tx-nx设置wifi和接口前言基础知识点1.创建和删除一个wifi连接2. 启动连接和关闭连接代码和调试1. 代码展示2. 调试写到最后前言 针对嵌入式开发&#xff0c;有时候通过QT或PAD跨网络对设备设置WIFI&#xff0c;在此记录下&#xff0c;方便后续的查阅。 基础知识点 1.创建和删…

167. 两数之和 II - 输入有序数组

给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index2 < numbers…