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

PHP 的异步编程 该怎么选择

一切的起点synchronized 的舒适区刚开始写代码时思维往往停留在单机模式。遇到需要控制并发的地方直觉反应就是加个 synchronized 关键字。1. 曾经写过的代码// 简单的库存扣减public synchronized void deductStock(String productId) {// 1. 查询库存Product product stockMapper.selectById(productId);// 2. 判断并扣减if (product.getStock() 0) {product.setStock(product.getStock() - 1);stockMapper.updateById(product);}}2. 这个方案能用吗能用但有前提。如果你的系统是一个简单的后台管理系统或者是一个单节点部署的内部工具并发量极低那么 synchronized 完全足够。它简单、高效且无需引入外部依赖是解决单机并发问题的如意金箍棒。3. 为什么后来不行了问题的关键在于”跨进程“。当业务发展服务需要部署两台甚至更多服务器时每台服务器都有一个独立的 JVM。服务器 A 的 synchronized 锁住了它自己的线程。服务器 B 的 synchronized 锁住了它自己的线程。结果A 和 B 同时放行了一个请求扣减了同一件商品。库存立刻变负数。这时候我们意识到我们需要一把能管得住所有服务器的大锁。二、初尝分布式锁Redis SETNX 的尝试既然 JVM 内部的锁不管用了那自然要找一个所有服务器都能访问到的第三方组件来存这把锁。Redis 因为其高性能和简单的 API成了首选。1. 最直观的写法Redis 有个命令叫 SETNX (SET if Not Exists)。这名字听起来就天生是为了抢占资源设计的。# 谁先执行成功谁就抢到了锁SETNX lock:product:101 1逻辑很简单多个服务器同时发 SETNX 命令。只有一个能返回 1成功其他的返回 0失败。抢到锁的执行业务做完之后 DEL 删除锁。2. 现实中的意外这个方案最大的隐患在于“删锁”这步。如果代码在执行业务逻辑时服务器突然断电了或者进程崩溃了导致 DEL 命令没来得及发出。后果这把锁就像幽灵一样永远存在于 Redis 里。后续所有针对这个商品的请求都会因为拿不到锁而被死死卡住。改进方案必须加过期时间。SETNX lock:product:101 1EXPIRE lock:product:101 10 # 10秒后自动过期3. 还是不够完美SETNX 和 EXPIRE 是两条命令不是原子操作。如果在第一句和第二句之间由于网络抖动或者服务重启断开了锁依然会变成死锁。适用场景这种简单的 SETNX 方案在很早期的 Redis 版本或者一些非核心业务比如简单的定时任务去重中还可以见到但在对于数据准确性要求极高的交易核心链路它显然过于脆弱了。三、进阶原子性与锁不住的尴尬吸取了死锁的教训后来 Redis 官方推出了原子命令或者我们通用 Lua 脚本来保证操作原子性。1. 修复死锁问题# 一条命令搞定加锁和过期时间SET lock:product:101 uuid NX PX 10000这就解决了原子性问题。只要锁加上了由于有过期时间哪怕服务器爆炸锁最终也会自动消失系统能自动恢复。2. 引入了新问题锁因为超时提前释放了假设我们将锁的过期时间设为 10秒。但那天的数据库特别卡业务逻辑执行了 15秒。这就出现了一个严重的逻辑漏洞T0秒线程 A 加锁成功。T10秒锁自动过期释放。T11秒线程 B 进场发现没锁加锁成功。T15秒线程 A 终于执行完了发起 DEL 删除锁。关键点此时 A 删掉的其实是 B 的锁这就导致了连锁崩溃锁失效 - A 删 B 的锁 - B 裸奔 - B 删 C 的锁...适用场景这种方案适用于业务执行时间非常短且稳定的场景。但只要涉及网络调用如第三方支付、跨服务调用执行时间不可控这种固定过期时间的方案就始终悬着一把剑。四、最终方案Redisson 的守候为了解决锁过期时间不好估算的痛点Redisson 带着它的看门狗WatchDog 机制出现了。这也许是目前 Java 生态中最成熟的分布式锁方案。1. 什么是看门狗其实原理很朴素既然我不知道业务要跑多久那我能不能搞个助理在后台盯着后台看门狗Redis ServerRedisson SDK客户端后台看门狗Redis ServerRedisson SDK客户端loop[每隔 10秒(默认LockWatchdogTimeout/3)]1. 加锁 (lock)2. SETNX PEXPIRE (Lua脚本)3. 加锁成功4. 启动定时任务5. 续命 (业务还在跑TLL重置为30s)6. 业务结束解锁 (unlock)7. 停止续命任务8. 删除锁 (DEL)简单来说就是只要业务线程还在跑看门狗会每隔一会儿就去 Redis 喊一声大哥还没完呢给我续个杯Redis 收到通知就把过期时间重新填满。如果业务线程挂了看门狗也没了没人续杯锁自然就过期了。2. 使用起来的感受代码变得异常清爽仿佛回到了单机锁的时代// 1. 获取锁对象RLock lock redisson.getLock(lock:product:101);try {// 2. 加锁开启看门狗默认30秒过期每10秒续期一次lock.lock();// 3. 执行业务哪怕跑了1分钟锁也不会丢complexBusinessLogic();} finally {// 4. 释放锁只有当锁存在且是当前线程加的锁时才释放if (lock.isLocked() lock.isHeldByCurrentThread()) {lock.unlock();}}3. 稳在哪儿Redisson 帮我们把最难处理的几个点屏蔽了自动续期不用纠结 expire 设置多少秒合适。防止误删解锁时会校验线程 ID不会删掉别人的锁。可重入和 synchronized 一样同一个线程可以多次获取同一把锁。适用场景几乎涵盖了所有需要强一致性的分布式并发场景。无论是秒杀扣库存、金融账户扣款还是定时任务的分发执行Redisson 都是目前最稳健的选择。五、集群下的隐忧Redlock 是救世主吗讲到这里很多细心的朋友可能会问如果 Redis 是主从集群Cluster主节点挂了锁还没同步到从节点从节点升级为主锁不就丢了吗这一针见血。为了解决这个问题Redis 之父 Antirez 提出了 Redlock 算法让客户端向 N 个独立的 Redis 节点同时申请锁只要超过半数N/21申请成功就认为获取了锁。1. 为什么我不推荐 Redlock在实际工程落地中Redlock 的投入产出比ROI并不高部署成本高你需要至少 3 个最好 5 个完全独立的 Redis 实例而不是主从集群。性能折损客户端要顺序去多个节点加锁网络开销成倍增加。并非绝对安全分布式系统的时钟跳跃Clock Drift或者长 GC 依然可能打破 Redlock 的安全性这也是著名的 Martin Kleppmann 与 Antirez 辩论的焦点。2. 更有性价比的选择如果你的业务真的无法容忍哪怕百万分之一的主从切换丢锁风险我的建议是方案一独立部署专门部署一个单机版 Redis 实例不做集群只用来存锁。哪怕它挂了整个业务熔断也好过并发乱了。简单粗暴但极其有效。方案二拥抱强一致性CP如果锁的一致性比可用性更重要比如涉及资金转账请转身拥抱 ZooKeeper 或 Etcd。它们天生就是为 CP强一致性设计的不要勉强 AP高可用的 Redis 做它不擅长的事。方案三更通用的选择在 99.9% 的业务场景下接受 Redis 主从切换可能带来的极短暂锁丢失风险。想一想主节点宕机的概率是多少正好在宕机那几毫秒持有锁的概率是多少为了解决这微乎其微的概率引入复杂的 Redlock往往得不偿失。六、最后的一点心得技术方案的演进本质上是在做取舍。Synchronized 胜在简单败在扩展。Redis SETNX 胜在性能败在极端情况的可靠性。Redisson 胜在可靠和完备但在集群极端场景下依然有软肋。葱簧饺追

