如何使用redis生成流水号 redis持久化

2023-12-07 11:50

本文主要是介绍如何使用redis生成流水号 redis持久化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如何使用redis生成流水号

  • 概述
  • 原理介绍
  • 流程图
      • 1、初始化流水号信息进入缓存
      • 2、生成流水号
  • 代码实现
      • 1、流水号实体类
      • 2、初始化流水号进入缓存
      • 3、生成流水号
  • 代码测试
      • 普通测试
      • 并发测试
  • redis 持久化
      • RDB
      • AOF
  • 注意

概述

本文讲述如何使用redis生成流水号。本文是在Springboot中实现的。知道原理之后其他框架也可以轻松实现。

原理介绍

本文主要是使用redis的incr方法进行自增补零。然后结合时间、随机数、前缀组成唯一的流水号。

在这里插入图片描述
下面是流水号的结构。
在这里插入图片描述
在文章的最后还是简单介绍一下redis的持久化。防止redis宕机导致自增数重置。从而导致流水号重复。


流程图

本次实现分为
1、初始化流水号信息进入缓存
2、生成流水号

下面是分别的大致流程图

1、初始化流水号信息进入缓存

在这里插入图片描述

2、生成流水号

在这里插入图片描述

代码实现

1、流水号实体类

用于存储流水号信息


@Data
public class YuSnGenCode {// 流水号生成依赖的类,会使用类的名称作为redis的key private Class entity;// 前缀private String prefix;// 自增数位数 自增数达不到此位数自动补零private Integer num;public YuSnGenCode(Class entity, String prefix, Integer num) {this.entity = entity;this.prefix = prefix;this.num = num;}
}

2、初始化流水号进入缓存

在程序启动之后初始化流水号


