分布式锁的实现

基于Redis的锁

  1. 使用原子的set命令的nx 、ex参数设置过期时间和一个预定的值
  2. 设置成功后,即获取到锁,执行业务操作,否则没有获取到锁
  3. 获取锁的值,并比较预定的值是否和当前值相同,相同则可以删除,否则不能删除

以下代码基于Lua脚本实现

/**
*定义用到的Lua脚本
*/
final String LOCK_SCRIPT_STR = "if redis.call('set',KEYS[1],ARGV[1],'EX',ARGV[2],'NX') then return 1 else return 0 end";
final String UNLOCK_SCRIPT_STR = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

        String uuid=UUID.randomUUID().toString();
        try {
            Object evalsha = jedis.evalsha(jedis.scriptLoad(LOCK_SCRIPT_STR), Arrays.asList("key"), Arrays.asList(uuid, "1000"));
            if("1".equals(evalsha)){
                System.out.println("执行业务逻辑");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            jedis.evalsha(jedis.scriptLoad(UNLOCK_SCRIPT_STR), Arrays.asList("key"), Arrays.asList(uuid));
        }

基于zookeeper的锁

1.客户端在获取锁时,会在一个目录节点下创建一个临时节点,这个临时节点是有序号的,如:/lock/lock-0000000,/lock/lock-0000001
2.客户端获取目录节点下的所有子节点(lock-0000000,lock-0000001...),判断自己创建的节点是否为子节点列表最小的那个子节点
3.如果是,则认为当前客户端获取到锁,否则监听前一个子节点的删除事件
4. 执行业务代码
5.删除自己创建的子节点,并通知后一个监听器

以下是基于Curator实现的分布式锁
//引入maven

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.0.0</version>
</dependency>

实现代码

		try {
			//创建zookeeper的客户端
			RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
			CuratorFramework client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", retryPolicy);
			client.start();
			//创建分布式锁, 锁空间的根节点路径为/curator/lock
			InterProcessMutex mutex = new InterProcessMutex(client, "/curator/lock");
			mutex.acquire();
			//获得了锁, 进行业务流程
			System.out.println("Enter mutex");

		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			//完成业务流程, 释放锁
			mutex.release();
			//关闭客户端
			client.close();
		}    
posted @ 2019-02-26 17:54  Hitechr  阅读(255)  评论(0编辑  收藏  举报