首页 > 数据库 >这儿有一个基于redis生成订单流水号的工具,拿走不谢!

这儿有一个基于redis生成订单流水号的工具,拿走不谢!

时间:2023-12-26 17:04:08浏览次数:45  
标签:return String 不谢 redis 流水号 keyPrefix import

 

1 import cn.hutool.core.util.RandomUtil;
 2 import cn.hutool.core.util.StrUtil;
 3 import lombok.extern.slf4j.Slf4j;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.data.redis.core.RedisTemplate;
 6 import org.springframework.data.redis.core.script.DefaultRedisScript;
 7 import org.springframework.lang.Nullable;
 8 import org.springframework.stereotype.Component;
 9 
10 import java.time.LocalDateTime;
11 import java.time.format.DateTimeFormatter;
12 import java.util.Collections;
13 import java.util.concurrent.TimeUnit;
14 
15 /**
16  * 生成订单流水号18  * 精确到秒级,后面加随机数(redis获取)
19  * <p>
20  * 变更记录:2023-12-13 14:10 gz.zhang 通过增加随机性,修正因宿主机时钟回拨导致生成重复值的bug
21  * 变更记录:2023-12-19 14:37 刘红洁/张国战 ①key改为按日期,最后的拼接用取模的方式防止数据越界,②解决concat带来的bug。
22  *
23  * @author wangzaizhou
24  */
25 @Component
26 @Slf4j
27 public class GenerateOrderIdUtil {
28     private static final String DEFAULT_KEY_PREFIX = "keyPrefix";
29     private static RedisTemplate<String, Object> stringObjectRedisTemplate;
30 
31     @Autowired
32     public void setRedisUtil(RedisTemplate<String, Object> redisTemplate) {
33         stringObjectRedisTemplate = redisTemplate;
34     }
35 
36     /**
37      * 订单流水号组成: 时间秒 + 5位数(redis计算后的)
38      *
39      * @param keyPrefix redis key的前缀标识,可以指定为 系统标识(如“Channel”),也可以指定为业务标识(如“Pay”),或者具体数据标识(如“PayPaymentFlow”),etc.,也可为空
40      * @return 2021030914590406391
41      */
42     public static long genOrderId(@Nullable String keyPrefix) {
43         if (StrUtil.isBlank(keyPrefix)) {
44             keyPrefix = DEFAULT_KEY_PREFIX;
45         }
46         LocalDateTime now = LocalDateTime.now();
47         String redisKey = keyPrefix + now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
48         Long incrValue = null;
49         try {
50             incrValue = stringObjectRedisTemplate.execute(REDIS_SCRIPT, Collections.singletonList(redisKey), TimeUnit.HOURS.toSeconds(24));
51         } catch (Exception e) {
52             log.error("GenerateOrderIdUtil 生成订单流水号异常,keyPrefix={}", keyPrefix, e);
53         }
54         if (incrValue == null) incrValue = RandomUtil.randomLong(99999);
55         String orderIdPrefix = now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
56         String orderId = String.format("%s%05d", orderIdPrefix, incrValue % 100000);
57         return Long.parseLong(orderId);
58     }
59 
60     /**
61      * 订单流水号组成: 时间秒 + 5位数(redis计算后的)
62      *
63      * @return 2021030914590406391
64      */
65     public static long genOrderId() {
66         return genOrderId(DEFAULT_KEY_PREFIX);
67     }
68 
69     private final static DefaultRedisScript<Long> REDIS_SCRIPT = new DefaultRedisScript<>(
70             "local key = KEYS[1]\n" +
71                     "local expiration_time = (ARGV[1])\n" +
72 
73                     "local current_value = redis.call('INCRBY', key, 1)\n" +
74                     "if current_value == 1 then\n" +
75                     "  redis.call('EXPIRE', key, expiration_time)\n" +
76                     "end\n" +
77                     "return current_value\n"
78             , Long.class);
79 
80 }

 

标签:return,String,不谢,redis,流水号,keyPrefix,import
From: https://blog.51cto.com/u_15708799/8985242

相关文章

  • Redis哨兵内存碎片化故障处理
    背景介绍近期研发同学反馈业务响应波动厉害,怀疑是Redis操作key比较慢的缘故。由于该环境是我一手安装部署的,我将进行问题排查。Redis环境以及业务环境都已经使用Prometheus进行了监控。环境说明我们有两套一样的环境来服务不同的客户,另外一套环境中业务一直平稳运行,Redis并没......
  • Redis系列之事务机制
    什么是Redis事务学习mysql数据库的时候,我们知道了事务的ACID特性,Redis也是支持事务的,不过和数据库的事务又有什么区别?在mysql数据库中,我们使用begin开启事务,提交是commit,回滚是rollback,然后Redis中的事务是怎么一回事?redis的事务其实可以看做是一组命令按照顺序,串行执行队列中的命......
  • Windows下的Redis启动报错Redis service failed to start解决方法
    报错原因:Redis服务没有找到log文件解决方法在Redis安装目录下打开redis.windows-service.conf文件搜索logfile,找到logfile存放目录,一般默认为Logs/redis_log.txt在Redis安装目录创建Logs文件夹,在Logs文件夹下创建redis_log.txt文件重新启动即可解决......
  • Redis相关
    2023.12.26臭宝今天早上起床没拉粑粑,so sad   o(╥﹏╥)o  1.Redis为什么快?Redis是存在内存中的,Redis是单线程的,避免上下文切换。渐进式RehashRedis的所有数据都是存在一个hash数组上的,hash数组每个元素都是一个链表(所有类型都是,如String,hash,list,set,zset,bitma......
  • Redis进阶 Lua函数
    1.可以直接声明一个局部变量来接收函数,也可以直接简写localsquare=function(i)returni*iend简写:localfunctionsquare(i)returni*iend 2.当调用函数时,参数是一一对应的,如果多了参数,则会忽略,少则会将对应位置的参数赋值为nil 3.如果想要实现可变参数个数,也......
  • 美团面试:ES+Redis+MySQL高可用,如何实现?
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • Ubuntu上安装、使用Redis的详细教程
    sudoapt-getupdatesudoapt-getinstallredis启动方式二systemctlstartredis-server启动方式三serviceredis-serverstart重启redisserviceredis-serverrestart关闭redisserviceredis-serverstop查看redis状态serviceredis-serverstatus4、在宿主机连接redis根据以......
  • aioredis
    importasyncioimportaioredisfromconfig.env_configimportREDIS_URLclassRedisClient:def__init__(self,url,decode_responses=True,max_connections=30):self.url=urlself.decode_responses=decode_responsesself.max_c......
  • Redis发布订阅
    Redis的发布订阅(Pub/Sub)是一种消息传递模式,允许消息的发布者(publisher)将消息发送给订阅者(subscriber)。基本概念:发布者(Publisher):发布消息的客户端。订阅者(Subscriber):接收并处理发布者发送的消息的客户端。频道(Channel):消息被发布到的特定通道。发布者将消息发布到指定频道,接受者从频......
  • Redis分布式锁
    1.分布式锁的方案分类方案原理优点缺点基于数据库mysql数据库表的唯一索引1.表创建唯一索引2.加锁:执行insert语句,成功则加锁成功,失败则加锁失败3.解锁:执行delete语句完全利用DB实现,实现简单1.锁无超时自动失效机制,有死锁风险2.不支持锁冲入,不支持阻塞等待3.操作数据......