参考:https://www.jianshu.com/p/118fceb2194a

 

项目应用场景,考虑到会短时间内插入大量的流水数据进库数据,所以先保存在redis中,然后执行定时器5分钟获取redis的当前数据,进行批量插入。可能需求上 的统计的时间比5分钟还短,不确定上一次是否执行完毕,所以加个锁。

 

springBoot 参考版本: 2.3.7.RELEASE

        
        <!-- redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson-spring-boot-starter</artifactId>
            <version>3.13.6</version>
        </dependency>            

 config:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
public class MyRedissonConfig {

    @Autowired
    private RedisProperties redisProperties;

    @Bean(destroyMethod="shutdown")
    RedissonClient redissonClient() throws IOException {
        //1、创建配置
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://"+redisProperties.getHost()+":"+redisProperties.getPort());//要早yml配置文件中配置好  spring:redis
        return Redisson.create(config);
    }

}

  Test文件 : 在执行run1 方法的时候,再执行run2方法,就会发现 run2方法一直停留在获取锁的状态下,直到run1方法释放锁,run2方法才会接着执行

import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Test;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Log4j2
@SpringBootTest
public class MyLockTest {

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private final static String REDIS_KEY = "test_lock_list";

    @Test
    public void addRedisData(){
        for (int i = 0; i < 100; i++) {
            stringRedisTemplate.opsForList().rightPush(REDIS_KEY,i+"");
        }
    }

    @Test
    public void runTest1(){
        System.out.println("_____________________________执行run1");
        testLock();
    }

    @Test
    public void runTest2(){
        System.out.println("_____________________________执行run2");
        testLock();
    }

    public void testLock(){
        if(redissonClient==null){
            System.out.println("redissonClient 空");
            return;
        }
        RLock testLock = redissonClient.getLock("testLock");
        testLock.lock(60, TimeUnit.SECONDS);
        System.out.println("正在获取锁:"+System.currentTimeMillis());
        testLock.lock();
        System.out.println("获取锁成功:"+System.currentTimeMillis());
        try{
            List<String> list = stringRedisTemplate.opsForList().range(REDIS_KEY,0,50);
            /**
             * 进行一堆逻辑 , 假设这些逻辑的处理时间非常耗时,需要20S
             */
            Thread.sleep(20000);
            list.forEach(t->{
                System.out.println(t);
            });
            stringRedisTemplate.opsForList().trim(REDIS_KEY,list.size(),-1);
        }catch (Exception e){

        }finally {
            System.out.println("释放锁");
            testLock.unlock();
        }
    }


}