跳转至

第十九章 · 三句话

九月二十五日,星期四,上午九点。

纪衡的消息在最上面:「十一点,三楼会议室,技术决策会。把对账模块的方案带上。」下面一条是张磊的:「十点,我过来找你。技术 VP 让我问你几个问题。」

对账模块重构方案在草稿箱里躺了一天,三千字,五部分,没发。陈稳改了两个错别字,标题改了一遍,又改回来。连接池使用率百分之四十一。

上午十点,张磊站在工位旁边,手里一个笔记本。

「方便聊一下?」

楼梯间的窗户开着,风有点凉。

张磊打开笔记本,翻到一页:「技术 VP 让我联系你,数据治理的底层对齐方案,可以推广到其他业务线。你的方案,依赖哪些数据源,用了什么技术栈。」

「三个表,营销结算订单表、支付表、退款表。MySQL,InnoDB。」

「视图用的什么。」

「SQL。标准 SQL。」

「没有用中间件?」

「没有。当前数据量不需要。翻十倍需要中间表。」

张磊在笔记本上写了几笔,合上:「好。我回去整理一下,周五出推广计划。」

「好。」

张磊走了。十点三十五分。方案的第三部分写着工作量:两个月,一个人,不需要额外资源。这一行是他昨天加的,加完没有跟纪衡确认过。

会议室里坐了四个人。

纪衡坐在最前面,旁边是技术 VP,灰色衬衫,戴眼镜。对面坐了一个人,五十多岁,头发花白,深蓝色夹克,面前没有电脑,没有笔记本。

顾源。

陈稳的位置在侧边,靠墙。

纪衡说:「今天讨论一件事。结算系统对账模块重构,要不要做,怎么做,谁来做。你那个方案,带了吗。」

「带了。」

「讲一下。」

陈稳讲了十五分钟:背景,当前对账模块基于逐笔比对,T+1,无法覆盖当日异常。方案,引入事件驱动、消息队列、增量比对,T+0。工作量,两个月,一个人,不需要额外资源。风险,数据一致性、消息队列可靠性、事件顺序。

他讲完了,会议室里安静了几秒。

技术 VP 问:「数据一致性怎么保证。」

「事务消息。本地事务表加消息表,写入同一事务。消费端做幂等。」

「消息队列选型。」

「Kafka。公司内部已有集群。」

「Kafka 可靠性。」

「ACK 设 all,min.insync.replicas 设 2,重试次数设 3。」

技术 VP 在笔记本上写了一个数字,写完把笔帽扣上。

然后顾源开口了。

「事务消息,本地事务表和消息表,放在同一个数据库里?」

陈稳愣了一下。

「是的。」

「如果这个数据库挂了,消息还能发出去吗。」

事务消息这一节是上周易文给他划掉重写的,重写之后只剩四行。这四行里没有一句写到数据库不可用。

「你的方案,依赖同一个数据库的同一个事务。如果数据库不可用,消息发不出去,对账模块也跑不了。用一个单体依赖,解一个分布式问题。」

方案里那一节叫「风险」,写了三条:数据一致性、消息队列可靠性、事件顺序。没有第四条。

会议室里安静了几秒。

技术 VP 说:「单体依赖的问题,怎么解决。」

陈稳想了想:「我不知道。」

纪衡说:「回去想。下周同样的时间,同样的会议室,再讲一遍。」

「好。」

会议散了。技术 VP 先出门,纪衡跟在后面。顾源最后一个,没有回头。他面前的桌子还是空的,一张纸都没有。

陈稳坐在椅子上,没有动。

他想起他刚才讲了十五分钟,讲了事务消息,讲了本地事务表,讲了 Kafka 的 ACK 和 min.insync.replicas。他以为他讲得很清楚。他没想到的是——如果那个数据库挂了,怎么办。

他坐了很久。

易文的消息来了。

「会开完了?」

「开完了。」

