php redis分布式锁

一,概念

在PHP中实现分布式锁通常可以使用数据库、缓存系统(如Redis)或者其他中央存储系统来保证在分布式系统中的数据一致性与同步。秒杀下单、抢红包等等业务场景,都需要用到分布式锁。

常规方案大概有七中

方案一:SETNX + EXPIRE

方案二:SETNX + value值是(系统时间+过期时间)

方案三:使用Lua脚本(包含SETNX + EXPIRE两条指令)

方案四:SET的扩展命令(SET EX PX NX)

方案五:SET EX PX NX + 校验唯一随机值,再释放锁

方案六: 开源框架~Redisson

方案七:多机实现的分布式锁Redlock

这里我采用方案三,加锁和根据判断解锁都需要保持原子性,所以使用Lua脚本

二、代码

php 复制代码
<?php

class RedisLock
{
    private $redis;
    private $lockKey;

    public function __construct($lockKey)
    {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
        $this->lockKey = $lockKey;
    }

    public function acquireLock()
    {
        // 设置锁的超时时间,防止死锁(在删除锁的时候有可能服务挂了,那这个锁就成了死锁,设置过期时间可以防止死锁)
        $expire = 10;
        // 生成一个唯一的标识符(可能会出现线程A代码未执行完,锁已经过期,这时候另外一个线程B就能拿到了锁,这时线程A执行完毕删除锁,如果没有当前线程唯一标识就会删除掉B已经拿到的锁)
        $identifier = uniqid();

        while (!$this->redis->set($this->lockKey, $identifier, ['NX', 'EX' => $expire])) {
            // 如果设置失败,等待一段时间后重试
            usleep(1000);
        }

        return $identifier;
    }

    public function releaseLock($identifier)
    {
        // 释放锁,检查标识符是否匹配,确保只有持有锁的请求才能释放锁
        //这里的判断和删除锁需要保持原子性,所以使用Lua脚本来删除
        if ($this->redis->eval("if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end", [$this->lockKey, $identifier], 1)) {
            return true;
        }

        return false;
    }
}

// 示例用法
$lock = new RedisLock('my_resource');

// 尝试获取锁
$identifier = $lock->acquireLock();

if ($identifier) {
    // 成功获取锁,执行需要同步的操作

    // 释放锁
    $lock->releaseLock($identifier);
} else {
    // 获取锁失败,处理冲突或重试逻辑
    echo "Failed to acquire lock\n";
}
相关推荐
leeyi1 天前
Checkpoint 机制:Agent 怎么在断电后接着跑
redis·aigc·agent
云技纵横2 天前
一个 @Async 让循环依赖暴雷:Spring 代理的暗坑
redis
犯困蛋挞yy3 天前
用Claude快速解决Redis代码报错反复无解的问题
redis
两个人的幸福7 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
用户3169353811839 天前
Java连接Redis
redis
BingoGo9 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack9 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820710 天前
PHP 扩展——从入门到理解
php
鹏仔先生11 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
小小工匠11 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化