分布式锁是用来在分布式系统下控制对资源的独占访问,确保多个进程或线程不会同时操作同一资源。Redis 是实现分布式锁的常用工具之一。下面是详细的实现步骤和代码示例:
1. Redis 分布式锁的基本实现
通过设置一个唯一的键来实现锁,当操作完成后删除该键即可释放锁。
1.1 获取锁
使用 SET 命令并设置过期时间。NX 参数表示只有在键不存在时才能设置成功,EX 参数用于设置键的过期时间。
1SET lock_key unique_value NX EX 10 2
1.2 释放锁
只有持有锁的客户端才能删除锁。为了确保这一点,需要在释放锁时进行唯一值验证。
1# Lua脚本原子性地检查唯一值并删除锁 2if redis.call("GET", KEYS[1]) == ARGV[1] then 3 return redis.call("DEL", KEYS[1]) 4else 5 return 0 6end 7
2. Java 实现 Redis 分布式锁
2.1 引入依赖
在 Maven 项目中引入 Jedis 依赖:
1<dependency> 2 <groupId>redis.clients</groupId> 3 <artifactId>jedis</artifactId> 4 <version>3.5.2</version> 5</dependency> 6
2.2 获取锁的方法
1import redis.clients.jedis.Jedis; 2import redis.clients.jedis.params.SetParams; 3 4public class RedisDistributedLock { 5 private Jedis jedis; 6 private String lockKey; 7 private String lockValue; 8 private int expireTime; 9 10 public RedisDistributedLock(Jedis jedis, String lockKey, String lockValue, int expireTime) { 11 this.jedis = jedis; 12 this.lockKey = lockKey; 13 this.lockValue = lockValue; 14 this.expireTime = expireTime; 15 } 16 17 public boolean acquireLock() { 18 SetParams setParams = new SetParams(); 19 setParams.nx().ex(expireTime); 20 // 尝试获取锁 21 String result = jedis.set(lockKey, lockValue, setParams); 22 return "OK".equals(result); 23 } 24 25 public boolean releaseLock() { 26 // 释放锁的 Lua 脚本 27 String luaScript = 28 "if redis.call('GET', KEYS[1]) == ARGV[1] then " + 29 "return redis.call('DEL', KEYS[1]) " + 30 "else " + 31 "return 0 " + 32 "end"; 33 Object result = jedis.eval(luaScript, 1, lockKey, lockValue); 34 return "1".equals(result.toString()); 35 } 36 37 public static void main(String[] args) { 38 // 连接到本地 Redis 服务 39 Jedis jedis = new Jedis("localhost"); 40 41 String lockKey = "distributed_lock"; 42 String lockValue = "unique_value"; 43 int expireTime = 10; // 锁的过期时间,单位为秒 44 45 RedisDistributedLock lock = new RedisDistributedLock(jedis, lockKey, lockValue, expireTime); 46 47 // 获取锁 48 if (lock.acquireLock()) { 49 try { 50 // 执行你的逻辑 51 System.out.println("Lock acquired!"); 52 53 // 模拟业务处理时间 54 Thread.sleep(5000); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } finally { 58 // 释放锁 59 if (lock.releaseLock()) { 60 System.out.println("Lock released!"); 61 } else { 62 System.out.println("Failed to release lock!"); 63 } 64 } 65 } else { 66 System.out.println("Failed to acquire lock!"); 67 } 68 69 jedis.close(); 70 } 71} 72
3. Redisson 提供的分布式锁
Redisson 是一个开源的 Redis 客户端,提供了更高级的分布式锁实现,与 Java 的java.util.concurrent.locks.Lock接口兼容。
3.1 引入依赖
在 Maven 项目中引入 Redisson 依赖:
1<dependency> 2 <groupId>org.redisson</groupId> 3 <artifactId>redisson</artifactId> 4 <version>3.16.5</version> 5</dependency> 6
3.2 使用 Redisson 实现分布式锁
1import org.redisson.Redisson; 2import org.redisson.api.RLock; 3import org.redisson.api.RedissonClient; 4import org.redisson.config.Config; 5 6import java.util.concurrent.TimeUnit; 7 8public class RedissonDistributedLock { 9 public static void main(String[] args) { 10 // 创建 Redisson 配置 11 Config config = new Config(); 12 config.useSingleServer().setAddress("redis://127.0.0.1:6379"); 13 14 // 创建 Redisson 客户端 15 RedissonClient redissonClient = Redisson.create(config); 16 17 // 获取锁对象 18 RLock lock = redissonClient.getLock("distributed_lock"); 19 20 try { 21 // 尝试获取锁,等待时间10秒,持有锁30秒 22 if (lock.tryLock(10, 30, TimeUnit.SECONDS)) { 23 try { 24 // 执行你的逻辑 25 System.out.println("Lock acquired!"); 26 27 // 模拟业务处理时间 28 Thread.sleep(5000); 29 } finally { 30 // 释放锁 31 lock.unlock(); 32 System.out.println("Lock released!"); 33 } 34 } else { 35 System.out.println("Failed to acquire lock!"); 36 } 37 } catch (InterruptedException e) { 38 e.printStackTrace(); 39 } finally { 40 redissonClient.shutdown(); 41 } 42 } 43} 44
总结
通过配置 Redis 和编写合适的代码,可以实现可靠的分布式锁。上述示例展示了如何使用 Jedis 和 Redisson 来实现分布式锁。使用 Jedis 提供了更灵活的低级实现,而 Redisson 提供了更高级别的 API,使得分布式锁的使用更加简单和直观。选择合适的工具和方法取决于具体的应用场景和需求。
《Redis(161)如何使用Redis实现分布式锁?》 是转载文章,点击查看原文。
