Latest articles

思维导图必须自己画:把被 AI 借走的脑子要回来

Posted on in Journal

最近用 AI 用得有点多,活儿照样交得出去,可心里那点"这事我真弄明白了"的踏实感,越来越薄。这篇想说清楚两件事:这种不安不是矫情,认知科学、哲学、心理学这些年正好也在吵这件事,吵出了些挺扎实的研究;以及我给自己定的几条规矩——思维导图必须自己画、每天留出不碰 AI 的时间、把纸笔拾起来、每天给 AI 挑刺——每一条背后都有能说清楚的理由。

Continue reading

GTD 配 Agent:流程图先焊死,LLM 只管节点里的判断

Posted on in Journal

翻出一张 2009 年用 FreeMind 画的 GTD 思维导图,方法论十七年没变,变的是终于可能有样东西能替我把它跑起来。但把整套方法论讲给 LLM 听、让它自由判断每条输入该怎么处理,大概率会乱。这篇把一张 GTD 工作流草图拆成判断、动作、调度三类节点,说清楚哪段该交给 LLM、哪段该交给 Tools/Skills、哪段根本不该用智能。

Continue reading

简单之美:Lua Table

Posted on in Tech

Lua 不区分数组、哈希、集合,只给了一个 table——这不是能力不够,是故意的。本文从 table 的两副面孔讲到元表(metatable),讲到用元表搭 OO,再讲到 LuaJIT 和 OpenResty 怎么给 table 加性能后门,最后落到 OpenResty 里真正跨进程的那张表:共享内存字典 ngx.shared.DICT。附带可以直接照抄的 cheat sheet。

Continue reading

Overhiring、Overqualified:中年技术人求职路上绕不开的两个词

Posted on in Journal

这半年听几个同龄朋友聊起求职,拒信理由翻来覆去就两条——"我们现在 overhiring,先缓缓"和"你 overqualified 了"。两条理由合在一起是个死循环:岗位说不缺人,你自己又被嫌"太够格"。拆开看,这两个词背后各有一句没说出口的潜台词;往大了看,是内需、AI、外企收缩叠在一起的大背景;落到个人,是过去吃饭的本事——写代码、写文档、全栈多语言——正从稀缺品变成大路货。这篇想说清楚这个死循环怎么破,以及我自己想通的三件事。

Continue reading

用 SIPp 给 FreeSWITCH 做测试:注册、呼入、呼出、桥接、会议

Posted on in Tech

给 FreeSWITCH 写功能是一回事,证明它在五百路并发下还注册得上、接得通、桥得稳,是另一回事。SIPp 就是干这个的——用一份 XML 脚本模拟成千上万个话机,把注册、呼入、呼出、桥接、会议这五类场景逐个压过去。这篇给出每类场景可直接改地址就能跑的脚本、命令行和对应的 FreeSWITCH 配置,以及几个新手必踩的坑:认证两段式、CSV 账号注入、带媒体的 INVITE 要放 PCAP、以及为什么 bridge 测试得起两个 SIPp。

Continue reading

蘑菇定律:把自己埋进土里的那段日子,才是养分

Posted on in Journal

三年换了两个公司、三个团队,照理说早该习惯了,可每回进新团队,还是问啥啥不知、做啥啥不会,心里那句“我是不是真不行了”总压不下去。蘑菇被养在黑暗里靠养分长根——职场的“蘑菇定律”说的就是这个蛰伏期:先把自己埋进土里,把旧的倒空,根扎稳了,才谈得上出土。

Continue reading

用罗伯特定理来驱除心魔

Posted on in Journal

职场里最让人累的不是加班,而是被自己的心魔拖垮:一次失败没站住,接二连三就没心情了。罗伯特定理把这层窗户纸捅破——没有人因倒下或沮丧而失败,只有一直倒下或一直消极才会失败。本文先讲清它的真实出处(卡维特·罗伯特其实是演说家,不是史学家),再拆解那些流传甚广却常被改写的“失败名言”,最后落到几个能立刻做的小动作。

Continue reading

AI 编程的奥卡姆剃刀原则

Posted on in Journal

AI 写代码不怕麻烦,这是它最大的优点;可麻烦不归它承受,这是它最大的毛病。奥卡姆剃刀说“如无必要,勿增实体”——放到 AI 编程里,要砍的不是代码行数,是你三年后要背的维护工作量。对 FreeSWITCH、OpenResty、OpenSIPS 这类后端服务尤其如此:前人把引擎和脚本层分开,就是替你划好了那条界线,宁可多写几行 XML/Lua/路由脚本,也别轻易让 AI 给你生一个新模块。文末附三段可直接复制的 Prompt:方案阶段数实体、代码阶段做减法、规则文件里常驻约束。

