当前位置: 首页 > 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.lryc.cn/news/624236.html

相关文章:

  • linux-高级IO(中)
  • 【BFS 动态规划】P12382 [蓝桥杯 2023 省 Python B] 树上选点|普及+
  • Redis面试精讲 Day 25:Redis实现分布式Session与购物车
  • 【前端】使用Vue3过程中遇到加载无效设置点击方法提示不存在的情况,原来是少加了一个属性
  • [激光原理与应用-296]:理论 - 非线性光学 - 线性光学与非线性光学对比
  • (第十九期)用 VS Code 管理项目:目录文件夹与根目录,一次讲清
  • Vulkan笔记(五)-逻辑层与队列
  • halcon基于透视的可变形模型匹配
  • C预备知识01:
  • 数字电视:技术演进与未来展望
  • 用户认证技术
  • MySQL 函数大赏:聚合、日期、字符串等函数剖析
  • 静配中心配药智能化:基于高并发架构的Go语言实现
  • CPP异常
  • 新手向:Java方向讲解
  • 数据挖掘 3.5 支持向量机——边界和正则化
  • C++ const
  • CSDN转PDF【无水印且免费!!!】
  • 计算机网络:2、TCP和UDP
  • 代码随想录刷题Day36
  • 时序数据库 Apache IoTDB:从边缘到云端Apache IoTDB 全链路数据管理能力、部署流程与安全特性解读
  • RH134 管理网络安全知识点
  • 前端处理导出PDF。Vue导出pdf
  • 备份数据库数据的时候,使用全局锁会影响业务,那有什么其他方式可以避免?
  • Redis---持久化策略
  • 如何用企业微信AI 破解金融服务难题?
  • easyexcel fastexcel 官方文档 easyexcel合并单元格
  • linux:告别SSH断线烦恼,Screen命令核心使用指南
  • 前端上传excel并解析成json
  • 实现自学习系统,输入excel文件,能学习后进行相应回答