「怎么样。」

「顾源说我的方案有单体依赖问题。」

「他说了什么。」

「他说,事务消息的本地事务表和消息表放在同一个数据库,如果这个数据库挂了,消息还能发出去吗。」

「你怎么说的。」

「我没说话。」

「然后呢。」

「技术 VP 问我怎么解决。我说不知道。」

「纪衡怎么说。」

「回去想。下周重新讲。」

「你知道顾源在会议上说了几句话吗。」

「三句。」

「哪三句。」

「你的事务消息,本地事务表和消息表,放在同一个数据库里。如果这个数据库挂了,你的消息还能发出去吗。你的方案,依赖的是同一个数据库的同一个事务。」

「你记住了吗。」

「记住了。」

「那你现在知道问题在哪了。」

「知道。」

「回去改。」

「好。」

陈稳放下手机,打开记事本,写了一段话:「对账模块重构方案。问题:事务消息的本地事务表和消息表在同一数据库,单体依赖。解决方案:引入独立消息服务,独立数据库存储消息表。或者,改用外部消息队列,不依赖本地事务表。」

他看了一遍,保存,关掉。

他打开 IDE,对账模块的代码,看到之前加的 TODO 注释,看了一遍,然后开始写方案第二版。他改了数据一致性部分,把事务消息改为独立消息服务,消息表迁移到独立数据库,跨数据库事务通过最终一致性保证。

他写了两个小时,写完,保存,没有发。

下午两点,张磊的消息:「推广计划整理好了。明天上午十点,过来确认。」

「好。」

「另外,技术 VP 让我问一下,对账模块重构的方案,什么时候能出来。」

「下周四。」

「好。」

陈稳放下手机,打开记事本,在最后一行写:今天看到了另一种不说话的人。

他看了一遍,保存,关掉。

晚上七点,食堂打的饭菜是凉的,他吃了一半,倒掉。

他打开电脑,打开独立消息服务设计文档,写了一个小时,八百字,分三部分:消息表结构、消息服务接口、跨数据库一致性保证。他写了四个接口:发送消息、查询消息状态、重试消息、清理过期消息。每个接口写了入参、出参、幂等保证、异常处理。

文档保存了,没有发。地铁上他才看到何晚的消息。

「今天加班?」

「嗯。」

「几点回来。」

「现在。」

「好。我煮了粥。」

「好。」

他想起顾源说话的时候,没有看他,没有看任何人,看着窗外。声音不大,不快,不高。说完之后,会议室里安静了几秒。顾源面前那张桌子,从头到尾是空的。

他想起他以前也是这样说话的——短,不多,说完了就闭嘴。但他说话的时候,没有人听。顾源说话的时候,所有人都听到了。

粥在桌上,加了红枣和莲子,甜的。他全部吃完。

何晚在对面:「今天怎么样。」

「今天开了一个会。我讲了一个方案。有一个人说了三句话,我答不上来。」

「什么人。」

「架构组的。顾源。」

「他说了什么。」

「他说我的方案有单体依赖问题。如果数据库挂了,方案就失效了。」

「那你怎么办。」

「回去改。」

何晚把碗收走。水声起来的时候,陈稳还坐在桌前。那份八百字四个接口的文档,明天要发给易文,易文会说这个地方不对,那个地方要改。

水声停了。何晚转过身,他就在她身后。她没有惊讶。

「怎么了。」

「没什么。」

「你最近总是站在我身后。」

「我不知道。」

何晚擦干手,从他身边过去,拿起手机。这句「我不知道」,三天里他说过两次。

易文的消息在客厅亮起来。

「明天下午两点,二号楼,数据治理项目。你过来,教你一个东西。」

「什么。」

「来了就知道了。」

天花板上的裂缝还在,从角落延伸到中间,物业说不影响结构。

顾源那句话是:如果这个数据库挂了,你的消息还能发出去吗。

