redis 分布式锁实现方式

分布式锁

  分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。

分布式锁的实现方式

1、基于数据库的乐观锁实现分布式锁

2、基于zookeeper 临时节点的分布式锁

3、基于redis的分布式锁(常用)

分布式锁的注意事项

1、互斥性:在任意时刻,只有一个客户端能持有锁

2、同一性:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解锁

3、可重入性:即使有一个客户端在持有锁的期间奔溃而没有主动解锁,也能保证后续其他客户端能加锁

 

工具

public class RedisUtils {
    private static int port = 6379;
    private static String host = "127.0.0.1";
    private static JedisPool pool;
    static {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMinIdle(5);

        pool = new JedisPool(config, host, port);
    }

    public static Jedis getJedis() {
        return pool.getResource();
    }

    /**
     * 分布式锁的实现方式
     *  1、基于数据库的乐观锁实现分布式锁
     *  2、基于zookeeper 临时节点的分布式锁
     *  3、基于redis的分布式锁(常用)
     * 分布式锁的注意事项
     *  互斥性:在任意时刻,只有一个客户端能持有锁
     *  同一性:加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解锁
     *  可重入性:即使有一个客户端在持有锁的期间奔溃而没有主动解锁,也能保证后续其他客户端能加锁
     */


    /**
     * 获取分布式锁
     * 方式1
     * 使用redis的set命令实现获取分布式锁
     * @param lockKey
     * @param requestId
     * @param timeout
     * @return
     */
    public static boolean getLock(String lockKey, String requestId, int timeout) {
        // 获取Jedis对象,负责和远程redis服务器进行连接
        Jedis jedis = getJedis();
        // 参数三:NX和XX,
        // 参数sin:EX和PX
        String result = jedis.set(lockKey, requestId, "NX", "EX", timeout);
        if (result == "OK") {
            return true;
        }

        return false;
    }

    /**
     * 方式2
     * 使用 setnx 命令实现
     * @param lockKey
     * @param requestId
     * @param timeout
     * @return
     */
    public static synchronized boolean getLock2(String lockKey, String requestId, int timeout) {
        // 获取Jedis对象,负责和远程redis服务器进行连接
        Jedis jedis = getJedis();

        Long result = jedis.setnx(lockKey, requestId);
        if (result == 1) {
            // 设置有效期
            jedis.expire(lockKey, timeout);
            return true;
        }
        return false;
    }


    /***
     * 释放分布式锁的代码
     * 方式1
     * del命令实现
     * @param lockKey
     * @param requestId
     */
    public static void releaseLock(String lockKey, String requestId) {
        // 获取Jedis对象,负责和远程redis服务器进行连接
        Jedis jedis = getJedis();
        if (requestId.equals(jedis.get(lockKey))) {
            jedis.del(lockKey);
        }
    }

    /**
     * 方式2
     * redis + lua 脚本实现 推荐
     * @param lockKey
     * @param requestId
     * @return
     */
    public boolean releaseLock2(String lockKey, String requestId) {
        Jedis jedis = getJedis();
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
        if (result.equals(1L)) {
            return true;
        }
        return false;
    }

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值