码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • php redis分布式锁


    一,概念

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

    在这里插入图片描述
    常规方案大概有七中
    方案一:SETNX + EXPIRE
    方案二:SETNX + value值是(系统时间+过期时间)
    方案三:使用Lua脚本(包含SETNX + EXPIRE两条指令)
    方案四:SET的扩展命令(SET EX PX NX)
    方案五:SET EX PX NX + 校验唯一随机值,再释放锁
    方案六: 开源框架~Redisson
    方案七:多机实现的分布式锁Redlock
    这里我采用方案三,加锁和根据判断解锁都需要保持原子性,所以使用Lua脚本

    二、代码

    
    
    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";
    }
    
    
  • 相关阅读:
    基于Java的高校科研信息管理系统设计与实现(亮点:完整严谨的科研项目审批流程、多文件上传、多角色)
    pdf如何加密码保护?
    微服务Spring Boot 整合Redis 阻塞队列实现异步秒杀下单
    YARP:探索反向代理的新境界
    【逗老师的无线电】MMDVM盒子pi-star系统添加4G网卡及修改路由优先级
    Python学习笔记--面向对象的概念
    【wpf】数据模板 + ContextMenu 导致的 绑定失效
    java -- 深拷贝和浅拷贝的区别 & 如何实现深拷贝和浅拷贝
    IDEA 连接 数据库
    2023年亚太杯数学建模思路 - 案例:感知机原理剖析及实现
  • 原文地址:https://blog.csdn.net/sang521jia/article/details/139629409
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号