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

使用Redis生成全局唯一id

为了生成一个符合要求的分布式全局ID,我们可以使用 StringRedisTemplate 来实现。这个ID由三部分组成:

  1. 符号位(1 bit):始终为0,表示正数。
  2. 时间戳(31 bit):表示从某个起始时间点(例如2023-01-01 00:00:00)到现在的秒数。
  3. 序列号(32 bit):用于在同一秒内生成不同的ID。

实现步骤

  1. 计算时间戳:从某个起始时间点到现在的秒数。
  2. 生成序列号:使用Redis的原子递增操作来生成序列号。
  3. 组合ID:将时间戳和序列号组合成一个64位的长整型数字。

代码实现

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.TimeUnit;@Service
public class DistributedIdGenerator {@Autowiredprivate StringRedisTemplate stringRedisTemplate;// 起始时间点,例如2023-01-01 00:00:00private static final long EPOCH = ZonedDateTime.of(2023, 1, 1, 0, 0, 0, 0, ZoneId.systemDefault()).toInstant().toEpochMilli() / 1000;// 序列号的Redis键前缀private static final String SEQUENCE_KEY_PREFIX = "sequence:";/*** 生成分布式全局ID** @return 分布式全局ID*/public long generateId() {// 获取当前时间戳(从起始时间点到现在的秒数)long currentTimeSec = Instant.now().getEpochSecond() - EPOCH;// 生成序列号String sequenceKey = SEQUENCE_KEY_PREFIX + currentTimeSec;long sequence = stringRedisTemplate.opsForValue().increment(sequenceKey, 1);if (sequence >= (1L << 32)) { // 序列号溢出,重置为0stringRedisTemplate.expire(sequenceKey, 1, TimeUnit.SECONDS); // 设置1秒后过期sequence = 0;}// 组合IDlong id = (currentTimeSec << 32) | sequence;return id;}
}

代码解释

  1. EPOCH:起始时间点,例如2023-01-01 00:00:00,转换为秒数。
  2. SEQUENCE_KEY_PREFIX:Redis中存储序列号的键前缀。
  3. generateId 方法
    • currentTimeSec:从起始时间点到现在的秒数。
    • sequenceKey:根据当前时间戳生成的Redis键。
    • sequence:使用 opsForValue().increment 方法生成序列号,确保在同一秒内生成不同的ID。
    • 序列号溢出处理:如果序列号达到最大值(2^32 - 1),则重置为0,并设置键在1秒后过期。
    • 组合ID:将时间戳左移32位,然后与序列号进行按位或操作,生成最终的64位ID。

测试代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class IdController {@Autowiredprivate DistributedIdGenerator idGenerator;@GetMapping("/generate-id")public long generateId() {return idGenerator.generateId();}
}

http://www.lryc.cn/news/492350.html

相关文章:

  • pnpm:包管理的新星,平替 npm 和 yarn
  • Android调起系统分享图片到其他应用
  • 详解Qt QBuffer
  • Python基础学习-11函数参数
  • GTK#框架让C# Winform程序跨平台运行
  • 在Kubernetes使用CronJob实现定时删除指定天数外的文件(我这里使用删除备份mysql数据库文件为例)
  • 使用 Elastic 收集 Windows 遥测数据:ETW Filebeat 输入简介
  • 力扣-位运算-4【算法学习day.44】
  • Stable Diffusion 3详解
  • c#异步编程(async/await)
  • TCP/IP学习笔记
  • 0000_vim自定义快捷键_alias
  • Spring Boot项目中,实体类是否需要实现Serializable接口
  • 打通工业通信壁垒实现Ethernetip转profinet网络互通
  • 数据结构_图的应用
  • C#中面试的常见问题002
  • 快速理解微服务中Ribbon的概念
  • K8S简介、使用教程
  • 极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【四】
  • 麦肯锡报告 | 科技落地的真谛:超越技术本身的价值创造
  • 彻底解决 macOS 下Matplotlib 中文显示乱码问题
  • STM32-- keil 的option for target使用
  • 【MCU】微控制器的编程技术:ISP 与 IAP
  • C#基础题总结
  • Elasticsearch中的节点(比如共20个),其中的10个选了一个master,另外10个选了另一个master,怎么办?
  • 《参与中型项目,领略 Spring 魅力》
  • 计算机网络-GRE(通用路由封装协议)简介
  • 开源电话机器人产品的优点是什么?
  • Spring Boot 集成 Knife4j 的 Swagger 文档
  • 极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【一】