参考: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(); } } }