PHP模拟高并发异步请求测试+redis的setnx处理并发和防止死锁处理

ops/2024/10/16 0:19:07/
/** PHP并发异步请求测试*  /test/curlMulti*/public function curlMultiAction(){$urls = ["http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create","http://localhost:801/api/order/create", "http://localhost:801/api/order/create",];//并发测试$url = 'http://localhost:801/api/order/create';$data=['customerId'=>'10000','customerOrderNo'=>'Test530051-'.uniqid(),'goodsId'=>'1001273','account'=>'18857850025x','num'=>1,'sign'=>'abDebug',];// 创建批处理cURL句柄$multi_handle = curl_multi_init();$curls = [];foreach ($urls as $url){$ch = curl_init();$data['customerOrderNo'] = uniqid('Test-');curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_multi_add_handle($multi_handle, $ch);$curls[] = $ch;}$running = null;do {curl_multi_exec($multi_handle, $running);} while ($running > 0);foreach ($curls as $ch) {$response = curl_multi_getcontent($ch);echo "Response: " . $response . PHP_EOL;curl_multi_remove_handle($multi_handle, $ch);curl_close($ch);}curl_multi_close($multi_handle);die;}在 Redis 里,所谓 SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果,不过很多人没有意识到 SETNX 有陷阱!比如说:某个查询数据库的接口,因为调用量比较大,所以加了缓存,并设定缓存过期后刷新,问题是当并发量比较大的时候,如果没有锁机制,那么缓存过期的瞬间,大量并发请求会穿透缓存直接查询数据库,造成雪崩效应,如果有锁机制,那么就可以控制只有一个请求去更新缓存,其它的请求视情况要么等待,要么使用过期的缓存。下面以目前 PHP 社区里最流行的 PHPRedis 扩展为例,实现一段演示代码:<?php$ok = $redis->setNX($key, $value);if ($ok) {$cache->update();$redis->del($key);
}?>
缓存过期时,通过 SetNX  获取锁,如果成功了,那么更新缓存,然后删除锁。看上去逻辑非常简单,可惜有问题:如果请求执行因为某些原因意外退出了,导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新。于是乎我们需要给锁加一个过期时间以防不测:<?php$redis->multi();
$redis->setNX($key, $value);
$redis->expire($key, $ttl);
$redis->exec();?>
<?php$ok = $redis->set($key, $random, array('nx', 'ex' => $ttl));if ($ok) {$cache->update();if ($redis->get($key) == $random) {$redis->del($key);}
}?>
Redis防死锁处理: $lock_key = 'locks_' . $userid;
$is_lock = $redis->setnx($lock_key , 1); // 加锁
if($is_lock == true){ // 获取锁权限// 程序逻辑处理:if ......// 释放锁$redis->del($lock_key);
}else{// 防止死锁if($redis->ttl($lock_key) == -1){$redis->expire($lock_key, 5);}return true; // 获取不到锁权限,直接返回
}

$redis->ttl设置过期时间。当 key 不存在时,返回 -2 。 当 key 存在但没有设置剩余生存时间时,返回 -1 。 否则,以秒为单位,返回 key 的剩余生存时间。

注意:在 Redis 2.8 以前,当 key 不存在,或者 key 没有设置剩余生存时间时,命令都返回 -1 。


http://www.ppmy.cn/ops/94966.html

相关文章

【Nodejs】五、Node.js 模块化

一、介绍 1.1 什么是模块化与模块 ? 将一个复杂的程序文件依据一定规则&#xff08;规范&#xff09;拆分成多个文件的过程称之为 模块化 其中拆分出的 每个文件就是一个模块 &#xff0c;模块的内部数据是私有的&#xff0c;不过模块可以暴露内部数据以便其他 模块使用…

使用 Python 进行 PDF 文件加密

使用 Python 解密加密的 PDF 文件-CSDN博客定义一个名为的函数&#xff0c;该函数接受三个参数&#xff1a;输入的加密 PDF 文件路径input_pdf、输出的解密 PDF 文件路径output_pdf和密码password。https://blog.csdn.net/qq_45519030/article/details/141256661 在数字化时代…

顶顶通呼叫中心中间件-通话之前录音配置方法(mod_cti基于FreeSWITCH)

顶顶通呼叫中心中间件-通话之前录音配置方法(mod_cti基于FreeSWITCH) 1、修改配置文件 点击配置文件 -> 点击vars -> 根据图中配置 -> 点击提交XML ->重新启动freeswitch 修改成true就是电话接通开始录音&#xff0c;修改成false就是通话之前开始录音。 <!--应…

Qt 系统相关 - 网络与音视频

目录 一、Qt 网络 1. UDP Socket 1.1 核心 API 概览 1.2 回显服务器 1.3 回显客户端 2. TCP Socket 2.1 核心 API 概览 2.2 回显服务器 2.3 回显客户端 3. HTTP Client 3.1 核心 API 3.2 代码示例 二、Qt 音视频 1. Qt 音频 1.1 核心API概览 1.2 示例 2. Qt 视…

Vue项目-Table添加Form表单校验

一、HTML <template><div class"taskInfo"><el-form:model"generateParams":rules"formRules"ref"formRef"class"taskInfoForm"label-width"100px"><ul class"taskInfoSearch"&g…

深兰科技创始人陈海波入选“2024先锋科创家?硬科技商业先锋榜”

8月14日&#xff0c;2024先锋科创家系列榜单揭晓&#xff0c;深兰科技创始人、董事长陈海波先生凭借创新精神和商业洞察力成功入选&#xff0c;荣登“2024先锋科创家•硬科技商业先锋榜”。 该榜单评选由财联社《科创板日报》联合上海科学技术情报研究所(ISTIS)共同发起&#x…

云HIS区域医疗卫生信息化平台源码,云HIS系统,支持多租户,一套系统可以供多家医院使用

云hIS系统概述 基于云计算的医院信息管理系统&#xff08;云HIS&#xff09;&#xff0c;通过SaaS服务模式提供。这种云HIS系统设计考虑了模板化、配置化、智能化和可扩展性&#xff0c;覆盖了基层医疗机构的核心工作流程&#xff0c;并且能够与监管系统无缝对接&#xff0c;满…

Elasticsearch 分页机制及其深度分页问题解析

Elasticsearch 分页机制及其深度分页问题解析 引言 在处理大规模数据集时&#xff0c;分页是常见的需求&#xff0c;尤其是在搜索引擎中。Elasticsearch&#xff0c;作为一个高效的搜索引擎&#xff0c;提供了几种分页机制来满足不同的使用场景。然而&#xff0c;深度分页可能…