相关文章:

PHP 的异步编程 该怎么选择

一切的起点:synchronized 的舒适区 刚开始写代码时,思维往往停留在"单机"模式。遇到需要控制并发的地方,直觉反应就是加个 synchronized 关键字。 1. 曾经写过的代码 // 简单的库存扣减 public synchronized void deductStock(Stri…...

嵌入式串口协议中间件:轻量级SerHelp库设计与应用

1. 项目概述nahs-Bricks-Lib-SerHelp是 NAHS(North American Home System)生态中面向嵌入式砖块化(Brick-based)硬件平台的一套轻量级串行通信辅助库。该库不提供底层驱动实现,而是聚焦于串口协议层的工程化封装与通用…...

阿联酋人工智能大学:AI能在战争迷雾中做出理性判断吗?

这项由阿联酋穆罕默德本扎耶德人工智能大学和美国马里兰大学共同完成的研究发表于2026年3月,论文编号为arXiv:2603.16642v1。有兴趣深入了解的读者可以通过该编号查询完整论文。在人类历史上,预测战争走向一直是个极其困难的任务。就像我们很难在暴风雨中…...

LuckyLilliaBot QQ群管理自动化实战指南:从零搭建高效智能管理方案

LuckyLilliaBot QQ群管理自动化实战指南:从零搭建高效智能管理方案 【免费下载链接】LuckyLilliaBot NTQQ的OneBot API插件 项目地址: https://gitcode.com/gh_mirrors/li/LuckyLilliaBot LuckyLilliaBot是一款基于NTQQ客户端与OneBot11协议的QQ机器人开发框…...

如何选择可靠的第三方软件测试机构,构建全生命周期的软件安全防线

