Redis 在 PHP 中并发锁的使用说明


一、核心概念

Redis 并发锁是利用 Redis 的原子性命令(如 SETNXSET 带参数)实现的分布式锁,用于解决 PHP 多进程 / 多服务环境下的资源竞争问题(如库存扣减、订单重复提交),确保同一时间只有一个进程能操作共享资源。

二、关键特性与实现原则

  1. 原子性:锁的 “获取” 和 “设置过期时间” 需一步完成,避免进程崩溃导致死锁。
  2. 过期自动释放:为锁设置合理过期时间,防止持锁进程异常时锁无法释放。
  3. 唯一标识:用随机字符串(如 uniqid() 生成)作为锁的值,确保进程只能释放自己持有的锁。
  4. 非阻塞(可选):获取锁失败时可直接返回,避免进程阻塞等待。

三、PHP 实现实例

<?php

namespace common\library\traits\redis;

trait LockTrait
{
    protected $lockKey; // 锁key

    /**
     * 加锁
     *
     * @param mixed $key
     */
    public function lock($key, int $expireIn = 5, int $wait = 0): bool
    {
        $this->lockKey = $key;

        do {
            $lock = $this->setNx($key, time(), $expireIn);
            if ($lock) {
                return true;
            }
            if ($wait > 0) {
                sleep(1);
            }
        } while ($wait--); // 防止偶尔性的获取锁失败的情况

        // 无法正常获取锁 不允许往下进行
        return false;
    }

    /**
     * 释放锁
     */
    public function unlock(): bool
    {
        return $this->delete($this->lockKey);
    }
}

四、注意事项

  1. 过期时间设置:需根据业务实际执行时间调整(如业务需 3 秒,过期时间设 5 秒),过短可能导致锁提前释放,过长可能增加死锁风险。
  2. Redis 可用性:若 Redis 单点故障,会导致锁失效,生产环境建议用 Redis 集群(主从 + 哨兵)保证高可用。
  3. 阻塞需求处理:若需要 “获取锁失败后等待重试”,可在 acquire() 方法中添加循环(如循环 3 次,每次间隔 100ms),避免频繁请求 Redis。
  4. 业务幂等性:即使使用锁,仍需保证业务接口的幂等性(如订单提交时校验订单号是否已存在),防止极端情况下的重复操作。
发布时间 : 2025-09-04,阅读量:1
本文链接:https://upwqy.com/details/989.html
PHP 数组:从基础到实战的全面总结 vue3 中使用nprogress