php 使用redis锁限制并发访问类

2023-05-16

1.并发访问限制问题

对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功。

例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券。

伪代码如下:

if A(可以换领)
    B(执行换领)
    C(更新为已换领)
D(结束)

如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会更新为已换领(C)。因此如果用户在有一个更新为已换领之前,有多少次请求,这些请求都可以执行成功。

2.并发访问限制方法

使用文件锁可以实现并发访问限制,但对于分布式架构的环境,使用文件锁不能保证多台服务器的并发访问限制。

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
本文将使用其setnx方法实现分布式锁功能。setnxSet it Not eXists。
当键值不存在时,插入成功(获取锁成功),如果键值已经存在,则插入失败(获取锁失败)

RedisLock.class.php

<?php
/**
 *  Redis锁操作类
 *  Date:   2016-06-30
 *  Author: fdipzone
 *  Ver:    1.0
 *
 *  Func:
 *  public  lock    获取锁
 *  public  unlock  释放锁
 *  private connect 连接
 */
class RedisLock { // class start

    private $_config;
    private $_redis;

    /**
     * 初始化
     * @param Array $config redis连接设定
     */
    public function __construct($config=array()){
        $this->_config = $config;
        $this->_redis = $this->connect();
    }

    /**
     * 获取锁
     * @param  String  $key    锁标识
     * @param  Int     $expire 锁过期时间
     * @return Boolean
     */
    public function lock($key, $expire=5){
        $is_lock = $this->_redis->setnx($key, time()+$expire);

        // 不能获取锁
        if(!$is_lock){

            // 判断锁是否过期
            $lock_time = $this->_redis->get($key);

            // 锁已过期,删除锁,重新获取
            if(time()>$lock_time){
                $this->unlock($key);
                $is_lock = $this->_redis->setnx($key, time()+$expire);
            }
        }

        return $is_lock? true : false;
    }

    /**
     * 释放锁
     * @param  String  $key 锁标识
     * @return Boolean
     */
    public function unlock($key){
        return $this->_redis->del($key);
    }

    /**
     * 创建redis连接
     * @return Link
     */
    private function connect(){
        try{
            $redis = new Redis();
            $redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);
            if(empty($this->_config['auth'])){
                $redis->auth($this->_config['auth']);
            }
            $redis->select($this->_config['index']);
        }catch(RedisException $e){
            throw new Exception($e->getMessage());
            return false;
        }
        return $redis;
    }

} // class end

?>

demo.php

<?php
require 'RedisLock.class.php';

$config = array(
    'host' => 'localhost',
    'port' => 6379,
    'index' => 0,
    'auth' => '',
    'timeout' => 1,
    'reserved' => NULL,
    'retry_interval' => 100,
);

// 创建redislock对象
$oRedisLock = new RedisLock($config);

// 定义锁标识
$key = 'mylock';

// 获取锁
$is_lock = $oRedisLock->lock($key, 10);

if($is_lock){
    echo 'get lock success<br>';
    echo 'do sth..<br>';
    sleep(5);
    echo 'success<br>';
    $oRedisLock->unlock($key);

// 获取锁失败
}else{
    echo 'request too frequently<br>';
}

?>



测试方法:
打开两个不同的浏览器,同时在A,B中访问demo.php
如果先访问的会获取到锁
输出
get lock success
do sth..
success

另一个获取锁失败则会输出request too frequently

保证同一时间只有一个访问有效,有效限制并发访问。


为了避免系统突然出错导致死锁,所以在获取锁的时候增加一个过期时间,如果已超过过期时间,即使是锁定状态都会释放锁,避免死锁导致的问题。


源码下载地址:点击查看

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