在数字化转型的浪潮中,软件已成为企业运营的核心。然而,伴随其重要性一同增长的,是日益严峻的安全威胁。传统软件开发流程中,安全测试往往被置于交付前的独立环节,这种“事后补丁”的模式导致安全漏洞发现晚、修复成本…...

OpenClaw多模态扩展:Qwen3.5-4B-Claude处理截图与PDF

OpenClaw多模态扩展:Qwen3.5-4B-Claude处理截图与PDF 1. 为什么需要多模态能力? 去年夏天,我遇到一个头疼的问题:需要从几百份PDF报告里提取关键数据。手动复制粘贴不仅耗时,还容易出错。当时我就在想,如…...

前端拖拽交互实现:别再只会用原生拖拽了

前端拖拽交互实现:别再只会用原生拖拽了 毒舌时刻这代码写得跟网红滤镜似的——仅供参考。各位前端同行,咱们今天聊聊前端拖拽交互。别告诉我你还在用原生的HTML5拖拽API,那感觉就像在用诺基亚手机——能打电话,但体验太差。 为什…...

收藏!小白也能看懂的大模型如何改写工业效率?

收藏!小白也能看懂的大模型如何改写工业效率? 本文介绍了中控技术的TPT大模型在工业生产中的应用,它通过实时监控、自动计算最优参数和风险预警,帮助企业提升效率、降低成本。与互联网领域的AI应用不同,工业AI的价值更…...

终极Chrome全页截图指南:一键保存完整网页内容的高效方案

终极Chrome全页截图指南:一键保存完整网页内容的高效方案 【免费下载链接】full-page-screen-capture-chrome-extension One-click full page screen captures in Google Chrome 项目地址: https://gitcode.com/gh_mirrors/fu/full-page-screen-capture-chrome-ex…...

【独家首发】Polars 2.0 vs Pandas 2.2清洗基准测试:10亿行CSV清洗仅耗11.3秒?真相在此

第一章:Polars 2.0大规模数据清洗的范式跃迁Polars 2.0 不再是 Pandas 的轻量替代品,而是一次面向现代硬件与真实业务场景的数据处理范式重构。其核心跃迁体现在零拷贝内存布局、全链路惰性执行引擎(LazyFrame)与原生支持的并行流…...

RK3588开发板TF卡槽改造:实现SDIO WIFI模组O9201SB的灵活接入

1. RK3588开发板TF卡槽改造背景与价值 最近在折腾RK3588开发板时,发现一个很有意思的玩法:把原本只能插TF卡的卡槽改造成支持SDIO WIFI模组的接口。这个改造特别适合那些需要灵活接入不同WIFI模组的开发者,比如我在做智能家居网关开发时&…...

OpenClaw开发辅助:Qwen3.5-9B实现日志分析与错误自动修复

OpenClaw开发辅助:Qwen3.5-9B实现日志分析与错误自动修复 1. 为什么需要AI辅助日志分析? 每次凌晨被报警短信吵醒,盯着密密麻麻的日志文件找异常时,我都会想:如果能有个AI助手帮我自动分析日志、定位问题甚至尝试修复…...

Nuxt4 官网访问来源统计的实现

今天我遇到一个值得记录的问题,场景是这样的:官网后台需要做访问统计,我得把访问来源和访问目标的 URL 传递给后端。绕了好一阵子,才终于理清楚。 项目结构上,Nuxt 4 负责官网展示,后端是 Java 服务。核心…...

小白必看!收藏这份Agent思维链技术指南,轻松入门大模型世界

小白必看!收藏这份Agent思维链技术指南,轻松入门大模型世界 本文深入解析了Agent模型中的思维链技术,介绍了不同模型如Claude、Gemini等对思维链的不同称谓及其核心原理,即通过将思考内容带入上下文来提升多轮推理性能。文章对比了…...

浒浦潮汐表查询2026-03-28

位置:浒浦,日期:2026-03-28,农历:丙午[马]年二月初十,星期:星期六,潮汐类型:小潮死汛最高水位:275.00cm,最低水位:122.00cm&#xff0…...

EtherCAT模块化实战:如何为你的设备设计可热插拔的IO模块(基于SSC与0x4711示例)

EtherCAT模块化实战:如何为你的设备设计可热插拔的IO模块 在工业自动化领域,设备的灵活性和可扩展性正变得越来越重要。想象一下,当你的客户需要在生产线上快速更换不同类型的传感器或执行器时,如果每次硬件变更都需要重新配置整个…...

在WSL2 Ubuntu 22.04上搞定RK3568 SDK编译:我遇到的8个坑和填坑方法

在WSL2 Ubuntu 22.04上搞定RK3568 SDK编译:我遇到的8个坑和填坑方法 作为一名长期在Windows环境下工作的嵌入式开发者,第一次尝试在WSL2中编译RK3568 SDK的经历简直像是一场噩梦。从环境配置到最终构建成功,我踩遍了几乎所有可能的坑。这篇文…...

