简历_使用优化的Redis自增ID策略生成分布式环境下全局唯一ID,用于用户上传数据的命名以及多种ID的生成

系列博客目录


文章目录


Why

我们需要设置全局唯一ID。原因:当用户抢购时,就会生成订单并保存到tb_voucher_order这张表中,而订单表如果使用数据库自增ID就存在一些问题。

问题:id的规律性太明显、受单表数据量的限制。所以在自己的项目中,针对上传的数据的ID的生成也可以使用全局唯一ID。表中有ID,属性类型(文本、音频、图像)以及存储位置,文件名(文件名由ID+原始文件名作为后缀组成)。

多种ID比如用户ID,订单ID。

全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般要满足下列特性:高可用、唯一性、高性能、递增性、安全性。

Redis自增ID策略

为了增加ID的安全性,我们可以不直接使用Redis自增的数值,而是拼接一些其它信息:

ID的组成部分:

  • 符号位:1bit,永远为0
  • 时间戳:31bit,以秒为单位,可以使用69年
  • 序列号:32bit,秒内的计数器,支持每秒产生2^32个不同ID
java 复制代码
package com.hmdp.utils;

import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

@Component
public class RedisIdWorker {
    /**
     * 开始时间戳
     */
    private static final long BEGIN_TIMESTAMP = 1640995200L;
    /**
     * 序列号的位数
     */
    private static final int COUNT_BITS = 32;

    private StringRedisTemplate stringRedisTemplate;

    public RedisIdWorker(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public long nextId(String keyPrefix) {
        // 1.生成时间戳
        LocalDateTime now = LocalDateTime.now();
        long nowSecond = now.toEpochSecond(ZoneOffset.UTC);
        long timestamp = nowSecond - BEGIN_TIMESTAMP;

        // 2.生成序列号
        // 2.1.获取当前日期,精确到天
        String date = now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));
        // 2.2.自增长
        long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + date);

        // 3.拼接并返回
        return timestamp << COUNT_BITS | count;
    }
}

使用的示例代码如下:

java 复制代码
// 7.创建订单
VoucherOrder voucherOrder = new VoucherOrder();
// 7.1.订单id
long orderId = redisIdWorker.nextId("order");
voucherOrder.setId(orderId);
// 7.2.用户id
voucherOrder.setUserId(userId);
// 7.3.代金券id
voucherOrder.setVoucherId(voucherId);
save(voucherOrder);

// 7.返回订单id
return Result.ok(orderId);

每天一个key,方便统计订单量

ID 的构造是 :时间戳 + 计数器

相关推荐
ocean210315 小时前
2025-2026年AI部署与MLOps大厂面试高频问题
人工智能·面试·大模型推理·ai部署
洋不写bug21 小时前
链表面试笔试经典题目详细解析,题目多解法,复杂度分析
数据结构·链表·面试
黄敬峰1 天前
一文搞懂结构化大模型输出:从 SSE 到 Tool Calling 的四种姿势
面试
星星落进兜里1 天前
Redis 内存缓存,面试补充
数据库·redis·面试
蒸蒸yyyyzwd1 天前
cpp 选手秋招学习笔记 day27
服务器·c++·面试·八股
程序员清风1 天前
聊聊怎么缓解找工作的焦虑感?
java·后端·面试
杰克尼1 天前
同城拼车项目面试问题_01
spring·面试·职场和发展
YonyouHRSaaS1 天前
2026年AI招聘系统怎么选?AI面试功能怎么评估?
人工智能·面试·职场和发展·求职招聘·ai面试
写代码像蔡徐抻1 天前
三年了,AI为何还没有抢走程序员饭碗?
前端·后端·面试
YHL1 天前
🚀 SDD:告别「氛围编程」,迎接规范驱动开发新时代
面试