PHP项目添加分布式锁,这里是ThinkPHP8框架实现分布式锁

发布时间:2024年01月13日

背景:公司旧项目,最初访问量不多,单机部署的。后来,访问量上来了,有阵子很卡,公司决定横向扩展,后端代码部署了三台服务器。部署调整后,有用户反馈,一个订单支付了三次。

问题分析:
通过对项目日志分析,问题应该出现在,使用Redis做分布式锁,没有做到原子性操作。判断键是否存在和设置键及有效期是分两步来的,服务器卡的时候,放大了这两步操作的时间,导致了问题产生。

问题解决:
得优化这部分代码,得采用Redis调用lua脚本,实现操作的原子性。查了各种博客及Redis官方文档,推荐了ronnylt/redlock-php这个扩展,进来发现这个扩展比较老旧了,支持PHP版本太老了。
在这里插入图片描述
通过搜索redlock-php发现signe/redlock-php扩展应该可以满足公司项目需求。
在这里插入图片描述

PHP分布式测试:
本地部署了两套PHP接口代码,环境如下:

ThinkPHP8.0
PHP8
composer require ronnylt/redlock-php

测试接口代码如下:

<?php
declare (strict_types=1);

namespace app\controller;

use RedLock\RedLock;

class Index
{
    public function index()
    {
        $servers = [
            ['127.0.0.1', 6379, 0.01],
        ];

        $redLock = new RedLock($servers);
        $lock = $redLock->lock('my_resource_name', 200000);
        // $lock是一个数组,说明抢到临界资源,可以执行业务;上锁失败是false
        if ($lock) {
            // 执行业务逻辑
            echo "执行业务代码...<br/>";

            // 业务执行完毕,可以进行解锁操作
            $redLock->unlock($lock);
        } else {
            echo "未抢到临界资源,继续等待...<br/>";
        }
    }
}

测试时注释了解锁时间,把加锁时间设置成了200秒,测试结果符合预期,下面是测试过程截图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
符合预期后,把这扩展安装到现有项目,优化了现有代码,测试上线,这里记录下,防止下回碰到类似问题又去重零解决此类问题。

小结下流程:
1、PHP项目安装扩展

composer require ronnylt/redlock-php

2、分布式锁实现代码示例

<?php
declare (strict_types=1);

namespace app\controller;

use RedLock\RedLock;

class Index
{
    public function index()
    {
        $servers = [
            ['127.0.0.1', 6379, 0.01],
        ];

        $redLock = new RedLock($servers);
        $lock = $redLock->lock('my_resource_name', 200000);
        // $lock是一个数组,说明抢到临界资源,可以执行业务;上锁失败是false
        if ($lock) {
            // 执行业务逻辑
            echo "执行业务代码...<br/>";

            // 业务执行完毕,可以进行解锁操作
            // $redLock->unlock($lock);
        } else {
            echo "未抢到临界资源,继续等待...<br/>";
        }
    }
}
文章来源:https://blog.csdn.net/rulaixiong/article/details/135567518
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。