栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

RedisLock锁使用记录

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

RedisLock锁使用记录

1.RedisLock锁使用代码片段

@Autowired
    RedisLockHelper redisLock;
// 可以自定锁键
String lockKey =   "simCard:"+tPhoneCardApply.getPhoneNum();
                    long timeMillis = System.currentTimeMillis();
                    // 定义锁多长时间
                    String timeStamp = String.valueOf(timeMillis + 60 * 5 * 1000);
                    boolean lock = redisLock.lock(lockKey,timeStamp);
                    try{
                        if(lock){
								......需要执行的代码
							}
					}finally {
                        try {
                            redisLock.unlock(lockKey, timeStamp);
                        } catch (Exception e) {
                            e.printStackTrace();
                            logger.error("释放分布式锁失败! ", e);
                        }
                    }

  1. 代码片段中使用到的redisLock类
package com.huatek.frame.core.context;

import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;


@Component
@Slf4j
public class RedisLockHelper {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    
    public boolean lock(String targetId,String timeStamp){
        if(stringRedisTemplate.opsForValue().setIfAbsent(targetId,timeStamp)){
            // 对应setnx命令,可以成功设置,也就是key不存在
            return true;
        }

        // 判断锁超时 - 防止原来的操作异常,没有运行解锁操作  防止死锁
        String currentLock = stringRedisTemplate.opsForValue().get(targetId);
        // 如果锁过期 currentLock不为空且小于当前时间
        if(!StringUtil.isNullOrEmpty(currentLock) && Long.parseLong(currentLock) < System.currentTimeMillis()){
            // 获取上一个锁的时间value 对应getset,如果lock存在
            String preLock =stringRedisTemplate.opsForValue().getAndSet(targetId,timeStamp);

            // 假设两个线程同时进来这里,因为key被占用了,而且锁过期了。获取的值currentLock=A(get取的旧的值肯定是一样的),两个线程的timeStamp都是B,key都是K.锁时间已经过期了。
            // 而这里面的getAndSet一次只会一个执行,也就是一个执行之后,上一个的timeStamp已经变成了B。只有一个线程获取的上一个值会是A,另一个线程拿到的值是B。
            if(!StringUtil.isNullOrEmpty(preLock) && preLock.equals(currentLock) ){
                // preLock不为空且preLock等于currentLock,也就是校验是不是上个对应的商品时间戳,也是防止并发
                return true;
            }
        }
        return false;
    }
    
    public void unlock(String target,String timeStamp){
        try {
            String currentValue = stringRedisTemplate.opsForValue().get(target);
            if(!StringUtil.isNullOrEmpty(currentValue) && currentValue.equals(timeStamp) ){
                // 删除锁状态
                stringRedisTemplate.opsForValue().getOperations().delete(target);
            }
        } catch (Exception e) {
            log.error("警报!警报!警报!解锁异常{}",e);
        }
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/490732.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号