前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PHP进阶与redis锁限制并发访问功能示例

PHP进阶与redis锁限制并发访问功能示例

作者头像
友儿
发布2022-09-11 10:26:14
6090
发布2022-09-11 10:26:14
举报
文章被收录于专栏:友儿友儿

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

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

代码语言:javascript
复制
if A(可以换领) 
   B(执行换领) 
   C(更新为已换领) 
   D(结束) 

如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会更新为已换领(C)。

因此如果用户在有一个更新为已换领之前,有多少次请求,这些请求都可以执行成功。?

代码语言:javascript
复制
<?php
/**
 * Created by ZhengNiu.
 * User: 77103
 * Date: 2019/3/28
 * Time: 9:38
 */

namespace app\helper;

use Yii;

class RedisLock
{
    private $_redis;
    private $key;
    private $expire;

    /**
     * 初始化redis
     *
     * RedisLock constructor.
     * @param string $key 锁标识
     * @param int $expire 锁过期时间
     */
    public function __construct($key, $expire = 5)
    {
        try{
            $this->_redis = Yii::$app->redis;
            $this->key = $key;
            $this->expire = $expire;
        }catch (\Exception $ex) {
            return  new \Exception($ex->getMessage());
        }
    }

    /**
     * 获取锁
     *
     * @return bool
     */
    public function lock()
    {
        //不存在则返回1,存在返回0
        $is_lock = $this->_redis->setnx($this->key, time() + $this->expire);
        // 不能获取锁
        if (!$is_lock) {

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

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

        return $is_lock ? true : false;
    }

    /**
     * 释放锁
     *
     * @return Boolean
     */

    public function unlock()
    {
        return $this->_redis->del($this->key);
    }
}

调用:

代码语言:javascript
复制
<?php

    /**
     * 锁机制
     */
    public function actionLock()
    {
        $this->layout = false;
        $oRedisLock = new RedisLock('test2', 10);// 创建redislock对象
        $is_lock = $oRedisLock->lock();
        if ($is_lock) {
            echo 'get lock success</br>';
            //业务逻辑start
            sleep(5);
            //业务逻辑end
            $oRedisLock->unlock();
        } else {
            echo 'request too frequently</br>';
        }
    }

测试结果:打开两个浏览器 先访问的浏览器

代码语言:javascript
复制
get lock success
do sth..
success

后者:

代码语言:javascript
复制
request too frequently
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
腾讯云服务器利旧
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档