PHP建站技术分享-从入门到精通_各类知识收集PHP建站技术分享-从入门到精通_各类知识收集PHP建站技术分享-从入门到精通_各类知识收集

QQ:420220301 微信/手机:150-3210-7690
当前位置:首页 > 工作总结

php 使用redis锁限制并发访问类示例

管理员 2025-03-06
工作总结
60

在高并发场景下,使用 Redis 实现分布式锁是一种常见的解决方案。Redis 锁可以确保在同一时间只有一个客户端能够执行关键代码段,从而避免资源竞争和数据不一致的问题。

以下是一个使用 Redis 实现分布式锁的 PHP 类示例。


实现功能

  1. 加锁

    • 使用 Redis 的 SET 命令设置一个带有过期时间的锁。

    • 使用 NX 选项确保锁的唯一性。

  2. 解锁

    • 使用 Redis 的 DEL 命令删除锁。

    • 使用 Lua 脚本确保解锁操作的原子性。

  3. 锁续期

    • 在锁过期前,自动延长锁的持有时间。


类实现

php
复制
<?phpclass RedisLock{
    private $redis;
    private $lockKey;
    private $lockValue;
    private $timeout;

    /**
     * 构造函数
     *
     * @param Redis $redis Redis 实例
     * @param string $lockKey 锁的键名
     * @param int $timeout 锁的超时时间(秒)
     */
    public function __construct($redis, $lockKey, $timeout = 10)
    {
        $this->redis = $redis;
        $this->lockKey = $lockKey;
        $this->timeout = $timeout;
        $this->lockValue = uniqid(); // 生成唯一的锁值
    }

    /**
     * 尝试加锁
     *
     * @return bool 是否加锁成功
     */
    public function lock()
    {
        // 使用 SET 命令加锁,NX 选项确保锁的唯一性,EX 选项设置过期时间
        return $this->redis->set($this->lockKey, $this->lockValue, ['NX', 'EX' => $this->timeout]);
    }

    /**
     * 解锁
     *
     * @return bool 是否解锁成功
     */
    public function unlock()
    {
        // 使用 Lua 脚本确保解锁操作的原子性
        $luaScript = "
            if redis.call('get', KEYS[1]) == ARGV[1] then
                return redis.call('del', KEYS[1])
            else
                return 0
            end
        ";

        return $this->redis->eval($luaScript, [$this->lockKey, $this->lockValue], 1);
    }

    /**
     * 锁续期
     *
     * @param int $additionalTime 续期时间(秒)
     * @return bool 是否续期成功
     */
    public function renew($additionalTime)
    {
        // 使用 Lua 脚本确保续期操作的原子性
        $luaScript = "
            if redis.call('get', KEYS[1]) == ARGV[1] then
                return redis.call('expire', KEYS[1], ARGV[2])
            else
                return 0
            end
        ";

        return $this->redis->eval($luaScript, [$this->lockKey, $this->lockValue, $additionalTime], 1);
    }}// 示例用法$redis = new Redis();$redis->connect('127.0.0.1', 6379);$lockKey = 'my_resource_lock';$lock = new RedisLock($redis, $lockKey, 10);// 尝试加锁if ($lock->lock()) {
    echo "加锁成功,执行业务逻辑...\n";

    // 模拟业务逻辑执行时间
    sleep(5);

    // 锁续期
    if ($lock->renew(10)) {
        echo "锁续期成功,继续执行业务逻辑...\n";
    }

    // 解锁
    if ($lock->unlock()) {
        echo "解锁成功,释放资源...\n";
    }} else {
    echo "加锁失败,资源已被占用...\n";}?>

代码说明

  1. 加锁

    • 使用 SET 命令的 NX 选项确保锁的唯一性。

    • 使用 EX 选项设置锁的过期时间,防止死锁。

  2. 解锁

    • 使用 Lua 脚本确保解锁操作的原子性,避免误删其他客户端的锁。

  3. 锁续期

    • 使用 Lua 脚本确保续期操作的原子性,避免在续期时锁已被其他客户端获取。

  4. 唯一锁值

    • 使用 uniqid() 生成唯一的锁值,确保每个客户端持有不同的锁。


示例输出

plaintext
复制
加锁成功,执行业务逻辑...
锁续期成功,继续执行业务逻辑...
解锁成功,释放资源...

注意事项

  1. Redis 连接

    • 确保 Redis 连接正常,并处理连接失败的情况。

  2. 锁过期时间

    • 设置合理的锁过期时间,避免锁过早释放或长时间占用。

  3. 锁续期

    • 在业务逻辑执行时间较长时,使用锁续期功能避免锁过期。

  4. 原子性操作

    • 使用 Lua 脚本确保解锁和续期操作的原子性。


扩展功能

  1. 阻塞锁

    php
    复制
    public function blockLock($retryInterval = 100, $maxRetries = 10){
        $retries = 0;
        while ($retries < $maxRetries) {
            if ($this->lock()) {
                return true;
            }
            usleep($retryInterval * 1000); // 毫秒转微秒
            $retries++;
        }
        return false;}
    • 实现一个阻塞锁,在加锁失败时等待一段时间后重试。

  2. 锁的可重入性

    php
    复制
    private $lockCount = 0;public function reentrantLock(){
        if ($this->lockCount > 0) {
            $this->lockCount++;
            return true;
        }
    
        if ($this->lock()) {
            $this->lockCount++;
            return true;
        }
    
        return false;}public function reentrantUnlock(){
        if ($this->lockCount > 1) {
            $this->lockCount--;
            return true;
        }
    
        if ($this->unlock()) {
            $this->lockCount--;
            return true;
        }
    
        return false;}
    • 支持同一个客户端多次加锁(可重入锁)。


总结

通过 Redis 实现分布式锁可以有效解决高并发场景下的资源竞争问题。以上示例提供了一个简单而强大的 PHP 类,支持加锁、解锁和锁续期功能。根据实际需求,可以进一步扩展和优化代码。



本文关键词: php 使用 redis 限制 并发 访问

希望以上内容对你有所帮助!如果还有其他问题,请随时提问。 各类知识收集 拥有多年CMS企业建站经验,对 iCMS, LeCMS, ClassCMS, Fastadmin, PbootCMS, PHPCMS, 易优CMS, YzmCMS, 讯睿CMS, 极致CMS, Wordpress, HkCMS, YznCMS, WellCMS, ThinkCMF, 等各类cms的相互转化,程序开发,网站制作,bug修复,程序杀毒,插件定制都可以提供最佳解决方案。

相关推荐

扫码关注

qrcode

QQ交谈

回顶部