Continue reading

抖动缓冲:同一条网络轨迹下,三种策略谁更好?

Posted on in Tech

打电话时对方声音断断续续,是网络丢包;但还有一种更隐蔽的情况——包都到了,却因为到达时间不齐,播放端缺了当前该播的那一小段。抖动缓冲就是为这件事生的:网络里的包到达时间不规律,播放端却必须每 10ms 吐出一块音频。缓冲浅了会卡顿,深了又增加延迟。我把小固定、大固定和自适应三种策略放在同一条网络轨迹、同一段真人语音下跑了对比实验,用数据说话:没有哪种永远最好,自适应是在延迟与连续之间动态找平衡——它多半比小固定稳、比大固定快,但真遇到突然的抖动峰值,它照样会卡那么一下。整套实验我开源成了一个小项目 ajb-demo,代码在 GitHub 上,读者可以拉下来自己跑、自己听、自己调参数验证——让数据替你选该用哪种策略。

Continue reading

如何避免代码里的霰弹式修改

Posted on in Tech

一个业务规则改一下,却要同时动十几个文件,还经常漏改一两处,导致同一条规则在系统不同地方表现不一致——这就是霰弹式修改(Shotgun Surgery)。这篇讲清楚它的现象、根因和治理办法:根因不是代码写得多,而是一个概念的知识被复制到了很多地方;治理的目标不是"代码只出现一次",而是"一个变化原因只有一个主要修改点"。文中给出判断标准(因为同一个业务原因而变化才抽象)、Change Map 排查法、从 N→1 的重构路径、测试保护步骤,以及一份能照着念的 Code Review 五问。最后单独讲当霰弹跨越多个服务、多个仓库时该怎么办——你失去了"一次改完"的能力,治理思路要从"收成一个修改点"转成"建一个权威来源 + 兼容地滚动"。对后端和通信系统工程师尤其适用:很多霰弹式修改,本质是领域逻辑泄漏到了 Handler 和 Adapter 层。

Continue reading

Start small, stay curious

Posted on in Journal

岁数渐长没关系,别丢掉好奇心和尝试的勇气。从乔布斯的“Stay hungry. Stay foolish.”说起,从大处着眼,从小处着手,不贪大求全,日拱一卒。

Continue reading

OpenResty 能做什么:把 Nginx 变成可编程服务器

Posted on in Tech

你每天刷的网站里,很可能有一层流量是从 OpenResty 过的——Netcraft 2026 年 7 月的统计里,它在全球 Web 服务器里排第四,背后还站着 Kong、Apache APISIX 这些主流 API 网关。OpenResty 不是另一个服务器,而是一台能用 Lua 写逻辑的 Nginx:把业务代码塞进请求处理的那条流水线里,用非阻塞的方式访问 Redis、MySQL、上游服务,单机就能扛住几万到几十万连接。本文讲清楚它能做什么、架构怎么运转、优劣势在哪、有哪些成功案例和最佳实践,以及最容易让人栽跟头的那几个坑——其中最致命的一条,一行代码就能让性能掉 15 倍。

Continue reading

AI 生成的知识库,到底怎么保证质量

Posted on in AI

我写过几个把代码库和文档自动变成知识库的 skill,试过各种自动校验的路子,最后还是得人来审。这篇把我踩过的坑、业界的做法、能用的工具和几篇值得读的论文串起来,结论很朴素:没有银弹,人审是必要环节,但可以把人审成本压到最低。

Continue reading

Lua 编程三十个常见错误:初级、中级、高级,逐个拆解

Posted on in Tech

解释性脚本语言的坑大多是共通的——动态类型、隐式转换、宽松的作用域、还有"够用就好"的语法。Lua 以小巧著称,一门语言只有二十来个关键字,却屡屡在游戏脚本、Nginx/OpenResty 配置、Redis 事务、各种嵌入式场景里让人栽跟头。本文把高频翻车整理成三十个常见错误,按初级、中级、高级三层排开,每一条都配了可以自己跑的代码实例。大多数坑不是语法问题,而是 Lua 的"抠门"设计——数组从 1 开始、nil 不算元素、表比较的是引用、连整数除法都是后来才补的——这些设计单独看都合理,凑到一起就成了连环陷阱。

