您的当前位置:首页>全部文章>文章详情

php Redis锁

发表于:2025-05-10 09:45:38浏览:8次TAG: #PHP #redis

Redis作用

Redis 锁主要用于解决分布式系统中的并发控制问题,确保多个进程或线程在共享资源时的互斥访问。以下是其核心作用和应用场景:

1. 分布式互斥锁

在分布式系统中,多个服务实例可能同时访问同一资源(如库存扣减、订单创建),Redis 锁可确保同一时间只有一个客户端执行关键代码段。
示例场景:电商系统的库存扣减

  • 多个用户同时购买同一商品时,使用 Redis 锁保证库存数据的一致性,避免超卖。
2. 防止竞态条件

当多个操作需要按顺序执行时,Redis 锁可避免竞态条件。
示例场景:缓存失效时的数据库查询

  • 当缓存过期时,多个请求可能同时查询数据库并重建缓存。使用 Redis 锁确保只有一个请求执行数据库查询,其他请求等待结果,减少数据库压力。
3. 任务幂等性保障

确保同一任务不会被重复执行。
示例场景:定时任务去重
分布式定时任务可能在多个节点同时触发,使用 Redis 锁保证任务只在一个节点执行。

4. 资源访问控制

限制对有限资源的并发访问数量。

示例场景:连接池限制
  • 当连接池资源不足时,使用 Redis 锁控制获取连接的权限,避免资源耗尽。

调用

// 使用示例
$param1 = '参数1';
$param2 = '参数2';
$redisLock = new RedisLock();
$result = $redisLock->run(function()use($param1,$param2){
    // TODO 执行你的业务操作
    dump($param1,$param2);
},'my_distributed_lock');
if ($result) {
    dump($result);
}
else {
    dump($redisLock->getError());
}

<?php
namespace app\common\utils;
/**
 * Redis锁
 * 1、安装redis以及redis扩展
 */
class RedisLock
{
    private $redis;
    private $error = null;

    /**
     * 初始化
     * @param $redisHost
     * @param $redisPort
     */
    public function __construct($redisHost = '127.0.0.1', $redisPort = 6379)
    {
        try {
            $this->redis = new \Redis();
            $this->redis->connect($redisHost, $redisPort);
        } catch (\Exception $e) {
            $this->setError("无法连接到 Redis 服务器: " . $e->getMessage());
        }
    }

    /**
     * 入口
     * @param callable $callback
     * @param $lockKey
     * @param $expireTime
     * @return false|mixed|null
     */
    public function run(callable $callback,$lockKey,$expireTime = 10)
    {
        if ($this->acquireLock($lockKey,$expireTime)) {
            $result = is_callable($callback) ? call_user_func_array($callback, []) : null;
            $this->releaseLock($lockKey);
            return $result;
        }
        else {
            return $this->setError($this->getError()?:'您的操作过于频繁,请稍后再试');
        }
    }
    /**
     * 上锁
     * @return bool|\Redis|string
     */
    private function acquireLock($lockKey,$expireTime)
    {
        if ($this->getError()) {
            return false;
        }
        try {
            return $this->redis->set($lockKey, 1, ['NX', 'EX' => $expireTime]);
        } catch (\Exception $e) {
            return $this->setError("获取锁时发生 Redis 错误: " . $e->getMessage());
        }
    }

    /**
     * 释放锁
     * @return false|int|\Redis
     */
    private function releaseLock($lockKey)
    {
        if ($this->getError()) {
            return false;
        }
        try {
            return $this->redis->del($lockKey);
        } catch (\Exception $e) {
            return $this->setError("释放锁时发生 Redis 错误: " . $e->getMessage());
        }
    }
    /**
     * 获取异常
     * @return null
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * 设置异常
     * @param $message
     * @return false
     */
    private function setError($message)
    {
        $this->error = $message;
        return false;
    }
}