当前位置: 首页 > news >正文

php方案 PHP的消息幂等消费

PHP消息幂等消费 先说问题 消息队列重试机制 → 同一条消息可能投递多次 订单消息消费两次 → 扣款两次 → 用户投诉 ↑ 必须保证"处理多次 = 处理一次"---幂等的三个层面1.最简单-Redis 去重classIdempotentConsumer{publicfunctionconsume(array$message):void{$msgId=$message['id'];// 消息唯一ID(MQ自带或业务生成)$key="consumed:$msgId";// SET NX = 只有不存在时才设置,原子操作$isNew=$this->redis->set($key,1,['NX','EX'=>86400]);if(!$isNew){return;// 重复消息,直接跳过}$this->process($message);// 真正处理}}问题:process()失败了,但 Redis 已标记"已消费"→ 消息丢失---2.正确姿势-先执行后标记+数据库唯一键publicfunctionconsume(array$message):void{$msgId=$message['id'];try{$this->pdo->beginTransaction();// 唯一键冲突 = 重复消息,直接忽略$this->pdo->exec(" INSERT IGNORE INTO consumed_messages (msg_id, created_at) VALUES ('$msgId', NOW()) ");if($this->pdo->rowCount()===0){$this->pdo->rollBack();return;// 重复,跳过}$this->processOrder($message);// 业务逻辑$this->pdo->commit();}catch(\Exception$e){$this->pdo->rollBack();// 失败回滚,消息可重试throw$e;}}关键:INSERTIGNORE+事务,业务处理和去重记录原子完成---3.业务层幂等-状态机兜底// 即使去重失败,业务状态机也能拦截publicfunctionprocessOrder(array$msg):void{$order=Order::find($msg['order_id']);// 状态检查:不是待支付 → 已处理过,直接跳过if($order->status!=='pending'){return;}// UPDATE 加状态条件,天然幂等$affected=$this->pdo->exec(" UPDATE orders SET status = 'paid', paid_at = NOW() WHERE id ={$msg['order_id']}AND status = 'pending' ");if($affected===0)return;// 并发下已被处理,安全跳过$this->deductBalance($msg);// 扣款}---4.消息ID生成(没有唯一ID时)// 用业务字段组合生成幂等key,比随机UUID更可靠functionbuildMsgId(array$message):string{returnmatch($message['type']){'pay'=>"pay:{$message['order_id']}:{$message['amount']}",'notify'=>"notify:{$message['user_id']}:{$message['event']}",default=>md5(json_encode($message)),};}---三层防御组合 第一层:RedisNX→ 快速拦截99%重复(性能好) 第二层:DB唯一键 → 兜底,防Redis故障 第三层:状态机条件 → 业务语义保障,最终防线 消息到来 → Redis检查 →DB插入 → 业务状态检查 → 执行 ↓重复 ↓重复 ↓已处理 跳过 跳过 跳过---常见坑 坑1:先标记再处理 → 处理失败消息丢失 ✗ 坑2:只用Redis去重 → Redis重启丢数据 ✗ 坑3:事务外做去重检查 → 并发竞争失效 ✗ 坑4:用消息内容md5做ID→ 相同内容≠相同业务 ✗ 正确:DB唯一键+事务+业务状态机三层 ✓---一句话 幂等=Redis 快速拦截+数据库唯一键兜底+状态机条件更新,缺一不可。
http://www.jsqmd.com/news/449852/

相关文章:

  • 基于AMT双参数动力性换挡规律的燃油车自动变速模型研究——采用MATLAB m文件编写,实现直接运行
  • 基于主从博弈理论的共享储能与综合能源微网优化复现之旅
  • AI泡沫幸存者:从烧钱到盈利的残酷转型——软件测试从业者的专业视角
  • 工厂注意!以后SLCP审核机构不能随便选了:高分才能上榜,低分直接消失!
  • 台达DVP 16ES2与DT3系列温控器通讯程序TDES-1
  • 深入剖析AI 大语言模型 LLM
  • 深度盘点:AI行业支持远程办公的十大热门岗位及招聘渠道一览
  • 助人为乐之客观分析:女性如何选择才不吃亏?——技术岗 vs 管理岗
  • 【无标题】C语言中的循环与分支语句
  • 摆脱论文困扰!千笔,专科生专属AI写作神器
  • Ansys、ABAQUS质量刚度矩阵最强智能提取版本:腾讯会议讲解及模型调式指南(Matlab...
  • 三维随机裂隙网络模型(圆盘形,可直接导入COMSOL并利用Matlab接口编程的模型生成工具包...
  • [特殊字符] SegFormer:高精度树木覆盖分割模型
  • 量子骗局揭秘:伪量子算法代码证据
  • Nginx的性能优化
  • STM32G431 无感 FOC 驱动:从原理到实现
  • 一文读懂《2028年全球智能危机》
  • 基于SpringBoot+Vue的演出购票系统
  • 2026年企业AI战略必看:GEO优化公司选型指南与精准适配路径实测 - 品牌推荐
  • 2026高职大数据技术需要掌握哪些技能?
  • 深聊2026年盘扣式脚手架厂家,哪家性价比和口碑都好 - 工业设备
  • 数字铁幕:中美AI标准分裂应对策略
  • 锂电池负极表面那些张牙舞爪的锂枝晶,像极了科幻片里的外星生物入侵。这些金属晶体在生长过程中随时可能刺穿隔膜引发短路,咱们今天就用相场法来揭开它们的生长密码
  • 亲测好用!AI论文平台 千笔AI VS 笔捷Ai 本科生必备神器
  • 羊小咩变荔卡购物额度回收合规边界与实操技巧 - 容易提小溪
  • 编写洗发水,沐浴露配方配比程序。按不同发质肤质计算原料比例,生成简易配方。
  • 一文搞懂MCP、Agent、Skills:AI时代三大核心概念深度对比,搞懂了少走3年弯路
  • 【无人机追踪】基于资源树多约束 (能耗 时间 联盟)的多无人机任务分配算法附Matlab代码
  • 2026年企业AI战略必看:GEO服务商选型指南与精准适配路径 - 品牌推荐
  • 分账和代付,哪个更适合你