Continue reading

PHP2Shell 漏洞:PHP 紧急发布两个高危 RCE 补丁,今天就要动手

Posted on in Tech

PHP 在 2026 年 10 月 21 日紧急发布补丁,修复两个可导致未认证远程代码执行(RCE)的高危漏洞,统称 PHP2Shell,对应 CVE-2026-109618 和 CVE-2026-109619,CVSS v4.0 评分高达 9.2。漏洞位于 PHP 核心的内存管理与错误处理路径,影响几乎所有 PHP 版本,攻击可以不经过任何应用代码直接打到服务器。本文讲清楚漏洞是什么、风险有多高、哪些版本受影响,并给出今天就能做的处置清单——以及用 Docker 跑 WordPress 时,为什么"光换镜像不重建容器"能漏掉这次修复,该怎么正确升级。

Continue reading

别让经验把你坑了:老程序员的"去芜存菁"

Posted on in Journal

经验是把双刃剑。它让你快,也让你懒得求证。我在一个 Redis Cluster 的场景里栽过:想当然以为"一个 master 带它的副本都挂了,落在其他存活 master 上的 key 照样能读",据此写了一堆代码去算哪些 key 落在哪个 master、再逐一验证——结果因为 cluster-require-full-coverage 默认是 yes,只要有一段 slot 没人管,整个集群就停摆,所有 key 全读不了,那堆代码白写了。这篇讲清楚经验主义的坑在哪、为什么老手更容易踩,以及怎么给自己的经验库做一次"去芜存菁",并给一张随手能用的核对清单。

Continue reading

把知识库建成一座图书馆:DDD 的思想、AI 的建法,和 RAG 到 GraphRAG 的省钱之路

Posted on in Tech

很多团队把知识库建成了一个超大的文件仓库——文档都在,但谁也找不着、AI 也查不准。问题不在存了多少,在有没有"编目"。本文把知识库当成一座图书馆来讲:DDD 给的是图书馆的分类法(领域、上下文、实体、服务),决定书怎么摆、怎么被找到;AI 既是整理书架的馆员,也是来借书的读者,两个角色得分开对待。检索这头,朴素 RAG 像只会按书名模糊搜的检索台,能答"第几页讲了什么",答不了"这个主题整体在说什么";GraphRAG 用知识图谱加社区摘要补上了这块,但建图太贵;LazyGraphRAG 把建图挪到查询时,索引成本砍到只有全量 GraphRAG 的千分之一。一条主线串起来:知识库的价值不在存量,在可检索性,而可检索性来自结构。

Continue reading

一个 Slot 挂了,为什么整个 Redis Cluster 都不可用?讲透 cluster-require-full-coverage

Posted on in Tech

很多人以为 cluster-require-full-coverage yes 的意思是“一个 Redis 节点挂了整个集群就挂”。这是个误会。它真正管的不是节点死活,而是 16384 个 slot 是否被完整覆盖。节点挂了集群还活着,靠的是副本 failover,不是这个配置。本文从一次线上排查讲起,配两张图、一段真实源码(clusterUpdateState),把 slot 覆盖、集群状态、failover、以及它和 cluster-allow-reads-when-down 的分工一次讲清楚,最后给一张排查清单。

Continue reading

人到中年,最可贵的领悟是克制

Posted on in Journal

年轻时觉得克制是软弱,是认输。人到中年才慢慢明白,克制不是压抑自己,而是看清了边界之后的选择:对身体,对别人,对信念,对那个不甘平凡的自己。写给同样在跟欲望较劲的中年人。

Continue reading

不用碰撞:读懂一段 Lua,O(1) 造出落在指定 Slot 的 Redis Key

Posted on in Tech

把 Redis Cluster 想成一个有 16384 个抽屉的柜子:给数据起个名字,柜子算出它进几号抽屉。我们要反着来——给定抽屉号,倒推一个能落进去的名字。很多人靠瞎试,又慢又碰运气。其实这里的算法说穿了只是异或:每个“开关”对结果的影响固定、还能叠加,于是倒推就成了一道凑开关的小学游戏,一步解出。本文用“抽屉、灯开关、调音台”这些大白话,配四张图,带没学过高数、刚入门编程的人逐段读懂一段真实的 Lua 实现,代码我逐个抽屉验证过。

Continue reading