当前位置: 首页 > news >正文

学习雪花算法

package com.yupi.cicd.test;import org.springframework.stereotype.Component;/*** 雪花算法ID生成器* 技术亮点:解决分布式环境下的全局唯一ID生成问题*/
@Component
public class SnowflakeIdGenerator {// 起始时间戳 (2024-01-01)private final long START_TIMESTAMP = 1704067200000L;// 机器ID位数private final long MACHINE_ID_BITS = 5L;// 数据中心ID位数private final long DATACENTER_ID_BITS = 5L;// 序列号位数private final long SEQUENCE_BITS = 12L;// 最大机器IDprivate final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS);// 最大数据中心IDprivate final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_ID_BITS);// 最大序列号private final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);// 机器ID左移位数private final long MACHINE_ID_SHIFT = SEQUENCE_BITS;// 数据中心ID左移位数private final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS;// 时间戳左移位数private final long TIMESTAMP_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS + DATACENTER_ID_BITS;private long machineId;private long datacenterId;private long sequence = 0L;private long lastTimestamp = -1L;public SnowflakeIdGenerator() {this(1L, 1L);}public SnowflakeIdGenerator(long machineId, long datacenterId) {if (machineId > MAX_MACHINE_ID || machineId < 0) {throw new IllegalArgumentException("机器ID超出范围");}if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {throw new IllegalArgumentException("数据中心ID超出范围");}this.machineId = machineId;this.datacenterId = datacenterId;}/*** 生成下一个ID* 技术难点:确保在高并发环境下ID的唯一性*/public synchronized long nextId() {long timestamp = System.currentTimeMillis();// 时钟回拨检查if (timestamp < lastTimestamp) {throw new RuntimeException("时钟回拨异常,拒绝生成ID");}// 同一毫秒内序列号递增if (timestamp == lastTimestamp) {sequence = (sequence + 1) & MAX_SEQUENCE;if (sequence == 0) {// 序列号溢出,等待下一毫秒timestamp = waitNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;// 组装ID:时间戳 + 数据中心ID + 机器ID + 序列号return ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT)| (datacenterId << DATACENTER_ID_SHIFT)| (machineId << MACHINE_ID_SHIFT)| sequence;}/*** 等待下一毫秒*/private long waitNextMillis(long lastTimestamp) {long timestamp = System.currentTimeMillis();while (timestamp <= lastTimestamp) {timestamp = System.currentTimeMillis();}return timestamp;}
}
package com.yupi.cicd.test;public class testSonw {public static void main(String[] args) {System.out.println("hello world");SnowflakeIdGenerator snowflakeIdGenerator = new SnowflakeIdGenerator();for (int i = 0; i < 19; i++) {long l = snowflakeIdGenerator.nextId();System.out.println(l);}}
}

为什么不推荐使用数据库自增主键?也不推荐使用UUID作主键,用雪花算法会有什么问题?

自增
在分库分表的时候会出现问题

每一个表都有一个自增,这个时候ID就不能保证唯一性了

也可以用步长来解决问题(类似于分库分表的时候强制唯一)但是后续如果要扩容就是由三个表变成四个表,数据工作量很大,划分规则可能要变,旧数据怎么办

UUID

1.影响查询性能

UUID比较长占用的空间比较大,每行数据也大,那么同样的数据量需要page页 page页越多

索引树的高度也就越高,遍历次数也多,遍历page页也多,page也又是内存和磁盘交互的最最小单位,IO次数多

2.操作性能

UUID无序,非趋势递增

B+树内部株建索引是要进行id 的排序,添加一个新数据的时候,需要对数据的内容进行重排序

3.雪花算法

符号位为最高位,用long来存储,64位

是趋势递增的,是64bit的二进制,占用的空间小很多

一个典型的64位ID结构如下:

- 1位符号位(固定为0)

- 41位时间戳(毫秒级,可以使用约69年)(2的1次方/1000*60*60*24)

- 10位机器ID(可以配置,通常包括5位数据中心ID和5位机器ID)(2的10次方=1024台机器)

数据中心可以代表机房,比如使用云服务器,华南华北还有不用的机房

机器ID:每一个机房里面有不同的这个机器

- 12位序列号(同一毫秒内生成的序列号,每毫秒最多4096个)

也有三个问题

1.时间回拨的问题

系统时间变了不正确,如果改成过去的时候就乱了,ID就不是趋势递增的了

解决:
1.直接抛出异常,发现生成的id时间戳比之前的要小的时候直接抛出异常

2.采用备用方案:比如随机

2.机器ID的管理问题

集群部署的时候,100台机器,要去维护机器ID不重复是成本比较大

解决

1.机器ID一般通过配置文件去配置,

3.序列号一直是0的问题

分库分表场景数据不均匀

当为好为0的时候获取时间错的最后一位换一个

http://www.dtcms.com/a/337592.html

相关文章:

  • 冒泡排序——简单理解和使用
  • NVIDIA 技术沙龙探秘:聚焦 Physical AI 专场前沿技术
  • Handler以及AsyncTask知识点详解
  • 数据结构部分算法记录
  • Oracle维护指南
  • 计算机大数据毕业设计推荐:基于Hadoop+Spark的食物口味差异分析可视化系统【源码+文档+调试】
  • RPM数据库损坏修复:DB_RUNRECOVERY: Fatal error, run database recovery
  • 新能源知识库(78)微网控制器与储能LCU对比
  • 【opencv-Python学习日记(7):图像平滑处理】
  • 普通用户使用docker命令
  • 「数据获取」《中国经济普查年鉴》(2004、2008、2013、2018、2023)(获取方式看绑定的资源)
  • Centos7 使用lamp架构部署wordpress
  • Django开发Web应用
  • Vitis 2023下调用math.h(log)函数提示未定义的解决办法
  • HT6875_2.8W 防削顶单声道D 类音频功率放大器
  • CoRL 2025|隐空间扩散世界模型LaDi-WM大幅提升机器人操作策略的成功率和跨场景泛化能力
  • vue3 el-table-column 列头添加 图标按钮
  • 无人机迫降模式技术要点解析
  • HTTP协议-4-浏览器是怎么抉择HTTP版本的?
  • MySQL Operator开发实战系列:特别篇 - 生产环境故障排查与性能调优指南
  • 第4.3节:awk正则表达式详解-特殊字符
  • PyTorch数据处理工具箱(数据处理工具箱概述)
  • AI大模型实战:用自然语言处理技术高效处理日常琐事
  • 鸿蒙中应用框架和应用模型
  • 【JavaEE】多线程 -- 阻塞队列
  • 使用WinDbg对软件崩溃信息进行抓包的方法
  • 决策树学习笔记
  • Linux内存管理系统性总结
  • RabbitMQ:数据隔离
  • 代码随想录刷题Day36