您的位置:首页 > 科技 > IT业 > 《知识点扫盲 · Redis 分布式锁》

《知识点扫盲 · Redis 分布式锁》

2024/12/23 8:37:34 来源:https://blog.csdn.net/syb513812/article/details/141038770  浏览:    关键词:《知识点扫盲 · Redis 分布式锁》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

文章目录

    • CSDN.gif
    • 技术简介
    • 示例说明
    • 总结陈词

CSDN.gif

技术简介

Redis 分布式锁是一种利用 Redis 的特性来实现的分布式锁机制,主要用于解决在分布式系统中多个实例对共享资源的并发访问问题。通过使用 Redis 作为锁的存储介质,可以确保在多个服务实例之间的互斥访问。
Redis 分布式锁的基本原理:

  • 加锁:通过 SETNX 命令,尝试设置一个锁的键。如果设置成功,表示获得锁;如果失败,表示锁已经被其他实例持有。
  • 设置过期时间:为了防止死锁,通常在加锁时会设置一个过期时间,确保即使持锁的实例崩溃,锁也会在一定时间后自动释放。
  • 解锁:在完成对共享资源的操作后,释放锁。解锁时需要确保只有持有锁的实例才能解锁,通常通过比较锁的值来实现。

Redis 分布式锁的注意事项:

  1. 锁过期时间: 设置合理的锁过期时间,避免死锁。
  2. 释放: 确保在使用完锁后及时释放锁,避免资源浪费。
  3. 重入锁: 如果需要同一个线程多次获取锁,可以使用可重入锁。
  4. 公平锁: 如果需要按照请求顺序分配锁,可以使用公平锁
  5. 锁竞争: 在高并发场景下,可能会出现锁竞争,需要考虑如何处理锁竞争。

示例说明

编写工具类 RedisLockUtil,代码如下:

public class RedisLockUtil {public static final String LOCK_KEY_PREFIX = "lock:";private static final String UNLOCK_LUA_SCRIPT = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";private static final RedisScript<Long> UNLOCK_REDIS_SCRIPT = new DefaultRedisScript<>(UNLOCK_LUA_SCRIPT, Long.class);/*** 尝试Redis锁** @param lockKey  锁名称* @param lockId   锁持有者唯一ID* @param duration 过期时间(过期自动释放锁)* @param timeUnit 时间单位* @return true: 获取锁成功 , false: 获取锁失败*/public static boolean tryLock(@NonNull String lockKey, @NonNull String lockId, long duration, @NonNull TimeUnit timeUnit) {return RedisUtil.setIfAbsent(LOCK_KEY_PREFIX.concat(lockKey), lockId, duration, timeUnit);}/*** 释放Redis锁** @param lockKey 锁名称* @param lockId  锁持有者唯一ID*/public static boolean unlock(@NonNull String lockKey, @NonNull String lockId) {Object result = RedisUtil.getRedisTemplate().execute(UNLOCK_REDIS_SCRIPT, Collections.singletonList(LOCK_KEY_PREFIX.concat(lockKey)), lockId);return Long.valueOf(1).equals(result);}
}

核心工具类逻辑:

/*** 仅在Redis中键不存在时设置键的值并设置过期时间。** @param redisKey Redis中的键。* @param value    要设置的值。* @param expire   键的过期时间。* @param timeUnit 过期时间的时间单位。* @return 如果成功设置了键值对,则返回true,否则返回false。*/
public static boolean setIfAbsent(@NonNull String redisKey, Object value, long expire, TimeUnit timeUnit) {return checkBool(getRedisTemplate().opsForValue().setIfAbsent(redisKey, value, expire, timeUnit));
}

使用示例:

    public void doSomething() {// 分布式锁标识,根据该标识进行加锁和解锁String lockKey = "myLockKey";// 随机ID,解锁时用于校验String lockId = UUID.randomUUID().toString();try {// 创建一个60秒后自动过期的锁. 返回true: 获取锁成功,返回false:获取锁失败(开发者自行决定获取锁失败时处理方案)boolean status = RedisLockUtil.tryLock(lockKey, lockId, 60, TimeUnit.SECONDS);// 获取锁失败if (!status) {// 执行获取锁失败的业务处理逻辑throw ApiException.createEx(ExceptionCodeEnum.REDIS_TRY_GET_LOCK_FAILURE, lockKey);}// 执行获取锁成功后的业务逻辑// ...} finally {// 解锁状态,true:解锁成功,false:解锁失败boolean unlockStatus = RedisLockUtil.unlock(lockKey, lockId);if (!unlockStatus) {log.error("[Redis分布式锁] 解锁失败, lockKey={}, lockId={}", lockKey, lockId);}}}

总结陈词

此篇文章介绍了 Redis 分布式的基础应用,仅供学习参考。
Redis 分布式锁是一种简单高效的实现分布式锁的方案,可以有效解决分布式系统中数据冲突问题。选择合适的实现方法,注意相关注意事项,可以确保锁的可靠性和性能。
💗 后续会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

CSDN_END.gif

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com