第十九章 · 三句话¶
九月二十五日,星期四,上午九点。
纪衡的消息在最上面:「十一点,三楼会议室,技术决策会。把对账模块的方案带上。」下面一条是张磊的:「十点,我过来找你。技术 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,为什么用独立消息服务不用本地事务表,为什么用最终一致性不用强一致性。
他写了两个小时,二千字,三部分。他写完了,发给易文。
他打开记事本,写一行:「方案第三版已写。已发易文。」
下午五点,易文的回复来了。
「方案看了。可以。周四用这个版本讲。」
这条回复用了三分钟。前两版她各看了一天。
「你知道你这次,跟上一次的区别在哪里吗。」
「知道。」
「哪里。」
「我这次写的不是技术方案。是问题和方法。」
「你学会了。」
陈稳没有回复。
他放下手机,打开记事本,在最后一行写:九月二十六日。易文说我学会了。但我不确定我学会了什么。我只知道,我今天写方案的时候,一直想着顾源说的那三句话。
他看了一遍,保存,关掉。
地铁上,何晚的消息。
「今天回来早。」
「嗯。」
「晚上想吃什么。」
「面。」
「你昨天说粥。」
「今天吃面。」
「好。」
车厢的灯白得刺眼。易文下午问他,你知道顾源为什么只说三句话吗。他说不知道。
他现在知道为什么了。这件事他没有跟易文说。
开门的声音传到厨房,何晚没有回头。
「回来了。」
「嗯。」
「面马上好。」
他换了鞋,直接到厨房门口,站在何晚身后。
何晚还是没有回头。水开了,面下进去,筷子搅一下,盖上,再开,加一碗冷水,再开,关火,捞出来,一勺酱油,一勺醋,一勺辣椒油。
面是热的,汤是辣的,他全部吃完。
何晚在对面:「你今天怎么了。」
「没什么。」
「你看起来又不一样了。」
「哪里不一样。」
「你今天回来的时候,没有站在那里发呆。你直接走到厨房门口了。」
这件事他自己没有注意到。她注意到了。
「你变了。」
「我不知道这是好还是不好。」
「我也不知道。」
何晚把碗收走。水声起来。
第三版方案两千字,三部分,第一部分只有一句话是问题,其余全是方法。
水声停了。她转过身,他又在身后。她擦干手,从他身边过去,拿起手机。这是今天第二次,也是这个星期第四次。
他没有拿手机。
裂缝还在。
他看了一会儿,说:「今天下午,我写方案的时候,一直想着顾源说的那三句话。我写一句,就想起一句。我写完了,发现我写的方案,跟以前不一样了。」
「哪里不一样。」
「以前我写的是,我做了什么,用了什么技术。今天我写的是,遇到了什么问题,用什么方法解决了。」
何晚没有说话。
「易文说,我学会了。」
「你学会了吗。」
「我不知道。」
「那你觉得呢。」
陈稳想了想:「我觉得,我还没学会。但我至少知道,我该学什么了。」
何晚起身进卧室,关上门。门锁咔嗒一声响,不是锁上了,是关上了,没有锁。
星期五晚上,对面那栋楼,那扇黑着的窗,还是黑的。
记事本最后一行:九月二十六日。何晚说我变了。她说我直接到了厨房门口。我今天学会了,说问题,不要说事实。这是顾源的方式。
他看了一遍,保存,关掉。
卧室的灯已经关了。他在客厅里又把方案第三版从头看了一遍。第二部分第三行有一个词写重了:「机制机制」。
他改掉,保存。这个版本下午已经发出去了,改的是本地这一份。
← 第十八章 这个人是谁 · 目录 · 第二十章 胃药 →