Redis实现全局唯一Id

一、全局唯一ID

每个店铺都可以发布优惠券:

当用户抢购时,就会生成订单并保存到tb_voucher_order这张表中,而订单表如果使用数据库自增ID就存在一些问题:

  • id的规律性太明显

  • 受单表数据量的限制

场景分析:如果我们的id具有太明显的规则,用户或者说商业对手很容易猜测出来我们的一些敏感信息,比如商城在一天时间内,卖出了多少单,这明显不合适。

场景分析二:随着我们商城规模越来越大,mysql的单表的容量不宜超过500W,数据量过大之后,我们要进行拆库拆表,但拆分表了之后,他们从逻辑上讲他们是同一张表,所以他们的id是不能一样的, 于是乎我们需要保证id的唯一性。

全局ID生成器,是一种在分布式系统下用来生成全局唯一ID的工具,一般要满足下列特性:

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

成部分:符号位:1bit,永远为0

时间戳:31bit,以秒为单位,可以使用69年

序列号:32bit,秒内的计数器,支持每秒产生2^32个不同ID

二、Redis实现全局唯一Id

package com.dfrz.utils;import org.springframework.beans.factory.annotation.Autowired;
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 MyRedisIncreaseIdUtil {/*** 开始时间戳,2022年1月1日0时0分0秒的时间的时间戳*/private static final long BEGIN_TIMESTAMP = 1640995200L;/*** 序列号的位数*/private static final int COUNT_BITS = 32;private static final String INCREASE_ID_PRE = "increase:id";@Autowiredprivate 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(INCREASE_ID_PRE + keyPrefix + ":" + date);// 3.拼接并返回return timestamp << COUNT_BITS | count;}/* public static void main(String[] args) {//使用LocalDateTime.of()方法创建了一个LocalDateTime对象,代表2022年1月1日0时0分0秒的时间LocalDateTime time = LocalDateTime.of(2022, 1, 1, 0, 0, 0);//使用toEpochSecond()方法将这个时间转换为从1970年1月1日0时0分0秒(UTC时间)开始的秒数long second = time.toEpochSecond(ZoneOffset.UTC);System.out.println(second);}*/}

测试类:

三、详细介绍

这段代码定义了一个名为MyRedisIncreaseIdUtil的类,用于生成基于时间和Redis自增操作的唯一ID。

具体来说,该类做了以下几件事情:

  1. 定义常量

    • BEGIN_TIMESTAMP:这是开始时间戳,代表2022年1月1日0时0分0秒的时间的时间戳。
    • COUNT_BITS:这是序列号的位数,这里设置为32位。
    • INCREASE_ID_PRE:这是一个字符串常量,用于在Redis中作为键的前缀。
  2. 注入依赖

    • 使用@Autowired注解将StringRedisTemplate对象注入到stringRedisTemplate成员变量中,这是Spring框架的自动装配特性。
  3. 实现生成ID的方法

    • nextId(String keyPrefix):这是一个公共方法,接受一个字符串参数keyPrefix,并返回一个长整型ID。
      • 首先,使用LocalDateTime.now()获取当前时间,然后通过toEpochSecond(ZoneOffset.UTC)方法将其转换为Unix时间戳(从1970年1月1日0时0分0秒开始的秒数)。
      • 接着,使用now.format(DateTimeFormatter.ofPattern("yyyy:MM:dd"))获取当前日期,精确到天,并格式化为"yyyy:MM:dd"的字符串格式。
      • 然后,使用stringRedisTemplate.opsForValue().increment()对Redis中的键进行原子自增操作。这里使用了格式化的日期作为Redis键的一部分,以确保每个日期只有一个序列号。
      • 最后,通过位运算(左移操作符<<)将时间戳转换为二进制表示中的高位,序列号转换为低位,然后使用位或操作符|将它们拼接在一起,形成一个唯一的ID。

这个类的主要目的是生成基于当前时间和Redis自增操作的唯一ID,通过时间戳保证全局唯一性,通过Redis自增操作保证同一日期内的唯一性。

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

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

相关文章

两整数之和

题目链接 两整数之和 题目描述 注意点 不使用 运算符 和 - ​​​​​​​&#xff0c;计算并返回两整数之和-1000 < a, b < 1000 解答思路 需要用位运算来模拟加法&#xff0c;关键是要找到相加的和以及进位1的部分。如果不考虑进位的话&#xff0c;相加可以运用异…

Redis内部数据结构Dict结构详解

目录 dict的数据结构定义 dict的创建&#xff08;dictCreate&#xff09; dict的查找&#xff08;dictFind&#xff09; dict的插入&#xff08;dictAdd和dictReplace&#xff09; dict的删除&#xff08;dictDelete&#xff09; 如果你使用过Redis&#xff0c;一定会像我一样对…

STM32F103标准外设库——GPIO 输入、输出 (五)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

高级 Python 面试问题与解答

文章目录 专栏导读1.什么是PIP&#xff1f;2.什么是 zip 函数&#xff1f;3.Python 中的 __init __ () 是什么&#xff1f;4.Python 中的访问说明符是什么&#xff1f;5.Python 中的单元测试是什么&#xff1f;6.Python全局解释器锁&#xff08;GIL&#xff09;&#xff1f;7.P…

浪花 - 搜索标签前后端联调

前传&#xff1a;浪花 - 根据标签搜索用户-CSDN博客 目录 一、完善后端搜索标签接口 二、前后端搜索标签接口的对接 1. 使用 Axios 发送请求 2. 解决跨域问题 3. Axios 请求传参序列化 4. 接收后端响应数据 5. 处理后端响应数据格式 6. 搜索结果为空的页面展示 附&am…

区域入侵/区域人数统计AI边缘计算智能分析网关V4如何修改IP地址?

智能分析网关V4是TSINGSEE青犀推出的一款AI边缘计算智能硬件&#xff0c;硬件采用BM1684芯片&#xff0c;集成高性能8核ARM A53&#xff0c;主频高达2.3GHz&#xff0c;INT8峰值算力高达17.6Tops&#xff0c;FB32高精度算力达到2.2T&#xff0c;硬件内置了近40种AI算法模型&…

C++ 后端面试 - 题目汇总

文章目录 &#x1f37a; 非技术问题&#x1f37b; 基本问题&#x1f942; 请自我介绍&#xff1f;&#x1f942; 你有什么问题需要问我的&#xff1f; &#x1f37b; 加班薪资&#x1f942; 你对加班有什么看法&#xff1f;&#x1f942; 你的薪资期望是多少&#xff1f;【待回…

如何避免知识付费小程序平台的陷阱?搭建平台的最佳实践

随着知识经济的兴起&#xff0c;知识付费已经成为一种趋势。越来越多的人开始将自己的知识和技能进行变现&#xff0c;而知识付费小程序平台则成为了一个重要的渠道。然而&#xff0c;市面上的知识付费小程序平台琳琅满目&#xff0c;其中不乏一些不良平台&#xff0c;让老实人…

SpringBoot ES 聚合后多字段加减乘除

SpringBoot ES 聚合后多字段加减乘除 在SpringData Elasticsearch中&#xff0c;聚合统计的原理主要依赖于Elasticsearch本身的聚合框架。Elasticsearch提供了强大的聚合功能&#xff0c;使得你可以对文档进行各种计算和统计&#xff0c;从而得到有关数据集的有用信息。 Elast…

Cloudflare cdn 基本使用

个人版免费试用&#xff0c;一个邮箱账号只能缓存一个网站cdn。 地址&#xff1a;cloudflare.com 创建站点 在网站创建站点&#xff0c;填上你的域名 点击进入网站 缓存全局配置 可清除缓存&#xff0c;设置浏览器缓存时间 我设置了always online,防止服务器经常不稳定 缓…

第二回 史大郎夜走华阴县 鲁提辖拳打镇关西- Linux新手快速入门

却说九纹龙史进跟朱武等三人约好了中秋赏月&#xff0c;却不料这天突然失火&#xff0c;房子都被一把火烧光。于是史进只好夜里跟着朱武等人一起离开华阴县。朱武劝他到少华山一起干&#xff0c;史进说&#xff1a;我的师傅王进&#xff0c;说要到延安府做事&#xff0c;我去投…

AI in Cybersecurity

人工智能在网络安全领域扮演着重要角色。它的应用和技术为网络安全提供了更有效的工具和方法&#xff0c;以提高网络的安全性&#xff0c;并保护网络免受恶意活动的影响。 人工智能在威胁检测和威胁情报收集方面发挥着关键作用。通过分析大量的网络数据和日志&#xff0c;人工智…

处理表格(数字里有,代码不认为他是数字的情况)

表格在CSV2024_actual 需求&#xff0c;把每个月的cost相加&#xff0c;最后算出全年度cost&#xff0c;把每个Q的cost相加&#xff0c;q1q2q3q4&#xff0c;得出q的总和 遇到问题&#xff0c;一开始算出来都是0&#xff0c;后面发现数字之间有千位分隔符&#xff0c;所以代码…

04--MySQL函数的使用

1、SQL函数的使用 当我们学习编程语言的时候&#xff0c;经常会遇到函数。函数的好处是&#xff0c;它可以把我们经常使用的代码封装起来&#xff0c;需要的时候直接调用即可。这样既提高了编写代码的效率&#xff0c;又提高了可维护性。在SQL中函数主要要对数据进行处理&…

Linux实操学习

Linux常用操作 一、帮助命令1. man1.1 基本语法1.2 快捷键1.3 注意事项 2. help2.1 基本语法2.2 注意事项 3. 常用快捷键 二、文件目录类1. 常规操作1.1 pwd1.2 cd1.3 ls 2. 文件夹操作2.1 mkdir2.2 rmdir 3. 文件操作3.1 touch3.2 cp3.3 rm3.4 mv 4. 文件查看4.1 cat4.2 more4…

Math.ceil + Math.max 找出数组最大值并向上取整十位数或者整百位数

1、声明数组 let arr [125, 52, 85, 526, 658, 738] 2、找出数组最大值并向上取整十位数 console.log(Math.ceil(Math.max(...arr) / 10) * 10); // 740 console.log(Math.ceil(Math.max(...arr) / 50) * 50); // 750 3、找出数组最大值并向上取整百位数 console.log(Math…

Hive聚合函数详细讲解

Hive中的聚合函数用于在数据上进行计算并返回单个值,这些值通常是基于一组行或列的汇总。以下是您提到的聚合函数的详细讲解,包括案例和使用注意事项: SUM() 功能:计算某列的总和。语法:SUM(column)案例:SELECT SUM(salary) FROM employees;注意事项:通常用于数值型列。…

常用界面设计组件 —— 窗体(QT)

二、常用界面设计组件2.1 窗体2.1.1 设置窗体位置、大小及背景颜色2.1.2 设置窗体标题2.1.3 多窗体调用 二、常用界面设计组件 组件是GUI的基本元素&#xff0c;也称为UI控件。它接受来自底层平台的不同用户事件&#xff0c;如鼠标和键盘事件&#xff08;以及其它事件&#xf…

Mybatis 41_构造器映射及使用注解完成构造器映射

41_构造器映射 构造器映射&#xff1a;XML Mapper项目0503构造器映射 ConstructorArgs注解项目0504构造器映射_注解 构造器映射&#xff1a; 构造器映射能控制MyBatis调用指定、有参数的构造器来创建结果集要映射的Java对象 XML Mapper 在<resultMap…/>元素内添加<…

AI扩展手写数字识别应用(二)

理解代码 输入处理 在新应用的代码部分&#xff0c;和我们在手写数字识别课程介绍的代码比起来&#xff0c;差别最大的地方就在于如何处理输入。在上个案例中&#xff0c;我们只需要简单地将正方形区域中的图像格式调整一下&#xff0c;即可用作MNIST模型的输入。而在本文的案…