Redis实现分布式锁机制

Redis实现分布式锁思路
  常用的是redis函数是setnx(),这个应该是实现分布式锁最主要的函数。首先是将某一业务标识名作为键存到redis里,并为其设个过期时间,如果是还有加锁请求过来,先是通过setnx()看看是否能将锁的标识插入到redis里,可以的话就返回true,不可以就返回false。
  
一、使用Lua脚本简单的实现Redis锁的实现 :

public class DistributeLocker {
     

    private Jedis jedis;

    private Lock lock;
	/**
	 * 加锁成功标识
	 */
    private static final String LOCK_SUCCESS = "1";
	/**
	 * 脚本入参个数
	 */
    private static final int KEY_COUNT = 1;
	/**
	 * 加锁脚本
	 */
    private static String LOCK_SCRIPT;
	/**
	 * 解锁脚本
	 */
    private static String RELEASE_SCRIPT;
	/**
	 * 初始化脚本
	 */
    static {
     
        LOCK_SCRIPT = "local key = redis.call('get',KEYS[1]) if ('1' == key) then return 0 "
                + "else redis.call('set',KEYS[1],'1') redis.call('expire',KEYS[1],ARGV[1]) return 1 end";
        RELEASE_SCRIPT = "if (redis.call('exists',KEYS[1])) then redis.call('del',KEYS[1]) end";
    }
    /**
	 * 定义带参构造函数
	 */
    public DistributeLocker (Lock lock) {
      }
    public void lock (final String key, final int exprieTime) {
     
    	try {
     
	        if (LOCK_SUCCESS.equals(jedis.eval(LOCK_SCRIPT, KEY_COUNT, key, String.valueOf(exprieTime)))) {
     
	            lock.success();
	        } else {
     
	            lock.failure();
	        }
        } finally {
     
        	releaseLock(key);
        }
    }
	
	/**
	 * 解锁逻辑
	 */
    public void releaseLock (String key) {
     
        jedis.eval(RELEASE_SCRIPT, KEY_COUNT, key);
    }
}


public interface Lock {
     

    void success();

    void failure();
}
public class Test {
     

    void purchase(String key, int secondTime){
     
        new DistributeLocker(new Lock() {
     
            @Override
            public void success() {
     
                // do something
            }

            @Override
            public void failure() {
     
                // do something
            }
        }).lock(key,secondTime);
    }
}

注:Redis分布式锁的实现方式有很多种,各有利弊,加锁的时候主要注意检查锁与加锁操作要有原子性,防止重复加锁成功。过期时间主要是为了防止未释放锁导致锁的一直存在,从而无法获取锁操作。

二、使用Redisson框架

  • 官网
    https://github.com/redisson/redisson/wiki/Table-of-Content

  • 依赖

<dependency>
    <groupId>org.redissongroupId>
    <artifactId>redisson-spring-boot-starterartifactId>
    <version>3.13.0version>
dependency>
  • 使用缺省配置

  • 工具类

@Slf4j
@Component
public class DistributeLocker {
     

    private RedissonClient redissonClient;

    public DistributeLocker(RedissonClient redissonClient) {
     
        this.redissonClient = redissonClient;
    }

    public void lock (String key, long exprieTime, LockTask task) {
     
        lock(0L, key, exprieTime, task);
    }

    public void lock (long waitTime, String key, long exprieTime, LockTask task) {
     
        RLock rLock = redissonClient.getLock(key);
        try {
     
            if (rLock.tryLock(waitTime, exprieTime, TimeUnit.MILLISECONDS)) {
     
                task.success();
            } else {
     
                task.failure();
            }
        } catch (Exception e) {
     
            log.error("DistributeLocker.lock Error. key:{}, e:{}", key, e);
        } finally {
     
            rLock.unlock();
        }
    }

}

  • 使用
@SpringBootApplication
@EnableDiscoveryClient
public class StartUpApplication {
     

    public static void main(String[] args) {
     
        ConfigurableApplicationContext context = SpringApplication.run(StartUpApplication.class, args);
        DistributeLocker locker = context.getBean(DistributeLocker.class);
        locker.lock("test", 100L, new LockTask() {
     
            @Override
            public void success() {
     
                System.out.println("加锁成功");
            }

            @Override
            public void failure() {
     
                System.out.println("加锁失败");
            }
        });
    }
}

你可能感兴趣的:(Redis,Redis,Java,分布式锁,Lua)