php 使用redis锁限制并发访问类 的相关文章

  • 如何在 PHP 中从字符串类名实例化? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 如何创建返回方法名称的新实例 不幸的是我收到这个错误 错误 类名必须是有效的对象或字符串 这是我的代码 class Foo public f
  • 获取今天的科普特日期

    我正在寻找获取今天的科普特日期与任何代码类型类似php or javascript在我的网站标题中显示科普特日期 我需要阿拉伯语或英语版本 我试图找到它 但没有找到类似的英文内容 参考 http www copticchurch net e
  • 垃圾邮件打败了我所有的验证码

    我有一个 WordPress 博客 我在上面使用验证码插件的时间最长 因为它有效 最近我收到了大量的垃圾邮件 然后我尝试执行通过 PHP 生成的 将这些随机数添加在一起 但仍然没有成功 我不太确定需要做什么来阻止这些垃圾邮件 但这很烦人 我
  • 如何仅删除页面的自动段落格式,而不删除帖子的自动段落格式(WordPress)

    我已经熟悉这个在 WordPress 中删除自动段落格式的小技巧 remove filter the content wpautop remove filter the excerpt wpautop 但是添加这个函数 php删除整个网站的
  • xdebug.remote_handler 在 PHP.INI 中设置,但未在 PHPinfo 中显示

    我正在尝试让 Xbdebug 与 NetBeans 一起运行 以便调试一些 PHP 代码 我确信几年前我已经让它工作了 然后切换了 IDE 现在想切换回来 When I try to debug the status bar shows 并
  • 使用 phpdocx 下载损坏的 .docx

    我有一个项目 我们使用 phpdocx pro 在模板中生成 docx 文件 我可以很容易地将数据输入到模板中 但是当下载文件并在 MS Word 2010 中打开时 程序报告无法打开文件 因为内容存在问题 详细信息是 文件已损坏 并且无法
  • 解析错误:语法错误,意外的 T_RETURN [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 遇到这个问
  • PHP - 警告:strpos() [function.strpos]: 空分隔符是什么意思?

    警告 strpos function strpos 空分隔符是什么意思 我有这个 if strpos 039 text false text str replace 039 text 猜测一下 我会说 text是一个空字符串 感谢马克指出细
  • 从 php 到 JavaScript 的数组

    我正在尝试使用 json 将数组列表从 php 传输到 javascript 但它不起作用 JS ajax url getProfilePhotos php type post post or get method data if you
  • 带 url 参数的 Laravel post 路由

    我面临着幼虫路由的大墙 我似乎找不到解决方案 我在视图模板中有此表单
  • Laravel 登录后重定向回来

    登录后如何重定向返回页面 在 Laravel 5 2 中 认证控制器 protected redirectTo 重定向用户
  • 当我使用 session_start() 时,Xampp 7.0.1 Apache 崩溃

    当我在 PHP 中使用 session start 启动会话时 我的 Apache 服务器停止工作 我正在使用 Windows 版 Xampp 7 0 1 我的配置文件如下所示 即使我把它放在文件的第一行 它也不起作用 有人知道如何解决这个
  • ACL授权失败后ZF3重定向

    我有一个带有 ACL 的新 ZF3 应用程序 现在 我需要在未经授权的访问的情况下重定向到错误页面 例如 403 我认为最好的方法是触发一个事件 然后捕获它 但我失败了 全部都在我的用户模块中Module php 摘录 namespace
  • php如何生成动态list()?

    根据我的理解 这就是 list 的工作原理 list A1 A2 A3 array B1 B2 B3 所以在帮助下list 我们可以相应地从数组中分配值 这是我的问题 如何生成动态list 1 基于数据库返回结果 我不确定有多少 但我将其全
  • PHP switch case 在 case 中存在多个值

    我有一个变量保存值 每周 每月 季度 和 年度 还有另一个变量保存值从 1 到 10 switch var2 case 1 var3 Weekly break case 2 var3 Weekly break case 3 var3 Mon
  • PHP LDAP 查询获取特定安全组的成员

    我正在努力让 LDAP 查询工作来为我提供安全组的成员 我们的活动目录结构设置为 DC domain DC co dc uk然后 我们有一个名为 公司用户 的 OU 其中有一个用于 IT 和标准的 OU 在这些中我们创建了用户 所以我被设置
  • 设置大型电子邮件通知系统有哪些方法?

    我的公司有一个用 PHP 构建的网站 我们使用内置的 PHP 电子邮件功能每天向订阅者发送数千封电子邮件 这是一个糟糕的主意 它堵塞了我们的服务器 并且需要几个小时才能完成整个批次 现在我已经研究过像 MailChimp 这样的群发邮件服务
  • 使用 file_get_content 发布数据

    我已经做了一些关于如何使用的研究file get content与帖子 我也读过this one https stackoverflow com questions 2445276 how to post data in php using
  • 使用 ImageMagick (PHP) 将 2 个图像并排合并为 1 个图像

    我认为这是一件容易的事 我有 2 张图片 JPG 我希望它们合并成一张图片 其中 2 张图片并排 所以我有图片 A 和图片 B 我想要图片 AB 并排 两个图像具有相同的宽度和高度 在本例中 宽度 200px 高度 300px 但是第二个图
  • 我可以让 swagger-php 在查询字符串上使用数组吗?

    我使用 Swagger php 当我定义查询字符串上的参数时 它可以是一个数组 但据我所知 它不支持这种查询字符串 https api domain tld v1 objects q 1 q 5 q 12 我相信这会被设定in the co

随机推荐

  • MySql查看与修改auto_increment方法

    本文将介绍如何查看表的auto increment及其修改方法 查看表当前auto increment 表的基本数据是存放在mysql的information schema库的tables表中 xff0c 我们可以使用sql查出 span
  • js遍历获取表格内数据方法

    本文将介绍如何使用js获取表格内某一单元格的内容 xff0c 表格由table tr td等html标记组成 table表示表格 xff0c tr表示行 xff0c td表示行中列 1 一般的表格结构如下 span class hljs t
  • JS生成二维码(兼容各种浏览器及中文)

    本文将介绍如何使用JS生成二维码 xff0c 兼容各种浏览器及手机端 xff0c 支持中文 代码如下 xff1a span class hljs doctype lt DOCTYPE html gt span span class hljs
  • mysql 严格模式 Strict Mode说明

    1 开启与关闭Strict Mode方法 找到mysql安装目录下的my cnf xff08 windows系统则是my ini 文件 在sql mode中加入STRICT TRANS TABLES则表示开启严格模式 xff0c 如没有加入
  • C++产生随机数

    随机数 计算机的随机数都是由伪随机数 xff0c 即是由小M多项式序列生成的 xff0c 其中产生每个小序列都有一个初始值 xff0c 即随机种子 xff08 注意 xff1a 小M多项式序列的周期是65535 xff0c 即每次利用一个随
  • git 误删分支恢复方法

    在使用git的过程中 xff0c 因为人为因素造成分支 xff08 commit 被删除 xff0c 可以使用以下步骤进行恢复 首先用以下步骤创建一个新分支 xff0c 修改一些文件后删除 xff0c 以便进行恢复 1 创建分支 abc g
  • 软件工程师的鄙视链

    最近这几年在世界各地突然吹起了一股全民写程序的风潮 xff0c 但是身为一介靠写程序 xff08 以及在上班时间胡乱上网 xff09 来谋生的 developer xff08 所谓的 developer 就是 软件工程师 的比较潮的说法 x
  • mac使用brew安装软件失败的通用解决方法

    使用mac的brew安装软件 xff0c 有时会出现安装失败 xff0c 或显示安装成功 xff0c 但不能正常使用的情况 例如安装php56 redis扩展 xff0c 显示安装成功 xff0c 重启后查看phpinfo看不到redis扩
  • node.JS md5加密中文与php结果不一致的解决方法

    因项目需要 xff0c 需要node JS与php做接口调用 xff0c 发现node JS对中文使用md5加密与php对中文md5加密的结果不同 PHP span class php span class hljs preprocesso
  • mysql互换表中两列数据方法

    1 创建表及记录用于测试 span class hljs operator span class hljs keyword CREATE span span class hljs keyword TABLE span span class
  • mysql 时间戳格式化函数from_unixtime使用说明

    我们一般使用字段类型int 11 时间戳来保存时间 xff0c 这样方便查询时提高效率 但这样有个缺点 xff0c 显示的时间戳 xff0c 很难知道真实日期时间 mysql提供了一个时间戳格式化函数from unixtime来转换格式 f
  • mysql函数concat与group_concat使用说明

    1 concat 函数 使用方法 xff1a concat str1 str2 返回的结果为连接参数产生的字符串 xff0c 如有任何一个参数为null xff0c 则返回值为null 注意 xff1a 如果所有参数均为非二进制字符串 xf
  • mysql innodb启动失败无法重启的处理方法

    电脑在使用过程中死机 xff0c 重启后发现mysql没有启动成功 xff0c 查看错误日志发现是innodb出现问题导致mysql启动失败 错误日志 mysql server start Starting MySQL ERROR The
  • mac环境使用sed修改文件出错的解决方法

    sed是linux命令 xff0c 用于处理文件内容 xff08 修改 xff0c 替换等 xff09 xff0c mac中都可以使用 xff0c 但发现相同的替换命令在linux可以正常执行 xff0c 在mac则执行失败 出错原因 用s
  • mysql order by rand() 效率优化方法

    从一次查询中随机返回一条数据 xff0c 一般使用mysql的order by rand 方法来实现 例如 从20万用户中随机抽取1个用户 span class hljs header mysql gt select from user o
  • 汇编语言:使用冒泡排序算法将10个数按从小到大顺序排列

    汇编语言 xff1a 冒泡排序算法 题目描述 自定义一组有首地址为data的10个字的数组 xff0c 请利用冒泡排序算法来编写程序 xff0c 使该数组中的数按照从小到大的次序有序化 xff08 注 xff1a 10个字可以自己定义 xf
  • 今天终于弄懂结构体数组与结构体变量的关系

    本人也是学计算机专业的 xff0c 但我是一个技术小白 xff0c 今年大一刚刚入学 xff0c 现在在过寒假 xff0c 因为我的C语言成绩并不太好 xff0c 父母总是为我感到担忧 xff0c 因此 xff0c 我每天都在敲代码 xff
  • MongoDB 导出导入备份恢复数据实例

    创建测试数据 创建db testdb collection user 插入10条记录 mongo MongoDB shell span class hljs property version span span class hljs num
  • crontab 使用日期时间命名重定向文件

    linux crontab命令可以实现定时执行任务 xff0c 最小的执行周期是1分钟 关于crontab的使用可以查看 Linux crontab定时执行任务 命令格式与详细例子 例 xff1a 每天12点执行test php xff0c
  • php 使用redis锁限制并发访问类

    1 并发访问限制问题 对于一些需要限制同一个用户并发访问的场景 xff0c 如果用户并发请求多次 xff0c 而服务器处理没有加锁限制 xff0c 用户则可以多次请求成功 例如换领优惠券 xff0c 如果用户同一时间并发提交换领码 xff0