他写方案的时候,从来没有想过这个问题。他写事务消息,写本地事务表和消息表,写 Kafka 的 ACK 和 min.insync.replicas,他以为他什么都想到了。三千字里有三条风险,没有第四条。

他闭上眼睛。

何晚的声音从旁边传来:「明天早上想吃什么。」

「粥。」

「还是粥。」

「嗯。」

「明天晚上回来吃饭吗。」

「回来。」

「好。」

卧室门关上,门锁咔嗒一声响,不是锁上了,是关上了,没有锁。

星期四晚上,对面那栋楼,那扇黑着的窗,还是黑的。

记事本最后一行:九月二十五日。顾源说了三句话。我答不上来。我回去改了。

他看了一遍,保存,关掉。

他以前也是这样说话的。但他说话的时候,没有人听。

这一条他没有写进记事本。

星期五,上午九点。

张磊的消息:「十点,我过来。方便吗。」

「方便。」

连接池使用率百分之四十。独立消息服务设计文档改了一行,消息重试的最大次数从 3 改成 5,保存。

上午十点,张磊递过来一个笔记本。

三页,钢笔字,工整。第一页是背景,第二页是推广方案,分三步:数据平台组内部推广、两条业务线试点、全公司推广。第三页是时间节点,第一步两周,第二步一个月,第三步两个月。

陈稳看完,把笔记本还回去:「可以。」

「有什么补充的吗。」

「试点业务线,建议选数据量小的。出了错,影响小。」

张磊在笔记本上写了一笔。

「全公司推广之前,做一次培训,写一份文档,把方法论讲清楚。不然推广了,别人看不懂。」

张磊又写了一笔:「好。我加进去。谢谢。」

「不客气。」

张磊走了。陈稳打开记事本,写了一行:张磊的推广计划,三页,钢笔字,工整。

他看了一遍,关掉,继续看代码。

下午两点,二号楼,数据治理项目的临时会议室。易文的屏幕上是 SQL 查询结果,三十七行。

「来了。坐。」

易文的眼睛没有离开屏幕:「张磊的推广计划,你看了。」

「看了。」

「觉得怎么样。」

「可以。三页,内容完整,时间节点合理。」

「哪里不行。」

「缺少风险预案。如果试点业务线出了问题,怎么办。」

「你说了吗。」

「说了。他加上去了。」

易文没有说话,继续看着屏幕。过了一会儿,她说:「你知道顾源为什么只说三句话吗。」

陈稳愣了一下:「不知道。」

「因为他说完三句话,就不需要再说了。他说的话,别人记住了。你说了十五分钟,别人记住了几句话。」

他讲了十五分钟,三千字,五部分。技术 VP 只在笔记本上写了一个数字。

「你记住顾源说了什么吗。」

「记住了。」

「你说一遍。」

「你的事务消息,本地事务表和消息表,放在同一个数据库里。如果这个数据库挂了,你的消息还能发出去吗。你的方案,依赖的是同一个数据库的同一个事务。」

「你怎么记住的。」

「他说的。」

「不是他说的。是你记住的。你记住,是因为他的话,每一句都指向一个问题。你的话,每一句都指向一个事实。事实没有用,问题才有用。」

这句话跟纪衡三个月前说的那句不一样。纪衡说的是,把事情做完,别的不用管。

「你写方案的时候,不要写'我做了什么',要写'你遇到了什么问题,我用什么方法解决了它'。不要写'我用了什么技术栈',要写'为什么用这个,不用那个'。不要写'我做了多少',要写'我解决了什么'。」

他记事本里有四十一条,每一条都是「我做了什么」。

「你把方案改一遍,按这个逻辑。改完了给我看。」

「好。」

门口。他停下来。

「易文。」

「嗯。」

「你今天说的,跟顾源说的,是一回事吗。」

易文转过头,看着他:「你知道了?」

「知道了什么。」

「问题比事实有用。」