图结构AI Agent记忆机制深度解析:小白/程序员必备,收藏学习大模型前沿技术!

图结构AI Agent记忆机制深度解析:小白/程序员必备,收藏学习大模型前沿技术! 本文深入解析了基于图结构的AI Agent记忆机制,揭示了LLM驱动AI Agent面临的三大局限:知识截断、工具 incompetence 和性能饱和。文章强调记…...

通用GUI编程技术——Win32 原生编程实战(十八)——GDI 设备上下文(HDC)完全指南

通用GUI编程技术——Win32 原生编程实战(十八)——GDI 设备上下文(HDC)完全指南 前面一系列文章我们聊了对话框、控件、资源这些内容,我们的窗口已经能够显示各种控件了。但你可能已经发现了一个问题:我们所…...

IDEA 2023.3 配置 JavaWeb 项目完整流程:从新建到打包 War 的保姆级避坑指南

IDEA 2023.3 配置 JavaWeb 项目完整流程:从新建到打包 War 的保姆级避坑指南 作为一名长期使用 IntelliJ IDEA 进行 JavaWeb 开发的工程师,我深知在配置项目时可能遇到的各种"坑"。特别是对于刚接触 IDEA 的新手来说,从项目创建到最…...

OpenSpec 生成文件说明

proposal.md —— 为什么做、做什么(产品/范围) Why:要解决什么问题、机会是什么。What Changes:会新增/改掉/删掉哪些能力,有没有 BREAKING。Capabilities:会动到哪些能力名(对应后面 specs/&l…...

电子小白之二极管

很多年前我第一次看到电路图上各种二极管符号时,心里只有一个想法:这玩意儿到底干嘛用的?硬件部门同事告诉我一句话,瞬间就通了: 正向导通,反向截止;整流防反,稳压发光。 今天就用最…...

云服务器购买怎么选?2026云服务器优惠与租赁指南

在AI创作、3D渲染、远程办公快速发展的今天,「云服务器购买」「云服务器租赁」已经成为越来越多个人和企业的刚需。但面对复杂的配置和价格体系,很多人都会问:👉 到底怎么选最划算? 👉 有没有长期稳定又有“…...

DBA_RECYCLEBIN purge指定日期前的表

SummaryHow to purge DBA_RECYCLBIN for objects older than x days/minutes? or do we have RECYCLEBIN RETENTION feature or truncate recyclebin ?--------------------------------------------------------------------------------------DBA_RECYCLEBIN has a column …...

AI 模型推理框架性能分析与对比

AI模型推理框架性能分析与对比 随着人工智能技术的快速发展,AI模型推理框架成为支撑各类应用落地的核心工具。无论是计算机视觉、自然语言处理还是推荐系统,高效的推理框架直接影响模型的响应速度、资源占用和部署成本。本文将从多个维度对比主流AI推理…...

Go语言的context.WithCancel取消信号传播与资源清理在分布式系统中的协调

Go语言的context.WithCancel取消信号传播与资源清理在分布式系统中的协调 在分布式系统中,任务的取消与资源清理是确保系统稳定性和高效性的关键挑战。Go语言通过context包提供了优雅的解决方案,尤其是context.WithCancel机制,能够实现跨组件…...

MxRadioRF2xx库:ARM Mbed平台RF2xx射频驱动开发指南

1. MxRadioRF2xx 库概述 MxRadioRF2xx 是一个专为 ARM Mbed OS 平台设计的 Atmel(现 Microchip)RF2xx 系列射频收发器驱动库。该库并非对底层寄存器操作的简单封装,而是面向嵌入式无线应用开发者的工程化抽象层,其核心目标是&…...

AIGC时代,程序员会被取代吗?我的看法与行动建议

AIGC时代,程序员会被取代吗?我的看法与行动建议 随着AI生成内容(AIGC)技术的迅猛发展,许多人开始担忧:程序员这一职业是否会被AI取代?从代码生成工具GitHub Copilot到对话式编程助手ChatGPT&am…...

深度学习中的优化器:原理与实践

深度学习中的优化器:原理与实践 一、背景与动机 在深度学习中,优化器是模型训练的核心组件,它决定了模型参数如何根据损失函数的梯度进行更新。选择合适的优化器对于模型的训练速度和最终性能至关重要。本文将深入探讨各种优化器的核心原理、…...

深度解析Internet Archive下载器:数字图书馆资源获取的完整方案

深度解析Internet Archive下载器:数字图书馆资源获取的完整方案 【免费下载链接】internet_archive_downloader A chrome/firefox extension that download books from Internet Archive(archive.org) and HathiTrust Digital Library (hathitrust.org) 项目地址:…...