• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

PHP实现Redis并发锁示例

php 搞代码 3年前 (2022-03-30) 27次浏览 已收录 0个评论
文章目录[隐藏]

前言

在一些业务场景中用户或用过程同时解决一块逻辑时会导致异样抵触, 因而应用并发锁只容许取得锁的那个进入下一步的解决, 未取得锁的进入期待或间接回绝操作, 这样能极大水平防止并发抵触问题.

示例

Redis执行命令是单线程按程序执行的, 应用Redis命令事实锁性能也就意味着先执行的先拿到锁.

环境阐明:

  • 上面示例中应用composer装置的predis/predis:^1.1扩大连贯Redis
  • config()函数是用来获取Redis服务配置的,你能够替换成你环境中的对应值
<code class="php"><?php

namespace util;

use Predis\Client;

class Redis
{
    const LOCK_PREFIX = 'lk:'; //并发锁键名前缀
    
    private static $client;
    
    /**
     * 单例模式获取redis连贯实例
     * @return Client
     */
    public static function client()
    {
        if (!self::$client) {
            $config = [
                'scheme' => 'tcp',
                'host' => config('redis.host'),
                'port' => config('redis.port'),
            ];
            //没有配置明码时,不传入明码项参数
            if (config('redis.password')) $config['password'] = config('redis.password');
            
            //所有键名都带上默认前缀
            self::$client = new Client($config, ['prefix' => config('redis.prefix')]);
        }

        return self::$client;
    }
    
    /**
     * 增加自定义并发锁
     * 原理是redis的单线程操作
     * @param string $name 锁名
     * @param int $ttl 锁的存在时长,秒
     * @param int $retries 重试次数
     * @param int $interval 重试距离,毫秒
     * @return bool 是否由以后调用加锁胜利
     */
    public static function lock(string $name, int $ttl = 10, int $retries = 0, int $interval = 200)
    {
        $redis = self::client();
        $key = self::LOCK_PREFIX . $name;
        $is_lock = false; //默认是加锁失败
        $interval = $interval * 1000; //毫秒转微秒
        
        //默认只试一次,如设了重试次数则叠加
        $num = 1 + $retries;
        for ($i = 1; $i <= $num; $i++) {
            //要害操作,键不存在时才设置值且带过期工夫
            $is_lock = (bool)$redis->set($key, 1, 'NX', 'EX', $ttl);
            
            if ($is_lock) {
                break;
                
            } elseif ($retries > 0 && $i < $num) {
                //间歇后再重试;如以后已是最初一次重试,则不休眠
                usleep($interval);
            }
        }

        return $is_lock;
    }

    /**
     * 解除自定义并发锁
     * @param string $name 锁名
     * @return bool 是否胜利
     */
    public static function unlock(string $name)
    {
        $key = self::LOCK_PREFIX . $name;

        return (bool)self::client()->del([$key]);
    }

}

//应用
//加锁, 返回 true 示意胜利获取锁
$lk = Redis::lock('lock_key');
if ($lk) {
    //进行一些业务解决
}

//解锁, 业务解决完后解锁, 解锁后其他人可从新取得锁
Redis::unlock('lock_key');

end.


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP实现Redis并发锁示例
喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址