springboot中表是以int为主键id的,写了一个生成不重复id的方法

【初衷】

由于系统改造,之前的单应用改成了分布式应用,但是系统底层在搭建的时候部分关联id定义为了int类型,导致分布式id生成的long类型无法插入到int中,且由于是多系统部署,为了把损失降到最低,故此决定把分布式生成long类类型主键id的方法改成生成int类型然后强转为long类型,多次尝试下来发现下面这种最稳定和好用,当然目前是为了验收所以在影响最小的前提下做了这改动,等验收完成后会修改表结构,然后继续用long,毕竟应付是暂时了,系统长久稳定才是程序员的最终追求

【评价】

1. 重复性分析

在这种方法中,生成的 ID 由三个部分组成:

  • 时间戳部分:21 位
  • 序列号部分:10 位
  • 随机数部分:12 位
时间戳部分:
  • 时间戳从 EPOCH (2024-06-01 00:00:00)开始计算,单位是秒。因为时间戳是基于当前秒数来生成的,并且每秒生成的 ID 都包含时间戳部分,这部分的唯一性基本上没有问题。
序列号部分:
  • 序列号在每秒内从 0 开始递增,最大值为 1023 (即 2^10 - 1),因此每秒最多生成 1024 个 ID。每秒钟会重置序列号,保证了在同一秒内生成的 ID 是唯一的。
  • 可能的问题:如果每秒的 ID 生成数量超过 1024,就会发生序列号溢出,抛出异常 Sequence overflow in current second。所以,如果在每秒内生成 ID 的速度很快,超过了 1024 次,会出现 ID 重复的情况。
随机数部分:
  • 随机数部分由 12 位构成,范围是 0 到 4095,这保证了在每次生成 ID 时,随机数部分的值是变化的,从而增加了唯一性。
  • 在同一秒钟内,即使序列号部分已经递增到了最大值 1023,随机数部分仍然能提供额外的变化,减少了重复的可能性。
总结:
  • 在正常情况下,每秒内最多生成 1024 个 ID,如果每秒生成的数量超过了 1024,会发生序列号溢出。因此,ID 的重复性主要受限于每秒生成的 ID 数量。
  • ID 会重复的条件:如果每秒生成的 ID 数量超过 1024,则会触发序列号溢出,导致重复。

2. 负数分析

Java 中的 int 类型是 32 位有符号整数,范围从 -21474836482147483647

ID 的构成:
  • 时间戳部分:21 位左移后仍然是正数,因为时间戳部分的位数不可能超出 31 位,所以不会导致符号位的变化。
  • 序列号部分:10 位左移后也不会影响符号位,因为最多左移 12 位,所以序列号部分也不会导致符号位变化。
  • 随机数部分:12 位本身不会影响符号位。
因此,生成的 ID 永远是正数。具体分析:
  • 左移操作:左移操作会让数值的高位变为 0,而 int 类型最高位是符号位。如果数据位数没有超出 31 位,则不会引起负数。
  • 结果:通过组合后的 ID 的最高位始终为 0,确保了生成的 ID 永远是正数。

3. 结论

  • 重复性:在正常使用情况下,ID 不会重复。唯一性问题仅会在每秒内生成超过 1024 次 ID 时才会出现。
  • 负数:生成的 ID 永远不会是负数,因为经过左移和组合操作后,最高位始终是 0

【注意】 每秒内生成超过 1024 次 ID 时才会出现

