公众号旧文

为什么我敢随便Kill进程?——幂等与可重入,普通人也能用上的工程哲学

作者:胖子阅读 —

我有一个抓数据的脚本。

它并不稳定。 会因为网络、接口、代码自身、甚至一些我说不清楚的原因,随时中断。

但我从来不怕它断。

甚至,我还写了一个 bat,每隔一段时间,主动把它Kill掉,再重新启动。

听起来很离谱,但它已经稳定运行很久了。

原因只有两个词:

幂等 + 可重入

一、先说结论:我默认程序一定会死

很多人写程序时,潜意识里都有一个假设:

程序一旦开始,就应该顺顺利利跑到结束

但现实世界不是这样的:

  • 网络会抖
  • 进程会挂
  • 机器会重启
  • 脚本会卡死

中断不是异常,而是常态。

所以我从一开始就不追求不中断, 而是追求:

断了,也没关系

二、什么是幂等?

教科书里的定义很严谨,但工程上,其实一句话就够:

幂等:同一个操作,执行一次和执行一百次,结果是一样的

注意重点不是执行一次, 而是——执行很多次,也不会出事。

在工程世界里,这意味着什么?

我敢重试

三、不幂等的系统,重试就是灾难

举几个你一定见过的例子:

  • 每运行一次脚本,就往数据库插一条记录 → 重跑 = 重复数据
  • 接口超时重试,但每次都会扣钱 → 重试 = 多扣费
  • 一个大循环,中断了只能从头来 → 重跑 = 前功尽弃

在这种系统里:

重试不是补救,而是放大事故

于是你会发现,程序一旦卡住, 你连重启的勇气都没有。

四、我的做法:把任务拆成一个一个

我抓的数据大概有 1500 个对象。

我的处理方式是:

  • 一次只抓 一个
  • 抓完立刻标记完成
  • 再抓下一个
  • 再次运行时:

这意味着什么?

无论我运行多少次脚本, 最终结果都只会是: 这 1500 个对象,各被成功抓取一次。

重复运行 ≠ 重复结果。

这就是幂等。

五、幂等带来的工程特权

当你的操作是幂等的,你会突然发现:

  • 可以随便重启脚本
  • 可以断了就重跑
  • 可以失败就重试
  • 可以写非常粗糙但有效的守护程序

我甚至不需要精确判断现在跑到哪一步了。

因为:

多跑几次也没关系

六、再往前一步:什么是可重入?

如果说幂等解决的是:

重复执行会不会出事

那可重入解决的是:

中途被打断,还能不能继续

用人话说就是:

程序在任何时刻被杀掉,下次还能从一个合理的位置继续跑

七、不可重入的程序,活在理想世界

很多程序之所以脆,不是因为代码写得差, 而是因为它们假设:

  • 过程不会被打断
  • 状态一直在内存里
  • 必须一次跑完

于是:

  • 一断,全废
  • 一挂,从头来
  • 一出问题,只能人工干预

这种程序, 不是不努力,是设计上就不适合真实世界。

八、可重入的关键,不是技术,而是拆分

让我这个脚本能随时被杀的,不是高级技术,而是几个简单原则:

  • 把任务拆成最小独立单元
  • 每完成一个,就立刻落盘
  • 所有状态都能从外部恢复
  • 启动时先检查已经完成了什么

只要做到这些:

中断,就只是一次暂停

九、于是我敢写一个暴力但有效的守护脚本

因为幂等 + 可重入,我可以:

  • 不优雅退出
  • 不保存复杂状态
  • 不关心中断发生在哪
  • 定时Kill,随后拉起

我的守护脚本逻辑非常简单:

不管你在不在跑,我都Kill掉你,再把你拉起来

至于你上次跑到哪了?

你自己知道就行

十、真正稳定的系统,靠的不是不出错

很多人追求的是:

这个程序千万别崩

而我追求的是:

它崩了也没关系

这是两种完全不同的工程思维。

前者在赌运气, 后者在接受现实。

十一、总结一句话

  • 幂等,让你不怕重复
  • 可重入,让你不怕中断

当这两点同时成立时:

程序崩溃, 不再是事故, 而只是流程的一部分。