开发者

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

开发者 https://www.devze.com 2022-11-28 14:43 出处:网络 作者: 有点儿困
目录使用redis的incr创建分布式自增idspringbootredis自增编号控制踩坑使用redis的incr创建分布式自增id测试使用springboot加载类测试,使用本地redis,...
目录
  • 使用Redis的incr创建分布式自增id
  • springboot redis自增编号控制 踩坑

使用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());
    Threa编程d 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 = entityIdCount开发者_JS学习er.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.hos编程t=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();

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

        return increment;
    }

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

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

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

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

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

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

0

精彩评论

暂无评论...
验证码 换一张
取 消