公众号旧文
为什么我敢随便Kill进程?——幂等与可重入,普通人也能用上的工程哲学
我有一个抓数据的脚本。
它并不稳定。 会因为网络、接口、代码自身、甚至一些我说不清楚的原因,随时中断。
但我从来不怕它断。
甚至,我还写了一个 bat,每隔一段时间,主动把它Kill掉,再重新启动。
听起来很离谱,但它已经稳定运行很久了。
原因只有两个词:
幂等 + 可重入
一、先说结论:我默认程序一定会死
很多人写程序时,潜意识里都有一个假设:
程序一旦开始,就应该顺顺利利跑到结束
但现实世界不是这样的:
- 网络会抖
- 进程会挂
- 机器会重启
- 脚本会卡死
中断不是异常,而是常态。
所以我从一开始就不追求不中断, 而是追求:
断了,也没关系
二、什么是幂等?
教科书里的定义很严谨,但工程上,其实一句话就够:
幂等:同一个操作,执行一次和执行一百次,结果是一样的
注意重点不是执行一次, 而是——执行很多次,也不会出事。
在工程世界里,这意味着什么?
我敢重试
三、不幂等的系统,重试就是灾难
举几个你一定见过的例子:
- 每运行一次脚本,就往数据库插一条记录 → 重跑 = 重复数据
- 接口超时重试,但每次都会扣钱 → 重试 = 多扣费
- 一个大循环,中断了只能从头来 → 重跑 = 前功尽弃
在这种系统里:
重试不是补救,而是放大事故
于是你会发现,程序一旦卡住, 你连重启的勇气都没有。
四、我的做法:把任务拆成一个一个
我抓的数据大概有 1500 个对象。
我的处理方式是:
- 一次只抓 一个
- 抓完立刻标记完成
- 再抓下一个
- 再次运行时:
这意味着什么?
无论我运行多少次脚本, 最终结果都只会是: 这 1500 个对象,各被成功抓取一次。
重复运行 ≠ 重复结果。
这就是幂等。
五、幂等带来的工程特权
当你的操作是幂等的,你会突然发现:
- 可以随便重启脚本
- 可以断了就重跑
- 可以失败就重试
- 可以写非常粗糙但有效的守护程序
我甚至不需要精确判断现在跑到哪一步了。
因为:
多跑几次也没关系
六、再往前一步:什么是可重入?
如果说幂等解决的是:
重复执行会不会出事
那可重入解决的是:
中途被打断,还能不能继续
用人话说就是:
程序在任何时刻被杀掉,下次还能从一个合理的位置继续跑
七、不可重入的程序,活在理想世界
很多程序之所以脆,不是因为代码写得差, 而是因为它们假设:
- 过程不会被打断
- 状态一直在内存里
- 必须一次跑完
于是:
- 一断,全废
- 一挂,从头来
- 一出问题,只能人工干预
这种程序, 不是不努力,是设计上就不适合真实世界。
八、可重入的关键,不是技术,而是拆分
让我这个脚本能随时被杀的,不是高级技术,而是几个简单原则:
- 把任务拆成最小独立单元
- 每完成一个,就立刻落盘
- 所有状态都能从外部恢复
- 启动时先检查已经完成了什么
只要做到这些:
中断,就只是一次暂停
九、于是我敢写一个暴力但有效的守护脚本
因为幂等 + 可重入,我可以:
- 不优雅退出
- 不保存复杂状态
- 不关心中断发生在哪
- 定时Kill,随后拉起
我的守护脚本逻辑非常简单:
不管你在不在跑,我都Kill掉你,再把你拉起来
至于你上次跑到哪了?
你自己知道就行
十、真正稳定的系统,靠的不是不出错
很多人追求的是:
这个程序千万别崩
而我追求的是:
它崩了也没关系
这是两种完全不同的工程思维。
前者在赌运气, 后者在接受现实。
十一、总结一句话
- 幂等,让你不怕重复
- 可重入,让你不怕中断
当这两点同时成立时:
程序崩溃, 不再是事故, 而只是流程的一部分。