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

 更新时间:2022年11月19日 14:24:01   作者:有点儿困  
这篇文章主要介绍了springboot如何使用redis的incr创建分布式自增id,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

使用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,所以我网上找了一个代码如下:

/**
     *
     * @param key
     * @param liveTime
     * @return
     */
    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,然后再往下执行。顺利解决~~~

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java使用反射访问成员变量的值示例

    java使用反射访问成员变量的值示例

    这篇文章主要介绍了java使用反射访问成员变量的值,结合实例形式分析了java基于反射机制操作类成员变量相关实现技巧,需要的朋友可以参考下
    2019-07-07
  • 如何搭建一个完整的Java开发环境

    如何搭建一个完整的Java开发环境

    这篇文章主要教大家如何搭建一个完整的Java开发环境,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Mybatis中的高级映射一对一、一对多、多对多

    Mybatis中的高级映射一对一、一对多、多对多

    这篇文章主要介绍了Mybatis中的高级映射一对一、一对多、多对多的相关资料,需要的朋友可以参考下
    2016-08-08
  • Java GUI实现多个窗口切换效果

    Java GUI实现多个窗口切换效果

    这篇文章主要为大家详细介绍了Java GUI实现多个窗口的切换效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • java语言实现权重随机算法完整实例

    java语言实现权重随机算法完整实例

    这篇文章主要介绍了java语言实现权重随机算法完整实例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-11-11
  • Spring从@Aspect到Advisor使用演示实例

    Spring从@Aspect到Advisor使用演示实例

    这篇文章主要介绍了Spring从@Aspect到Advisor使用演示实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-02-02
  • eclipse创建多层包(多级包)全过程

    eclipse创建多层包(多级包)全过程

    这篇文章主要介绍了eclipse创建多层包(多级包)全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Java引用传递和值传递栈内存与堆内存的指向操作

    Java引用传递和值传递栈内存与堆内存的指向操作

    这篇文章主要介绍了Java引用传递和值传递栈内存与堆内存的指向操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Spring扩展接口知识总结

    Spring扩展接口知识总结

    今天带大家学习Java Spring的相关知识,文中对Spring扩展接口作了非常详细的介绍及代码示例,对正在学习java的小伙伴们有很好地帮助,需要的朋友可以参考下
    2021-05-05
  • Java ServletContext对象用法解析

    Java ServletContext对象用法解析

    这篇文章主要介绍了Java ServletContext对象用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05

最新评论