redis 分布式锁的实现(带续命 *** 作)

redis 分布式锁的实现(带续命 *** 作),第1张

1.pom配置 添加依赖

4.0.0
 
        org.springframework.boot
        spring-boot-starter-parent
        2.6.7
         
    
    com.sun
    redis
    0.0.1-SNAPSHOT
    redis
    
        1.8
    
    
        
            org.springframework.boot
            spring-boot-starter-web
        

       
            org.projectlombok
            lombok
            1.18.22
            provided
       

       
       
            org.springframework.boot
            spring-boot-starter-data-redis
            2.6.7
       

   

2.编写redisTemplate 配置类

@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate();
        // 配置连接工厂
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jacksonSerial =new  Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

        jacksonSerial.setObjectMapper(om);

        // 值采用json序列化
        template.setValueSerializer(jacksonSerial);
        //使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());

        // 设置hash key 和value序列化模式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSerial);
        template.afterPropertiesSet();

        return template;
    }
}

3.添加yml配置

spring:
  redis:
    host: 192.168.113.129
    port: 6379
    timeout: 3000
    pool:
      max-wait: 30000
      max-active: 100
      max-idle: 20
      min-idle: 0

4.分布式锁的实现

@Service
@Slf4j
public class RedisLock {

    @Autowired
    private RedisTemplate redisTemplate;

    private ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 10, 10,
            TimeUnit.SECONDS, new LinkedBlockingDeque<>(100));
/**
 * 加锁
 *
 * @param key
 * @param userId
 * @param timeOut
 * @return
 */
public boolean lock(String key, String userId, long timeOut) {
    boolean success = redisTemplate.opsForValue().setIfAbsent(key, userId, timeOut, TimeUnit.SECONDS);
    if (!success) {
        log.error("key:{},userId:{}  get lock failer ", key, userId);
        return false;
    }
    try {
        renewExpiration(key,userId, timeOut);
        Thread.sleep(20000);
        return true;
    } catch (Exception e) {
        log.error("lock occur error:{}", e);
        return false;
    } finally {
        releaseLock(key, userId);
    }
}

/**
 * 续命 *** 作
 *
 * @param key
 * @param timeOut
 */
private void renewExpiration(String key,String userId, long timeOut) {
    threadPool.execute(() -> {
        Long currentTimeMills = System.currentTimeMillis();
        System.out.println("开始:" + LocalDateTime.now() + " ,timeOut:" + timeOut);
        while (true) {
            if (redisTemplate.hasKey(key) &&   userId.equals(redisTemplate.opsForValue().get(key))) {
                Long cost = System.currentTimeMillis() - currentTimeMills;
                if (cost > timeOut * 1000 / 2) {
                    currentTimeMills = System.currentTimeMillis();
                    redisTemplate.expire(key, timeOut, TimeUnit.SECONDS);
                    System.out.println("进行中:" + LocalDateTime.now() + " ,timeOut:" + timeOut);
                }
            } else {
                break;
            }
        }
    });
}

    /**
     * 释放锁
     *
     * @param key
     * @param userId
     */
    private void releaseLock(String key, String userId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        DefaultRedisScript redisScript = new DefaultRedisScript(script, Long.class);
        Long result2 = redisTemplate.execute(redisScript, Arrays.asList(key), userId);
        System.out.println("result2=" + result2);
    }

}

结果:

2022-04-25 00:41:15.089  INFO 16644 --- [nio-6012-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms
开始:2022-04-25T00:41:16.361 ,timeOut:10
进行中:2022-04-25T00:41:21.358 ,timeOut:10
进行中:2022-04-25T00:41:26.364 ,timeOut:10
进行中:2022-04-25T00:41:31.362 ,timeOut:10
进行中:2022-04-25T00:41:36.363 ,timeOut:10
result2=1

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/734120.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-27
下一篇 2022-04-27

发表评论

登录后才能评论

评论列表(0条)

保存