易文看着他,过了一会儿:「你回去吧。」

一号楼的新文件是空的。

他写了方案第三版。他没有写他做了什么,没有写他用了什么技术栈。他写了一个问题:结算系统对账异常发现时间较长,当前为 T+1,无法覆盖当日异常。

然后他写了一个方法:引入事件驱动和增量比对机制,将时间窗口缩短至 T+0。

然后他写了技术选型:为什么用 Kafka 不用 RabbitMQ,为什么用独立消息服务不用本地事务表,为什么用最终一致性不用强一致性。

他写了两个小时,二千字,三部分。他写完了,发给易文。

他打开记事本,写一行:「方案第三版已写。已发易文。」

下午五点,易文的回复来了。

「方案看了。可以。周四用这个版本讲。」

这条回复用了三分钟。前两版她各看了一天。

「你知道你这次,跟上一次的区别在哪里吗。」

「知道。」

「哪里。」

「我这次写的不是技术方案。是问题和方法。」

「你学会了。」

陈稳没有回复。

他放下手机,打开记事本,在最后一行写:九月二十六日。易文说我学会了。但我不确定我学会了什么。我只知道,我今天写方案的时候,一直想着顾源说的那三句话。

他看了一遍,保存,关掉。

地铁上,何晚的消息。

「今天回来早。」

「嗯。」

「晚上想吃什么。」

「面。」

「你昨天说粥。」

「今天吃面。」

「好。」

车厢的灯白得刺眼。易文下午问他,你知道顾源为什么只说三句话吗。他说不知道。

他现在知道为什么了。这件事他没有跟易文说。

开门的声音传到厨房,何晚没有回头。

「回来了。」

「嗯。」

「面马上好。」

他换了鞋,直接到厨房门口,站在何晚身后。

何晚还是没有回头。水开了,面下进去,筷子搅一下,盖上,再开,加一碗冷水,再开,关火,捞出来,一勺酱油,一勺醋,一勺辣椒油。

面是热的,汤是辣的,他全部吃完。

何晚在对面:「你今天怎么了。」

「没什么。」

「你看起来又不一样了。」

「哪里不一样。」

「你今天回来的时候,没有站在那里发呆。你直接走到厨房门口了。」

这件事他自己没有注意到。她注意到了。

「你变了。」

「我不知道这是好还是不好。」

「我也不知道。」

何晚把碗收走。水声起来。

第三版方案两千字,三部分,第一部分只有一句话是问题,其余全是方法。

水声停了。她转过身,他又在身后。她擦干手,从他身边过去,拿起手机。这是今天第二次,也是这个星期第四次。

他没有拿手机。

裂缝还在。

他看了一会儿,说:「今天下午,我写方案的时候,一直想着顾源说的那三句话。我写一句,就想起一句。我写完了,发现我写的方案,跟以前不一样了。」

「哪里不一样。」

「以前我写的是,我做了什么,用了什么技术。今天我写的是,遇到了什么问题,用什么方法解决了。」

何晚没有说话。

「易文说,我学会了。」

「你学会了吗。」

「我不知道。」

「那你觉得呢。」

陈稳想了想:「我觉得,我还没学会。但我至少知道,我该学什么了。」

何晚起身进卧室,关上门。门锁咔嗒一声响,不是锁上了,是关上了,没有锁。

星期五晚上,对面那栋楼,那扇黑着的窗,还是黑的。

记事本最后一行:九月二十六日。何晚说我变了。她说我直接到了厨房门口。我今天学会了,说问题,不要说事实。这是顾源的方式。

他看了一遍,保存,关掉。

卧室的灯已经关了。他在客厅里又把方案第三版从头看了一遍。第二部分第三行有一个词写重了:「机制机制」。

他改掉,保存。这个版本下午已经发出去了,改的是本地这一份。


← 第十八章 这个人是谁 · 目录 · 第二十章 胃药 →