@Component
@Slf4j
public class YuSnGenStart implements ApplicationRunner {@AutowiredYuSnGenUtil yuSnGenUtil;@Overridepublic void run(ApplicationArguments args) throws Exception {log.info("=====开始初始化流水号=====");List<YuSnGenCode> yuSnGenCodeList = new ArrayList<>();yuSnGenCodeList.add(new YuSnGenCode(Account.class, "AC", 6));yuSnGenCodeList.add(new YuSnGenCode(Shop.class, "DP", 6));yuSnGenCodeList.add(new YuSnGenCode(Order.class, "OR", 6));yuSnGenCodeList.add(new YuSnGenCode(Dispatch.class, "DL", 6));yuSnGenCodeList.add(new YuSnGenCode(Refund.class, "RF", 6));yuSnGenCodeList.add(new YuSnGenCode(PayLog.class, "PL", 6));yuSnGenCodeList.add(new YuSnGenCode(Withdrawal.class, "WR", 6));yuSnGenCodeList.add(new YuSnGenCode(Aftermarket.class, "AS", 6));yuSnGenCodeList.add(new YuSnGenCode(Coupon.class, "CO", 6));yuSnGenCodeList.add(new YuSnGenCode(CouponGen.class, "CG", 10));yuSnGenCodeList.add(new YuSnGenCode(Draw.class, "DP", 6));yuSnGenUtil.init(yuSnGenCodeList);log.info("=====初始化流水号完毕=====");}
}
  public void init(List<YuSnGenCode> yuSnGenCodes) {// 流水号初始化入缓存for (YuSnGenCode yuSnGenCode : yuSnGenCodes) {String redisKey = yuSnGenCode.getEntity().getName();// 存入缓存 key:key:实体类名称 value:流水号数据(前缀、自增数位数)redisTemplate.opsForValue().set(yuSnGenCode.getEntity().getName(), FastJsonUtils.toJsonStr(yuSnGenCode));log.info(yuSnGenCode.getEntity().getName() + "已初始化");}}

初始化之后的流水号如下图所示
在这里插入图片描述

3、生成流水号

   public Optional<String> gen(Class c) {// 获取实体类的名称String redisKey = c.getName();// 判断是不是有初始化此实体类if (null != redisTemplate.opsForValue().get(redisKey)) {// 从缓存获取流水号的生成信息YuSnGenCode yuSnGenCode = FastJsonUtils.toBean(redisTemplate.opsForValue().get(redisKey).toString(), YuSnGenCode.class);// 根据流水号的前缀判断今天是否有生成过流水号if (redisTemplate.opsForValue().get(yuSnGenCode.getPrefix()) == null) {// 没有则新建一个存入缓存 格式(key:OR  value:0)// 设置到第二天早上00:00:01过期Long todayTime = LocalDate.now().plusDays(1).atTime(0, 0, 0, 1).atOffset(ZoneOffset.ofHours(8)).toEpochSecond();Long nowTime = LocalDateTime.now().atOffset(ZoneOffset.ofHours(8)).toEpochSecond();Long expireTime = todayTime - nowTime;redisTemplate.opsForValue().set(yuSnGenCode.getPrefix(), 0, expireTime*1000, TimeUnit.MILLISECONDS);}// 进行自增操作StringBuffer sn = new StringBuffer();// 和前缀、时间、随机数进行组合sn.append(yuSnGenCode.getPrefix());String date = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));sn.append(date);Long num = redisTemplate.opsForValue().increment(yuSnGenCode.getPrefix());sn.append(addZero(String.valueOf(num), yuSnGenCode.getNum()));String random = String.valueOf(new Random().nextInt(1000));sn.append(random);// 生成最终的流水号返回return Optional.ofNullable(sn.toString());}return Optional.ofNullable(null);}
 // 自动补零public String addZero(String numStr, Integer maxNum) {int addNum = maxNum - numStr.length();StringBuffer rStr = new StringBuffer();for (int i = 0; i < addNum; i++) {rStr.append("0");}rStr.append(numStr);return rStr.toString();}

第一次生成流水号之后redis中会有一个以此流水号的前缀作为key的数据,后续直接进行自增。无需新增
在这里插入图片描述

代码测试

普通测试

   public Response test2() {return Response.success(yuSnGenUtil.gen(Order.class).get());}

结果如下
在这里插入图片描述

并发测试

这里我们使用ab进行压力并发测试
测试前我们流水号数据为0
在这里插入图片描述
进行5000请求100并发的测试
在这里插入图片描述
请求完毕之后流水号的数据是5000是没有问题的。
在这里插入图片描述

redis 持久化

redis持久化指redis意外退出之后重启仍然能够恢复之前数据。我们这里使用redis持久化防止redis意外退出重启导致流水号数据重置,从而导致我们的流水号生成重复。

Redis 提供了不同级别的持久化方式:

RDB

RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.

AOF

AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据

我们本次使用的是AOF的方式
在这里插入图片描述
根据官网的提示。我们只需要去redis.config文件中开启appendonly就可以了。这样redis会生成appendonly.aof文件,服务器重启的时候会重新执行这些命令来恢复原始的数据。
在这里插入图片描述

注意

因为AOF的默认备份方式有三种

1、always每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全
2、everysec每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
3、no从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。
而我们采用的是第二种。也是AOF默认的的。但是这样故障时可能会损失1s的数据,所以如果对数据要求十分严格的同学可以采用第一种方式只需要修改redis.config文件的appendfsync属性即可。
在这里插入图片描述

以上就是今天介绍的利用redis的incr自增方法编写生成流水号。如果有什么问题欢迎评论区指出。谢谢🙏

这篇关于如何使用redis生成流水号 redis持久化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/465765

相关文章

SpringBoot中使用Flux实现流式返回的方法小结

《SpringBoot中使用Flux实现流式返回的方法小结》文章介绍流式返回(StreamingResponse)在SpringBoot中通过Flux实现,优势包括提升用户体验、降低内存消耗、支持长连... 目录背景流式返回的核心概念与优势1. 提升用户体验2. 降低内存消耗3. 支持长连接与实时通信在Sp

python使用库爬取m3u8文件的示例

《python使用库爬取m3u8文件的示例》本文主要介绍了python使用库爬取m3u8文件的示例,可以使用requests、m3u8、ffmpeg等库,实现获取、解析、下载视频片段并合并等步骤,具有... 目录一、准备工作二、获取m3u8文件内容三、解析m3u8文件四、下载视频片段五、合并视频片段六、错误

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

在Windows上使用qemu安装ubuntu24.04服务器的详细指南

《在Windows上使用qemu安装ubuntu24.04服务器的详细指南》本文介绍了在Windows上使用QEMU安装Ubuntu24.04的全流程:安装QEMU、准备ISO镜像、创建虚拟磁盘、配置... 目录1. 安装QEMU环境2. 准备Ubuntu 24.04镜像3. 启动QEMU安装Ubuntu4

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

Python常用命令提示符使用方法详解

《Python常用命令提示符使用方法详解》在学习python的过程中,我们需要用到命令提示符(CMD)进行环境的配置,:本文主要介绍Python常用命令提示符使用方法的相关资料,文中通过代码介绍的... 目录一、python环境基础命令【Windows】1、检查Python是否安装2、 查看Python的安

Python并行处理实战之如何使用ProcessPoolExecutor加速计算

《Python并行处理实战之如何使用ProcessPoolExecutor加速计算》Python提供了多种并行处理的方式,其中concurrent.futures模块的ProcessPoolExecu... 目录简介完整代码示例代码解释1. 导入必要的模块2. 定义处理函数3. 主函数4. 生成数字列表5.