【Redis】解决全局唯一 id 问题
永远要记得坚持的意义
一、全局唯一 id 场景
概念: 以订单表的 id 为例
使用自增 id 会产生的问题:
- id 的规律性太明显,容易让用户猜测到一些信息
- 受表单数据量的限制 —— 分布式存储时,会产生问题 (自增长,容易产生 id 重复)
因此,我们需要定义全局 id
二、全局 id 生成器
全局 id 生成器的特性:
分布式系统下用来生成全局唯一 id 的工具,其特性有:
- 唯一性
- 高可用
- 高性能
- 递增性
- 安全性
全局唯一 id 生成的实现:
- UUID
16进制字符串,不单调递增,jdk自带的 - Redis 自增
- snowflake 算法
对时钟依赖非常高 - 数据库自增策略
数据库单独设置一个自增表,获取自增,实现唯一效果 (单调自增的数据库版,性能没有 Redis 自增好)
我们本文主要介绍 使用 Redis 作为全局唯一 id 生成器
我们不直接使用 redis 自增的数值,而是拼接一些其他信息,主要拼接的信息如下:
符号位 + 时间戳 + 序列号
三、技术实现
封装好的 Redis 生成唯一 id 的工具类如下:
@Component
public class RedisIdWorker {private static final long BEGIN_TIME = 1670198400;private StringRedisTemplate stringRedisTemplate;private RedisIdWorker(StringRedisTemplate stringRedisTemplate){this.stringRedisTemplate = stringRedisTemplate;}public long nextId(String keyPrefix){// 1. 生成时间戳LocalDateTime localDateTime = LocalDateTime.now();long nowSecond = localDateTime.toEpochSecond(ZoneOffset.UTC);long timestamp = nowSecond - BEGIN_TIME;// 2. 生成序列号 —— 防止超过上限(Redis 自增的上限 2 的64 次幂) 解决方式:再拼接一个日期字符串// 2.1 获取当前日期String day = localDateTime.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"));long count = stringRedisTemplate.opsForValue().increment("icr:" + keyPrefix + ":" + day);// 3. 拼接并返回return timestamp<<32 | count; // 前 32 位为时间戳 ,后 32 位为 序列号(即 count)}// 生成时间戳开始时间 —— 我这里是 2022 / 12/ 5 日开始
// public static void main(String[] args) {// LocalDateTime time = LocalDateTime.of(2022, 12, 5, 0, 0, 0);
// long second = time.toEpochSecond(ZoneOffset.UTC);
// System.out.println(second);
// }
}
测试类代码:
@Slf4j
@SpringBootTest
class HmDianPingApplicationTests {@Autowiredprivate RedisIdWorker redisIdWorker;// 500 线程的线程池子private ExecutorService es = Executors.newFixedThreadPool(500);@Testpublic void testIdWorker() throws InterruptedException {CountDownLatch latch = new CountDownLatch(200);// 每个线程生成 100 个 idRunnable task = () -> {for (int i=0; i<5; i++) {long id = redisIdWorker.nextId("order");log.info("id=" + id);}latch.countDown();};long begin = System.currentTimeMillis();for (int i=0; i<200; i++){es.submit(task);}latch.await();long end = System.currentTimeMillis();log.info("time=" + (end - begin));}}
使用全局唯一 id 解决秒杀业务
@Resourceprivate RedisIdWorker redisIdWorker;@Resourceprivate ISeckillVoucherService seckillVoucherService;@Override@Transactionalpublic Result seckillVoucher(Long voucherId) {// 1. 查询优惠券SeckillVoucher voucher = seckillVoucherService.getById(voucherId);// 2. 判断秒杀是否开始if(voucher.getBeginTime().isAfter(LocalDateTime.now())){return Result.fail("秒杀还未开始");}// 3. 判断秒杀是否已经结束if(voucher.getEndTime().isBefore(LocalDateTime.now())){return Result.fail("秒杀已经结束");}// 4. 判断库存是否充足if(voucher.getStock() < 1){return Result.fail("库存不足");}// 5. 扣除库存boolean success = seckillVoucherService.update().setSql("stock = stock - 1").eq("voucher_id", voucherId).update();if (!success){return Result.fail("库存不足");}// 6. 创建订单VoucherOrder voucherOrder = new VoucherOrder();// 订单的参数 —— 订单 id \ 代金券 id \ 用户 id// 生成唯一 idlong id = redisIdWorker.nextId("order");voucherOrder.setId(id);voucherOrder.setVoucherId(voucherId);voucherOrder.setUserId(1L);save(voucherOrder);return Result.ok();}
【Redis】解决全局唯一 id 问题相关推荐
- Redis实现全局唯一id,实现优惠卷秒杀的下单功能
Redis实现全局唯一id public class RedisIdWorker {private StringRedisTemplate stringRedisTemplate;public Red ...
- Redis实现全局唯一id
需求: 每个店铺都可以发布优惠券,而每张优惠券都是唯一的.当用户抢购时,就会生成订单并保存到 tb_voucher_order 这张表中,而订单表如果使用数据库自增 ID 就存在一些问题: id 的规 ...
- Redis生成全局唯一ID
简介: 全局唯一ID生成器是一种在分布式系统下用来生成全局唯一ID的工具 特性: 唯一性 高性能 安全性 高可用 递增性 生成规则: 有时为了增加ID的安全性,我们可以不直接使用Redis自增的数值, ...
- c#随机数生成编号_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法...
今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...
- 微信用户全局唯一标识_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法...
今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...
- snowflake做主键 自增_忘掉 Snowflake,感受一下性能高出 587 倍的全局唯一 ID 生成算法...
今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...
- mysql序列号生成_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法
今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...
- 忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法
今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...
- Redis:实现全局唯一ID
Redis:实现全局唯一ID 一. 概述 二. 实现 (1)获取初始时间戳 (2)生成全局ID 三. 测试 为什么可以实现全局唯一? 其他唯一ID策略 补充:countDownLatch 一. 概述 ...
最新文章
- CAD2010安装说明
- c++一元稀疏多项式计算器_武忠祥真题班归纳(更新至一元函数积分未完)
- 提取手机游戏资源 特效 显存分析工具 无视任何加密
- 第 8 章 容器网络 - 051 - 在 overlay 中运行容器
- 互联网各岗位的生存指南
- Python+pandas+matplotlib控制不同曲线的属性
- WebBrowser控件 打印2
- c#+asp.net如何删除指定路径下的文件和文件夹
- UWB定位记录二(DWM1000模组介绍)
- htpp-server开启https服务终端报错问题
- WINCE 实用技巧 之 创建快捷方式详解
- OpenCV开发笔记(五十七):红胖子8分钟带你深入了解直方图反向投影(图文并茂+浅显易懂+程序源码)
- 鞋底php是什么材质,软底鞋是什么?软底鞋的鞋底是什么材质?
- system/bt目录内容解析
- 数据结构(C语言版第2版)课后习题答案
- 道哥:我人生有两大选择,为的却都是同一件事
- 安装ubuntu 16.04 + ppa安装NVIDIA显卡驱动
- 又来汇丰软件(广东)的帖子了。。。
- Ajax 读音,你对了吗
- su: failed to execute /bin/bash: Permission denied问题解决