文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

springboot如何使用redis的incr创建分布式自增id

2022-11-21 22:51

关注

使用redis的incr创建分布式自增id

测试使用springboot加载类测试,使用本地redis, 模拟多线程去生成规律的自增id

@Component
public class Common implements CommandLineRunner {
    @Autowired
    private RedisTemplate redisTemplate;
 
    @Override
    public void run(String... args) throws Exception {
        long start = System.currentTimeMillis();
        Thread thread1 = new Thread(new Test1());
        Thread thread2 = new Thread(new Test1());
        Thread thread3 = new Thread(new Test1());
        thread1.start();
        thread2.start();
        thread3.start();
        long end = System.currentTimeMillis();
        System.out.println("耗时:"+(end-start));
    }
 
    class Test1 implements Runnable{
 
        @Override
        public void run() {
            getId();
 
        }
 
    }
 
    public void getId(){
        synchronized (this) {
            RedisAtomicLong entityIdCounter = null;
 
            for(int i=0;i<10;i++){
                if(!redisTemplate.hasKey("ceid")){
                    redisTemplate.opsForValue().increment("ceid", 1);
                    System.out.println("test1使用redis缓存保存数据成功");
                    entityIdCounter= new RedisAtomicLong("ceid", redisTemplate.getConnectionFactory());
                    //incr 默认初始值从0开始,
                    //可以设置初始值,
                    entityIdCounter.set(123);
                }
                entityIdCounter=new RedisAtomicLong("ceid", redisTemplate.getConnectionFactory());
                long increment=0;
 
                increment = entityIdCounter.incrementAndGet();
                if (i == 5) {
                    increment = entityIdCounter.decrementAndGet();
                    System.out.println("test1:失败,返回上个id");
                }else{
                    System.out.println(increment);
                }
            }
 
        }
    }
 
}

redis配置在application.properties中

# REDIS
# Redis数据库索引(默认为0)
spring.redis.database=0  
# Redis服务器地址 (默认为127.0.0.1)
spring.redis.host=127.0.0.1
# Redis服务器连接端口 (默认为6379)
spring.redis.port=6379  
# Redis服务器连接密码(默认为空)
spring.redis.password=  
# 连接超时时间(毫秒)
spring.redis.timeout=2000ms

springboot redis自增编号控制 踩坑

近段期间,公司 接手一个订单号生成服务,规则的话已经由项目经理他们规定好了,主要是后面的四位数代表的关于当前订单号已经执行第几个了。而这里面有一个要求就是支持分布式。

为了实现这个东西,刚开始我使用了redis的incr来解决这个问题,因为我们后端开发用的是Spring boot,所以我网上找了一个代码如下:


    public Long incr(String key, long liveTime) {
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();

        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }

        return increment;
    }

结果测试的时候,看着后面的数很满意,心里面有点小小的激动哦~~

但是当我将数据从小到大排序的时候,发现了一点异样,即刚开始的几个是存在问题的。

所以通过测试发现了,当redis里面还没有设置计时器的一刹那,分布式服务下,会存在前几个重复的现象。

发现这个问题之后,于是我通过redis锁,当判断redis下面还没存在计数key的情况下,锁住,然后在锁住的情况下,其他人进来调用的时候,线程睡眠500ms,然后再往下执行。顺利解决~~~

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