import java.util.concurrent.atomic.AtomicInteger;
import java.util.Random;public final class HybridGenerator {// 调整EPOCH为更近的时间点,避免时间戳部分溢出private static final long EPOCH = 1717200000L; // 2024-06-01 00:00:00 (秒)private static final AtomicInteger sequence = new AtomicInteger(0);private static volatile long lastSecond = -1L;private static final Random random = new Random();/*** 生成唯一且非负的int型ID* 结构:21位时间戳 + 10位序列号 + 12位随机数(保证不重复且不溢出)*/public static synchronized int nextId() {long currentSecond = System.currentTimeMillis() / 1000L;// 时间戳部分(限制在21位,避免溢出)long timestampPart = (currentSecond - EPOCH) << 21; // 左移21位// 序列号部分(10位,范围0-1023)if (currentSecond != lastSecond) {sequence.set(0);lastSecond = currentSecond;}int currentSequence = sequence.incrementAndGet();if (currentSequence >= 1024) { // 2^10=1024throw new RuntimeException("Sequence overflow in current second");}int sequencePart = currentSequence << 12; // 左移12位// 随机数部分(12位,范围0-4095)int randomPart = random.nextInt(4096); // 0~4095// 组合并确保非负(最高位始终为0)return (int) (timestampPart | sequencePart | randomPart);}/*** 解析时间戳*/public static long parseTimestamp(int id) {return EPOCH + (id >>> 21); // 无符号右移21位}/*** 解析序列号*/public static int parseSequence(int id) {return (id >>> 12) & 0x3FF; // 右移12位后取10位}/*** 解析随机数部分*/public static int parseRandomPart(int id) {return id & 0xFFF; // 取最后12位}// 测试代码public static void main(String[] args) {for (int i = 0; i < 1000; i++) {// 生成并解析IDint id = nextId();System.out.println("id = " + id);
//            System.out.println("Generated ID: " + id + " (Hex: " + Integer.toHexString(id) + ")");
//            System.out.println("Timestamp: " + parseTimestamp(id));
//            System.out.println("Sequence: " + parseSequence(id));
//            System.out.println("Random: " + parseRandomPart(id));
//
//            // 验证无符号性质
//            System.out.println("Is negative? " + (id < 0)); // 始终输出false}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/web/86012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

天气查询API集成指南

天气查询API集成指南 引言 在互联网和移动应用快速发展的今天&#xff0c;天气查询API已经成为开发人员构建各种应用程序时不可或缺的工具之一。无论是为用户提供日常出行建议、帮助农民规划农作时间&#xff0c;还是支持物流行业优化配送路线&#xff0c;实时且准确的天气信息…

AI 产品部署和交付的基础设施——全景解析

当然可以&#xff01;以下是对“AI产品部署和交付的基础设施”主题的详细内容扩展&#xff0c;适合介绍给同事&#xff0c;帮助大家系统性理解AI落地的全流程和关键要素。 AI产品部署和交付的基础设施——全景解析 各位同事&#xff0c;随着AI技术的飞速发展&#xff0c;AI产品…

Linux C 目录基本操作

需要引用的头文件 #include <unistd.h> unistd.h 为程序提供了对POSIX操作系统API的访问接口&#xff0c;主要用于提供与系统调用相关的功能。 char *getcwd(char *buf, size_t size); 用于获取当前工作目录&#xff08;Current Working Directory&#xff09;的绝对…

关于二分和分治的详细讲解(从属于GESP五级)

本章内容 二分 分治 当你把疑惑一劈为二&#xff0c;困境就只剩下一半。 一、二分查找 1. 何谓“二分”&#xff1f; “二分”本质是一种 对单调现象反复折半 的搜索思想。 单调现象&#xff1a;随变量增大&#xff0c;目标状态只会保持“假→真”或“真→假”一次性跃迁…

程序猿成长之路之数据挖掘篇——聚类算法介绍

作为无监督学习算法的基础&#xff0c;学好聚类算法很关键&#xff0c;我之前介绍过kmeans聚类算法&#xff0c;现在系统的介绍一下聚类算法 1. 什么是分类 日常生活中我们会经常见到分类的情况&#xff0c;如家里大扫除时给物品归类&#xff0c;超市货架上商品分类等。分类就…

PostgreSQL 性能优化与集群部署:PGCE 认证培训实战指南

&#xff5c;深夜被数据库报警惊醒&#xff1f; &#xff5c;海量数据查询卡死业务&#xff1f; &#xff5c;主库宕机导致服务中断&#xff1f; 如果你正被这些PostgreSQL生产难题困扰&#xff0c;是时候系统掌握数据库内核优化与高可用架构了&#xff01;深度求索联合PG分会…

Java 对象映射 数据库表映射 工具类 两个对象/表实现映射转换

场景&#xff1a;需要将一个对象的各个字段中的数据映射到另一个对象的字段数据中&#xff0c;或将一个数据库表映射到另一张表中。 本文使用泛型编程实现了一个对象映射功能的工具类。 需要源对象&#xff0c;映射关系map&#xff0c;目标类。由于是动态的类&#xff0c;所以…

Linux离线搭建Jenkins

Linux离线搭建Jenkins(centos7) Jenkins简介: Jenkins只是一个平台&#xff0c;真正运作的都是插件。这就是jenkins流行的原因&#xff0c;因为jenkins什么插件都有&#xff0c;Hudson是Jenkins的前身&#xff0c;是基于Java开发的一种持续集成工具&#xff0c;用于监控程序重…

从零学习linux(2)——管理

一.用户管理 1.用户属性 用户名、口令、用户ID&#xff08;UID&#xff09;、用户主目录&#xff08;HOME&#xff09;、用户shell 2. 3. 4.adduser添加用户 语法&#xff1a;adduser 用户名 如# adduser superw 添加用户名为superw的新用户 5.deluser删除用户 语法&am…

《贵州棒垒球》有什么国家级比赛·棒球1号位

中国国家级棒球比赛盘点 | 小白入门指南 3月 | 中国棒球联赛 (China Baseball League) 国内最高水平职业联赛&#xff0c;各省市职业队角逐冠军&#xff01; 英文&#xff1a;Top-tier professional event with teams nationwide. 5月 | 全国青年棒球锦标赛 (National Youth …

该项目名为“EduPal“,AI推荐

## 完整代码实现 ### 后端代码 (app.py) python import os import json import uuid import requests from datetime import datetime from flask import Flask, render_template, request, jsonify from dotenv import load_dotenv # 加载环境变量 load_dotenv() app …

C++法则15:匹配失败并不是一种错误(Substitution Failure Is Not An Error)。

C法则15&#xff1a;匹配失败并不是一种错误(Substitution Failure Is Not An Error)。 应用例子&#xff1a; SFINAE &#xff1a;关于is_class&#xff0c;is_base_of&#xff0c;C编译器的魔法器&#xff0c;如何实现&#xff0c;is_class&#xff0c;is_base_of。_c is cl…

Ollama客户端 + Docker搭建本地知识库(Mac系统)

一、环境准备 1. 安装Ollama客户端 官网下载&#xff1a;https://ollama.com 验证安装&#xff1a; ollama --version2. 安装Docker Desktop 下载地址&#xff1a;https://www.docker.com/products/docker-desktop 安装后确保Docker状态为"Running" 二、基础搭建…

FastMCP 2.9 版本详解:MCP 原生中间件与类型转换增强

下面我将从三个方面来讲解这个&#xff0c;第一是讲解2.9版本的更新&#xff0c;第二是讲解什么将手动解析底层JSON-RPC 消息&#xff0c;丢失 FastMCP 高层语义&#xff0c;第三是讲一讲&#xff0c;什么叫做中间件。不了解的兄弟们系好安全带&#xff0c;我们准备发车了&…

LTspice仿真6——PWL折线波产生

1.自定义波形 2.自定义波形周期 3.以文件.txt的形式定义折线波 4.通过C语言编程&#xff0c;一系列操作&#xff0c;生成自定义正弦波&#xff08;可自定义性强&#xff09;

FunASR搭建语音识别服务和VAD检测

调整VAD参数 1. 查找VAD模型的配置文件 FunASR中的VAD模型为FSMN-VAD&#xff0c;参数配置类为VADXOptions&#xff0c;可以在以下路径中找到&#xff1a; /workspace/FunASR/runtime/python/onnxruntime/funasr_onnx/utils/e2e_vad.py 其中&#xff0c;VADXOptions类定义了…

多模态大模型(从0到1)

文章目录 一、多模态大模型二、常见模态组合 典型应用场景三、多模态&#xff08;模型 框架&#xff09;1. 多模态模型2. 多模态框架 —— 开源项目推荐&#xff08;可快速上手&#xff09; 四、入门与学习路线1. 理论基础2. 主流多模态模型实战3. 进阶与应用拓展&#x1f4d…

# Vue.js 精确轮播组件实现详解

## &#x1f4d6; 概述 本文详细介绍了一个基于 Vue.js 开发的高精度轮播组件&#xff0c;该组件实现了精确的卡片对齐和平滑滚动效果。组件支持混合布局&#xff08;大卡片网格布局&#xff09;&#xff0c;具备智能位置计算和精确滚动控制功能。 ## ✨ 组件特点 ### &#x1…

将RESP.app的备份数据转码成AnotherRedisDesktopManager的格式

将RESP.app的备份数据转码成AnotherRedisDesktopManager的格式 最近发现了AnotherRedisDesktopManager&#xff0c;这个软件可以直接展示proto数据。 将RESP.app导出的json文件&#xff0c;转码为AnotherRedisDesktopManager的ano文件&#xff08;是一个list转了base64&#xf…

前端基础知识JavaScript系列 - 09(JavaScript原型,原型链 )

一、原型 JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象 当试图访问一个对象的属性时&#xff0c;它不仅仅在该对象上搜寻&#xff0c;还会搜寻该对象的原型&#xff0c;以及该对象的原型的原型&#xff0c;依次层层向上搜索&#xff0c;直到找到一个…