利用redis生成自增编号

基本思路

1、利用Redis中RedisAtomicLong类和其方法incrementAndGet()实现自增操作。

2、获取当天剩余的时间转化为秒,设置redis对应key值的失效时间

3、按照编号规则组装数据

遇到的坑

1、编号会存在重复操作,解决方案

 (1)在创建RedisAtomicLong类时使用Redisson分布式锁,详见下列代码

 (2)、使用下面代码替代RedisAtomicLong操作

Long increment = redisTemplate.opsForValue().increment(key, 1);
redisTemplate.expire(key,liveTime, TimeUnit.SECONDS);

2、Redisson分布式锁创建失败,为null,解决方案需要对redisTemplate进行序列化配置

  /**
     * redis key的层级不能超过3层()
     * 根据前缀+日期+每天的自增编号例如(WF2021041411200001)
     *
     * @param prefix
     * @param key
     * @param length
     * @return
     */
    public String getDayIncrCode(String prefix, String key, int length) {
        String code = "";
        String formatDay = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        Long dayEndTime = getAppointDateTimeMills();
        //当天失效
        long liveTime = (dayEndTime - System.currentTimeMillis()) / 1000;
        Long incre = getIncre(key, liveTime);
        String sequence = getSequence(incre, length);
        if (StrUtil.isNotBlank(prefix)) {
            code = code + prefix;
        }
        code = code + formatDay + sequence;

        return code;
    }

 获取当天结束的时间戳

 /**
     * 获取指定时间毫秒值
     *
     * @return
     */
    public static Long getAppointDateTimeMills() {
        Calendar ca = Calendar.getInstance();
        //失效的时间
        ca.set(Calendar.HOUR_OF_DAY, 23);
        ca.set(Calendar.MINUTE, 59);
        ca.set(Calendar.SECOND, 59);
        long curtime = ca.getTimeInMillis();
        return curtime;
    }

利用Redis中RedisAtomicLong生成自增(核心使用了 redis中的increment方法)

//RedisAtomicLong源码
public long incrementAndGet() {
        return this.operations.increment(this.key, 1L);
    }
  /**
     * 获取redis原子自增数据
     *
     * @param key
     * @param liveTime
     * @return
     */
    public Long getIncre(String key, long liveTime) {
        RedisAtomicLong counter = null;
        RLock lock = null;
        if (!redisTemplate.hasKey(key)) {
            try {
                lock = redissonLock.lock(key, 1);
                counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
            } finally {
                redissonLock.unlock(lock);
            }
        } else {
            counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        }
        Long increment = counter.incrementAndGet();
        //初始设置过期时间
        boolean result = (null == increment || increment.longValue() == 0) && liveTime > 0;
        if (result) {
            counter.set(1);
            counter.expire(liveTime, TimeUnit.SECONDS);
            increment = 1L;
        }
        return increment;
    }

格式化数据 

   /**
     * 补全自增的数据
     *
     * @param seq
     * @param length
     * @return
     */
    public static String getSequence(long seq, int length) {
        String str = String.valueOf(seq);
        int len = str.length();
        // 取决于业务规模,应该不会到达4
        if (len >= length) {
            return str;
        }
        int rest = length - len;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < rest; i++) {
            sb.append('0');
        }
        sb.append(str);
        return sb.toString();
    }

测试

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class IdUtilsTest {

    @Autowired
    private IdUtils idUtils;

    @Test
    public void testSequenceCode() {
        String key="test:er6666:6666:934";
        String formatDay = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        key=key+formatDay;
        for (int i = 0; i < 20; i++) {
            String st = idUtils.getDayIncrCode("ST", key, 4);
            System.out.println(st);
        }
    }
}

输出结果

 

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要使用Redis生成自增ID,可以借助Redis的INCR命令。INCR命令用于将一个键的值增加1,并返回增加后的值。你可以在你的代码中使用INCR命令来生成自增ID。下面是一个示例代码片段: ``` @ApiOperation("根据key生成自增Id") @RequestMapping(value = "/getId/{key}", method = RequestMethod.GET) public GenericResponse<Long> getId(@PathVariable("key") String key) { logger.info("生成Id中"); Long id = redisTemplate.opsForValue().increment(key, 1); return new GenericResponse<>(id); } ``` 在这个示例中,我们使用了Spring Data Redis提供的`redisTemplate`来执行INCR命令,通过操作键的值来实现自增。当调用这个接口时,每次都会生成一个自增的ID,并返回给用户。你可以根据实际需求对生成的ID进行格式化,比如添加日期前缀或补0等操作。 需要注意的是,为了使用Redis生成自增ID,你需要先确保已经正确地配置了Redis服务器,并在代码中引入相关的依赖。此外,你还可以使用Redis的其他功能,比如设置过期时间等,来满足自己的业务需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [REDIS生成分布式环境下自增ID](https://blog.csdn.net/yucaifu1989/article/details/122132257)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [毕设项目:基于SpringBoot+MyBatis-Plus 前后端分离的影院选座购票系统.zip](https://download.csdn.net/download/dd_vision/88222307)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值