Skip to content
  • AQS 原理详解:ReentrantLock 底下的那套排队框架

    学了 ReentrantLock、读写锁、SemaphoreCountDownLatch 之后,可能有过一个疑问:这一堆工具,底层是不是各写各的?不是,它们底下全是同一个东西——AQS(AbstractQueuedSynchronizer,抽象队列同步器)。JUC 里大半的同步工具,都是在这一个框架上搭出来的。这篇把它拆开看:state 是什么、队列怎么排、线程怎么挂起又怎么被唤醒。理解了 AQS,上面那一堆工具就不再是几个孤立的 API,而是同一套机制的不同用法。

    上游文章:《[ReentrantLock 详解](/ful

  • 读写锁详解:ReentrantReadWriteLock 与 StampedLock

    ReentrantLocksynchronized 有个共同点:同一时刻只允许一个线程进。可大量场景里,读和读之间根本不冲突——十个线程同时读一份配置、一个缓存被反复查询,互不干扰,凭什么排队?读写锁就是为"读多写少"准备的:读和读共享,只要有写就互斥。这篇梳理读写锁的规则、锁降级,以及 JDK 8 加的进阶版 StampedLock(乐观读,连读锁都可以不加)。

    锁的全景地图在《锁的分类与实现原理》,`R

  • ReentrantLock 详解:比 synchronized 多给了什么

    synchronized 日常够用了——简单、自动加锁释放,JDK 1.6 之后性能也优化得很好。但它有几个天生的限制:拿不到锁就一直傻等、等的时候不能被中断、所有线程抢锁不排队、也没有办法让线程"分拨"等待。这篇把 ReentrantLock 系统梳理一遍:它补齐了哪些能力、每个能力解决什么场景,以及什么时候其实还是 synchronized 更合适。

    这是"锁"系列的一篇。各种锁概念的全景(本地锁/分布式锁/悲观乐观锁)在《[锁的分类与实现原理](/software-architecture/design-ideas/lock-o

  • 工作台接口优化实战:12 次串行查询压垮一个首页

    这是一次真实接口优化的复盘。系统是一个固定资产管理系统,工作台是登录后的第一屏——今日统计、我的资产、待办审批、预警数字、最近操作,功能不复杂,但压测数据很难看:20 QPS 就饱和,P99 干到 1.7 秒

    这篇按当时的排查顺序写:先定位瓶颈在哪,再讲动了哪三刀,最后看数据。没有黑科技,全是朴素手段,但每一步的取舍值得说清楚——尤其是「为什么这个查询不能扔进异步线程」和「批量化引入的时序 bug」,都是踩过才知道的。


    一、先定位:别猜,数 SQL

    优化接口的第一原则:先搞清楚它到底干了多少事,而不是上来就加缓存

  • Testcontainers 详解

    集成测试最大的坑不是代码,是环境造假。H2 内存数据库号称能模拟 MySQL,但 ON DUPLICATE KEY UPDATEGROUP_CONCAT、JSON 字段、锁行为……这些 MySQL 方言它全跑不了。测试过了,一上真实环境就炸。

    Testcontainers 的思路很直接:测试时用 Docker 起一个真的 MySQL/Redis/RabbitMQ,测完自动销毁。测的就是真实组件的真实行为。

    本文是《[集成测试快速入门](/test-ops/integration/integration-test-qui

  • 一次真实的服务器压测实战

    上一节《JMeter 快速入门》讲了工具怎么用,这篇是实战记录:对一台部署在云服务器上的管理后台(前端 + 后端 API)做了一次完整压测——从定目标、设计场景、跑梯度,到从数据里把瓶颈挖出来。所有数据都是真实跑出来的,瓶颈发现的部分比“怎么压”更值得看。

    一、背景与压测目标

    被测系统:一台 2 核云服务器,nginx 托管前端静态资源,反向代理后面的 Java 后端(Spring Boot + MySQL)。日常访问没问题,但“没问题”不等于“知

  • 压测假绿排查:防重复提交拦截下的 QPS 陷阱

    上一篇《一次真实的服务器压测实战》的续章里,写接口的数据出现过一次反转:第一版脚本测出写接口 270 QPS、"快过所有读接口";修正方法重测后只剩 38 QPS,前后差了 7 倍。这篇把这次"数据打假"的完整过程单独成篇——从发现数字对不上,到翻源码定位防重逻辑,到设计实验验证拦截规律,最后修正压测方法拿到真实水位。压测数据里的"假绿"比压不动更危险:它不报错,只骗人

    一、问题:三组对不上的数字

    写接口压测(新增一条通知公告)跑完,把三份数据摆

  • Android 混淆规则文件 proguard-rules.pro 详解(keep 指令与 R8 工作流)

    release 包出问题,排查到最后基本都会翻到这个文件——proguard-rules.pro。规则写得对不对,直接决定线上会不会闪退。这个文件本身机制不复杂:R8 对代码做四件事——压缩、优化、混淆、预检,keep 规则就是告诉它「这几处别碰」。但「别碰」有四种说法,选错一种线上就崩。这篇把规则文件系统梳理一遍:它怎么被加载、keep 四兄弟的区别、什么必须 keep、出了事怎么用 mapping 反推。

    一、规则文件在构建里扮演什么角色

    它就放在 app/proguard-rules.pro,自己不干活——它只是 R8

  • IM 即时通讯系统架构分析与 Spring Boot 实现

    一、先看需求本质:服务端要“主动”找人

    IM,Instant Messaging,即时通讯——微信单聊、客服对话、App 里的系统通知,都属于这一类:消息要在“发出去”和“被看到”之间几乎无延迟地送达

    平时用微信,消息不丢、不重、一问一答顺序稳定,感觉理所当然。可真要自己动手做一个 IM(比如给产品加个客服聊天),把链路拆开才发现处处是坑:消息发出去了,对面可能没收到;超时重发,对面会收到两条一样的;走不同网络路径的消息,还可能后发的先到。

    这三个现象分别对应 IM 系统的三件核心事:不丢、不重、不乱序。这篇把 IM 系统

  • 缓存与数据库一致性:从 Cache Aside 到 binlog 订阅

    先看一个典型的缓存事故:用户改了头像,刷新好几遍还是旧头像。查缓存 TTL,60 秒早该过期了——最后发现是更新顺序出了问题:先删了缓存,数据库还没改完,另一个线程又把旧数据读回缓存。缓存和数据库的不一致,就是这么不经意间产生的。

    这篇把缓存一致性从最基础的 Cache Aside 讲到 binlog 订阅:为什么会出现不一致、延迟双删在防什么、Canal 怎么把缓存操作彻底解耦。代码按 Spring Boot 落地。


    一、先定基调:Cache Aside(旁路缓存)是基础

    先理清读写姿势,绝大多数不一致都是**姿