1、什么是分布式锁:
分布式锁,即分布式系统中的锁。在单体应用中我们通过锁解决的是控制共享资源访问的问题,而分布式锁,就是解决了分布式系统中控制共享资源访问的问题。与单体应用不同的是,分布式系统中竞争共享资源的最小粒度从线程升级成了进程。
2、分布式锁应该具备哪些条件:
- 在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
- 高可用的获取锁与释放锁
- 高性能的获取锁与释放锁
- 具备可重入特性(可理解为重新进入,由多于一个任务并发使用,而不必担心数据错误)
- 具备锁失效机制,即自动解锁,防止死锁
- 具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
3、分布式锁的实现方式:
- 基于数据库实现分布式锁
- 基于Zookeeper实现分布式锁
- 基于reids实现分布式锁
下面是基于Redis实现的分布式锁,代码实例直接用就好了!
<?php
namespace App\Support;
use Hyperf\Redis\Redis;
class RedisDistributedLock
{
/**
* @var Redis
*/
private Redis $redis;
/**
* 锁的名称
* @var string
*/
private string $lockKey;
/**
* 锁的超时时间,单位:毫秒
* @var int
*/
private int $lockTimeout;
/**
* 加锁成功后的锁值,用于释放锁
* @var string
*/
private string $lockValue;
/**
* @param Redis $redis
* @param string $lockKey
* @param int $lockTimeout
*/
public function __construct(Redis $redis, string $lockKey, int $lockTimeout)
{
$this->redis = $redis;
$this->lockKey = $lockKey;
$this->lockTimeout = $lockTimeout;
}
/**
* 获取锁
* @return bool
*/
public function lock(): bool
{
// 获取锁的值
$this->lockValue = uniqid();
// 尝试获取锁
$isLocked = $this->redis->set($this->lockKey, $this->lockValue, ['NX', 'PX' => $this->lockTimeout]);
return (bool)$isLocked;
}
/**
* 释放锁
* @return void
*/
public function release(): void
{
$script = <<<LUA
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
LUA;
$this->redis->eval($script, [$this->lockKey, $this->lockValue], 1);
}
}
如何使用
use App\Model\DistributedLock;
$redis = new Redis(...);
$lock = new DistributedLock($redis, 'lock_key', 10000);
if ($lock->lock()) {
try {
// 执行临界区代码
} finally {
$lock->release();
}
} else {
// 获取锁失败
}
部分参考自:Redis进阶应用:Redis+Lua脚本实现复合操作_cengnai6732的博客-CSDN博客