spring boot 二十 redis 分布式 锁

本文深入探讨了在高并发场景下,如何利用Redis实现分布式锁来保障数据一致性。通过具体代码示例,展示了如何使用set命令的NX和PX选项进行锁的获取,并通过Lua脚本确保解锁操作的原子性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分布式锁 要解决的问题就是高并发时导致的数据重复读取。

为了保证数据的 一致性,在单服务中我们使用 synchronize 在分布式服务中,这个显然是不行的,为了解决这个问题,我们一般使用 Redis的分布式锁 或 ZooKeeper的分布式锁。
直接上代码:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>
public class RedisUtils {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 尝试获取分布式锁
     *
     * @param jedis       Jedis对象
     * @param lockKey    锁key
     * @param requestId  用来标识 谁加的锁。解锁的时候也需要传过去
     * @param expireTime 过期期时间
     * @return 是否获取成功
     */
    public static synchronized boolean lock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }


    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 解锁 通过 lua 执行可以保证原子性,确保判断  解锁 的中间时候,锁过期,导致误解别人锁的情况。
     *
     * @param jedis     Jedis对象
     * @param lockKey   锁key
     * @param requestId 用来标识 谁加的锁
     * @return 是否释放成功
     */
    public static boolean unLock(Jedis jedis, String lockKey, String requestId) {

        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 (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值