永远要记得坚持的意义

一、全局唯一 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 问题相关推荐

  1. Redis实现全局唯一id,实现优惠卷秒杀的下单功能

    Redis实现全局唯一id public class RedisIdWorker {private StringRedisTemplate stringRedisTemplate;public Red ...

  2. Redis实现全局唯一id

    需求: 每个店铺都可以发布优惠券,而每张优惠券都是唯一的.当用户抢购时,就会生成订单并保存到 tb_voucher_order 这张表中,而订单表如果使用数据库自增 ID 就存在一些问题: id 的规 ...

  3. Redis生成全局唯一ID

    简介: 全局唯一ID生成器是一种在分布式系统下用来生成全局唯一ID的工具 特性: 唯一性 高性能 安全性 高可用 递增性 生成规则: 有时为了增加ID的安全性,我们可以不直接使用Redis自增的数值, ...

  4. c#随机数生成编号_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法...

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

  5. 微信用户全局唯一标识_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法...

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

  6. snowflake做主键 自增_忘掉 Snowflake,感受一下性能高出 587 倍的全局唯一 ID 生成算法...

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

  7. mysql序列号生成_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

  8. 忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

  9. Redis:实现全局唯一ID

    Redis:实现全局唯一ID 一. 概述 二. 实现 (1)获取初始时间戳 (2)生成全局ID 三. 测试 为什么可以实现全局唯一? 其他唯一ID策略 补充:countDownLatch 一. 概述 ...

最新文章

  1. CAD2010安装说明
  2. c++一元稀疏多项式计算器_武忠祥真题班归纳(更新至一元函数积分未完)
  3. 提取手机游戏资源 特效 显存分析工具 无视任何加密
  4. 第 8 章 容器网络 - 051 - 在 overlay 中运行容器
  5. 互联网各岗位的生存指南
  6. Python+pandas+matplotlib控制不同曲线的属性
  7. WebBrowser控件 打印2
  8. c#+asp.net如何删除指定路径下的文件和文件夹
  9. UWB定位记录二(DWM1000模组介绍)
  10. htpp-server开启https服务终端报错问题
  11. WINCE 实用技巧 之 创建快捷方式详解
  12. OpenCV开发笔记(五十七):红胖子8分钟带你深入了解直方图反向投影(图文并茂+浅显易懂+程序源码)
  13. 鞋底php是什么材质,软底鞋是什么?软底鞋的鞋底是什么材质?
  14. system/bt目录内容解析
  15. 数据结构(C语言版第2版)课后习题答案
  16. 道哥:我人生有两大选择,为的却都是同一件事
  17. 安装ubuntu 16.04 + ppa安装NVIDIA显卡驱动
  18. 又来汇丰软件(广东)的帖子了。。。
  19. Ajax 读音,你对了吗
  20. su: failed to execute /bin/bash: Permission denied问题解决

热门文章

  1. 实施部署(锐捷云桌面篇)
  2. 数据驱动业务发展 共建数据技术未来——专访OceanBase数据库创始人阳振坤
  3. CVPR 2020 论文大盘点-图像质量评价篇
  4. 这样写,才可以让JS对象中的key包含短横杠-
  5. 去掉字符串中所有的逗号
  6. 方正计算机驱动程序,方正Founder A5000 驱动
  7. scat TCD按钮
  8. 上传图片并预览 限制个数
  9. 2014牡丹江 现场赛 F zoj 3824 Fiber-optic Network
  10. 华为云数据库GaussDB(for OpenGauss)的连接