当前位置:首页 > PHP

php实现redis锁

2026-02-16 03:29:12PHP

PHP 实现 Redis 锁的方法

使用 SETNX 命令实现基本锁

在 PHP 中可以通过 Redis 的 SETNX 命令实现简单的分布式锁。SETNX 是 "SET if Not eXists" 的缩写,只有当键不存在时才会设置值。

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$lockKey = 'resource_lock';
$lockExpire = 10; // 锁过期时间(秒)

// 尝试获取锁
$isLocked = $redis->setnx($lockKey, time() + $lockExpire);

if (!$isLocked) {
    // 检查锁是否过期
    $lockTime = $redis->get($lockKey);
    if (time() > $lockTime) {
        // 锁已过期,删除并重新获取
        $redis->del($lockKey);
        $isLocked = $redis->setnx($lockKey, time() + $lockExpire);
    }
}

if ($isLocked) {
    try {
        // 执行业务代码
    } finally {
        // 释放锁
        $redis->del($lockKey);
    }
} else {
    // 获取锁失败
}

使用 SET 命令带选项实现更安全的锁

Redis 2.6.12 之后,SET 命令支持更多选项,可以实现更安全的锁机制:

php实现redis锁

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$lockKey = 'resource_lock';
$lockExpire = 10; // 锁过期时间(秒)
$lockToken = uniqid(); // 唯一标识符

// 尝试获取锁
$isLocked = $redis->set(
    $lockKey, 
    $lockToken, 
    ['nx', 'ex' => $lockExpire]
);

if ($isLocked) {
    try {
        // 执行业务代码
    } finally {
        // 确保只释放自己的锁
        if ($redis->get($lockKey) === $lockToken) {
            $redis->del($lockKey);
        }
    }
} else {
    // 获取锁失败
}

使用 RedLock 算法实现分布式锁

对于更复杂的分布式环境,可以使用 RedLock 算法,它需要在多个独立的 Redis 实例上获取锁:

php实现redis锁

function acquireLock($redisInstances, $resource, $ttl, $retryCount = 3, $retryDelay = 200) {
    $token = uniqid();
    $lockSuccessCount = 0;

    for ($i = 0; $i < $retryCount; $i++) {
        $lockSuccessCount = 0;

        foreach ($redisInstances as $redis) {
            if ($redis->set($resource, $token, ['nx', 'px' => $ttl])) {
                $lockSuccessCount++;
            }
        }

        // 检查是否在大多数实例上获取了锁
        if ($lockSuccessCount > (count($redisInstances) / 2)) {
            return $token;
        }

        // 释放已经获取的锁
        foreach ($redisInstances as $redis) {
            $redis->del($resource);
        }

        usleep($retryDelay * 1000);
    }

    return false;
}

function releaseLock($redisInstances, $resource, $token) {
    foreach ($redisInstances as $redis) {
        $script = '
            if redis.call("get", KEYS[1]) == ARGV[1] then
                return redis.call("del", KEYS[1])
            else
                return 0
            end
        ';
        $redis->eval($script, [$resource, $token], 1);
    }
}

使用 Redis 扩展的锁功能

某些 PHP Redis 扩展(如 phpredis)提供了内置的锁方法:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

if ($redis->rawCommand('LOCK', 'my_lock', 'NX', 'EX', 10)) {
    try {
        // 执行业务代码
    } finally {
        $redis->rawCommand('UNLOCK', 'my_lock');
    }
}

使用 Predis 库实现 Redis 锁

如果使用 Predis 客户端库,可以这样实现:

require 'vendor/autoload.php';
$client = new Predis\Client();

$lockKey = 'resource_lock';
$lockExpire = 10;
$lockToken = uniqid();

$lockAcquired = $client->set($lockKey, $lockToken, 'EX', $lockExpire, 'NX');

if ($lockAcquired) {
    try {
        // 执行业务代码
    } finally {
        $script = '
            if redis.call("get", KEYS[1]) == ARGV[1] then
                return redis.call("del", KEYS[1])
            else
                return 0
            end
        ';
        $client->eval($script, 1, $lockKey, $lockToken);
    }
}

注意事项

  • 确保为锁设置合理的过期时间,避免死锁
  • 使用唯一标识符(token)来确保只释放自己的锁
  • 考虑锁续期机制,如果业务执行时间可能超过锁的过期时间
  • 在高并发环境下,重试机制和退避策略很重要
  • 分布式环境下,时钟同步问题需要考虑
  • 评估业务对锁的需求强度,有些场景可能不需要强一致性锁

标签: phpredis
分享给朋友:

相关文章

php实现购物车

php实现购物车

PHP实现购物车功能 购物车功能是电商网站的核心模块之一,通常涉及商品添加、删除、数量修改和结算等操作。以下是使用PHP实现购物车功能的几种方法。 使用Session存储购物车数据 Session是…

php实现图片上传

php实现图片上传

实现图片上传的基本步骤 创建HTML表单用于文件上传,表单需设置enctype="multipart/form-data"属性,确保文件数据正确传输。 <form action="uploa…

php实现上传

php实现上传

PHP 文件上传实现 HTML 表单设置 创建一个包含文件上传字段的 HTML 表单,确保表单的 enctype 属性设置为 multipart/form-data,这是文件上传必需的设置。 &l…

php实现搜索

php实现搜索

PHP实现搜索功能的方法 在PHP中实现搜索功能通常涉及数据库查询和用户输入的匹配。以下是几种常见的实现方式: 使用MySQL LIKE语句 通过简单的LIKE语句实现基础搜索: $searchT…

基于php的设计与实现

基于php的设计与实现

PHP 设计与实现的关键要素 环境搭建与框架选择 PHP开发需配置服务器环境(如Apache/Nginx)、PHP版本(建议7.4+)及数据库(MySQL/MariaDB)。主流框架包括Laravel…

php实现推送

php实现推送

PHP 实现推送功能的方法 PHP 实现推送功能可以通过多种方式完成,包括 WebSocket、Server-Sent Events (SSE)、长轮询或第三方推送服务。以下是几种常见的方法: 使用…