“所以我们现在有共识了吗?”她问。声音比刚才更轻了,轻到像是在问一个她已经知道答案的问题。但她还是想听他说出来。就像一个已经收到ACK的节点,还是会定期发送心跳——不是因为不信任,是因为确认本身就是一种信任。
裴衍之看著她,嘴角扬起来了。不是那种克制的、理性的、成年人的微笑,是那种从心底里涌上来的、压不住的、想要跟她一起分享的笑。他笑起来的时候眼睛会瞇成一条缝,眼角会挤出细细的纹路,鼻子会皱一下,嘴角会歪向一边。他笑得不好看。但她觉得很好看。
“我们一直有共识。”他说,“只是你之前没发现。”
程司白看著他,看了大概三秒。这三秒里背景音乐换了一首,还是钢琴曲,比之前那首稍微快一些,音符之间的间隔更短,像一段正在加速的节奏。她的心跳没有加速,它稳定在一个频率上,不快不慢,和他的心跳同频。不是刻意的,是自动的。从某一天开始就是这样了,她不知道是哪一天,也许是咖啡馆的那个晚上,也许是电梯里的那个晚上,也许更早,早到她还没有意识到的时候。但它在。一直在。
她笑了。
不是嘴角动一下的那种,是真的笑了。笑容从她的眼睛里开始,蔓延到脸颊,蔓延到嘴角,蔓延到整个脸上。她笑得不好看,眼睛瞇成了一条缝,鼻子皱了一下,嘴唇因为笑得太用力而有点疼。但她没有停下来。这是她第一次在书里笑。不是微笑,不是浅笑,不是那种克制地、礼貌地、不露出任何破绽的笑。是那种从心底里涌上来的、压不住的、想要跟他一起分享的笑。
她笑的时候眼睛里有光。那光是暖的,不是窗外阳光照进来的那种暖,是另一种。是她在电梯里说“我留下”的时候有的那种,是她在会议室里说“谢谢你”的时候有的那种,是她在巷子里差一点把那句话说完的时候有的那种。那种光一直在她眼睛里,只是以前她把它压在水面下,压到看不见,压到她自己都以为没有了。但它在。一直在。
“裴衍之,你的比喻真的很烂。”她说。声音里带著笑,带著那种从心底里涌上来的、压不住的、想要跟他一起分享的笑。每一个字都在笑,“共识”“节点”“优雅退出”,这些词从她嘴里说出来的时候,不再是技术文档里的术语了。它们变成了另一种东西,一种只有他们两个人能听懂的语言。
裴衍之看著她笑,他也笑了。两个人坐在咖啡馆的卡座里,对著彼此笑。桌上放著一台没在写代码的电脑,一本没在读的论文,两杯没喝完的咖啡。阳光照在杯壁上,照在键盘上,照在两个人之间那二十公分的距离上。那二十公分里有风,有阳光,有空气中飘浮的灰尘,有钢琴曲的音符。但它们都在那里,没有谁要越过那二十公分,没有谁要把那二十公分填满。因为不需要。他们已经连接了。不是通过距离,是通过共识。一个不需要证明的、不需要测试的、不需要等待逾时重传的共识。它在三年前就达成了,只是花了很长时间才确认。
“但你看懂了。”他说。
程司白没有否认。她低下头,看著桌上那篇论文,第四页,第三段。她读了三遍的那个段落。她现在知道为什么读了三遍都没有读进去了——不是因为太难,是因为她在等。等一个她不需要读论文就能得到的答案。那个答案不在论文里,在旁边。在她旁边二十公分的地方,在一双正在笑的眼睛里,在一段不需要校准就能同步的心跳里。那个答案很简单——信任不是被证明的,是被选择的。你不需要证明一个人不会离开,你只需要选择相信他不会。你不需要证明一段关系不会失败,你只需要选择参与它。你不需要证明两个人比一个人更好,你只需要选择试试看。
她选择了。
窗外是城市的灯光。不是晚上的那种亮,是下午的那种。阳光照在对面写字楼的玻璃幕墙上,反射出一片金色的光。那片光照进咖啡馆,照在两个人的身上,把他们的影子投在身后的墙上——两个影子靠在一起,肩膀重叠,分不清哪个是谁的。咖啡馆里很安静。背景音乐换了一首,还是钢琴曲,很轻,轻到像一个人在很远的地方弹奏,音符飘过来的时候已经散了一半,只剩下一些断断续续的轮廓。吧台后面有人在洗杯子,水龙头的声音哗哗地响,和钢琴声混在一起,变成一种她说不清楚的白噪音。不是那种空调的、单调的、没有温度的白噪音,是另一种。是有人在的白噪音。是有人在旁边翻动书页的声音,是有人在键盘上敲击的声音,是有人在二十公分的地方呼吸的声音。这些声音很小,小到如果你不在认真听,根本不会注意到。但她听到了。她一直在听。
他们并排坐著。她对著论文,他对著电脑。两个人的萤幕朝不同的方向,键盘在不同的高度,咖啡在不同的温度。但他们的肩膀轻轻挨在一起。隔著两层布料,她能感觉到他肩膀的温度——不是那种烫的、灼人的热,是那种温的、恒定的、让人想一直靠著的那种暖。她没有靠上去,只是挨著。两个人的肩膀之间没有一条缝,那条缝在三个月前的电梯里就消失了。不是被填满的,是它自己合上的。就像两个频率相近的振荡器放在一起,时间长了就会同步。这是物理规律。不需要选择,不需要努力,不需要达成共识。它自己就会发生。但它发生了。在他们决定让它发生之前,就发生了。
程司白低头看著论文。第四页,第三段。她还是没有读进去。但她不著急了。她不需要今天读完这篇论文,不需要明天理解这个算法,不需要下周把它应用到系统里。她可以慢慢读。今天读一段,明天读一段,后天再读一段。读不懂也没关系,可以问旁边的人。他可能懂,可能也不懂。但他会跟她一起读。两个人读一篇论文,比一个人快还是慢?她不知道。她只知道两个人读一篇论文的时候,读不进去也没关系。因为你不会觉得是自己不够好。你会觉得——也许这篇论文本来就不值得读进去。也许值得读进去的东西不在论文里。也许值得读进去的东西在旁边,在二十公分的地方,在一个正在跟你一起浪费时间的人身上。
她把论文合上了。动作很轻,轻到没有发出声音。裴衍之没有转头看她,但他感觉到了。他的手从键盘上移开,放在桌上,手掌朝上,手指微微张开。那是一个开放的姿势——不设防,不防御,不保护自己。她把手放在他的掌心里。她的手很小,手指很细,指甲剪得很短。她的手很凉,他的手很暖。他的手指合拢了,轻轻地,慢慢地,像在握一件他等了很多年终于等到的东西。
窗外是城市的灯光。阳光照在两个人交握的手上,照在她的手背上,照在他的手指间。那些光在指缝里穿过,投在桌上,一条一条的,像一段被分割的数据流。每一条都是完整的,但拼在一起才是全部的真相。
分布式系统的难题,从来不是算法。算法有证明,有测试,有边界条件。你可以写一个函数,输入是节点的状态,输出是共识的结果。确定性的,可重复的,可以被验证的。但人与人之间没有这样的函数。没有输入,没有输出,没有确定性的结果。你只能在不知道结果的情况下做出选择,在不确定对方会不会回应的情况下发送请求,在没有收到ACK的时候决定是重发还是超时。这不是算法能解决的问题。这是信任的问题。信任不是被证明的,是被选择的。你选择相信一个人不会离开,不是因为他有不会离开的证明,是因为你愿意承担他会离开的风险。你选择相信一段关系不会失败,不是因为它有不会失败的保证,是因为你愿意参与它的失败和成功。你选择相信两个人比一个人更好,不是因为数据支持这个结论,是因为你愿意试试看。你愿意在不知道结果的情况下,把请求发送出去。然后等待。超时了,重发。再等待。再超时,再重发。你不知道要等多久,你不知道会不会收到ACK。但你愿意等。因为你相信,等到的东西值得那个时间。
程司白坐在咖啡馆里,手被裴衍之握著,肩膀挨著裴衍之的肩膀,窗外是城市的灯光。她的论文合上了,他的电脑待机了,两杯咖啡凉了。背景音乐换了一首,她没有听出来是什么曲子,也许是某首她听过的,也许不是。不重要。她不需要知道背景音乐是什么,不需要读完那篇论文,不需要写完那段代码。她只需要坐在这里,手被握著,肩膀挨著肩膀,等著太阳下山,等著城市的灯光从金色变成橘色再变成白色,等著咖啡馆里的客人来来走走,等著那个她等了三年才等到的人,继续等下去。不需要等什么特定的东西,不需要等一个结果,不需要等一个答案。只是等。在一起等。
她花了三年才明白这件事。信任不是被证明的,是被选择的。你不需要证明一个人值得信任,你只需要选择相信他。你不需要证明一段关系不会失败,你只需要选择参与它。你不需要证明两个人比一个人更好,你只需要选择试试看。她选择了。在三年前的电梯里,她选择了离开。在三个月前的电梯里,她选择了留下。在今天的咖啡馆里,她选择了不再选择。她只是待在这里,手被握著,肩膀挨著肩膀,等著看接下来会发生什么。不知道会发生什么。不知道系统会不会崩溃,不知道节点会不会故障,不知道网络会不会分区。但她不怕了。不是因为她变强了,是因为她知道了——即使系统崩溃了,有人会和她一起排查。即使节点故障了,有人会和她一起恢复。即使网络分区了,有人会在那边等著,等网络恢复的时候,第一时间发送心跳。她在这边,他在那边。中间隔著二十公分,隔著三年的时间,隔著一千多个没有说出口的夜晚。但那二十公分里现在没有墙了,三年的时间里现在没有空了,一千多个夜晚里现在没有沉默了。它们被填满了。被咖啡填满,被外套填满,被纸条填满,被“别用工作逃避”填满,被“我一直愿意”填满,被“我留下”填满,被“批准”填满。被每一次心跳填满。
她闭上眼睛。阳光透过眼皮照进来,橘红色的,温暖的,像一个信号——系统正常,连接稳定,共识达成。不需要再证明,不需要再测试,不需要再等待逾时重传。就是一个简单的状态。已连接。她靠在裴衍之的肩膀上,头发蹭著他的脖子。他的手握著她的手,手指扣著手指,掌心贴著掌心。两个人的心跳在不同的频率上运行,但通道是开的,数据在传输,共识在维持。不需要加速,不需要优化,不需要提升吞吐量。只需要保持这个频率,不快不慢,每一个滴答都和上一个滴答间隔相同的时间。她在心里跟著那个节奏数了一会儿。滴答,滴答,滴答。然后不数了。因为她知道,不管她数不数,它都在那里。稳定的,可靠的,不会崩溃的。
就像他。一直都在。
分手之后的第一百三十七天,他在程式码里写了一个Bug。
不是那种逻辑错误或者边界条件遗漏的Bug,是一种他从来没犯过的、低级的、让人看了会摇头的Bug。他在一个共识算法的实现里,把“term”这个变数名写成了“temper”。编译器报错的时候他盯著那行红色的提示看了很久,久到萤幕暗了两次。他没有改。他把那行代码注释掉了,然后在下面重新写了一行,用了另一个变数名。从那天起,他再也没有在程式码里写过“consensus”这个词。
不是刻意的。手指打到“c”的时候会停下来,像一段卡住的循环——条件不满足,无法进入下一条指令。他试过强迫自己打完整,打出来之后盯著萤幕看,觉得这八个字母长得很奇怪。c-o-n-s-e-n-s-u-s。明明是八个很正常的字母,他却觉得它们在发光,刺眼的那种。他把那行代码删了,换成了“agree”。后来又换成了“protocol”,再后来换成了“distribute”。他换了很多种说法,每一种都绕过了那八个字母。就像他在生活里绕过了很多东西——那家咖啡馆,那条她走过的路,那个她说“晚安”的楼下。
他以为绕过去就好了。绕过去就不用想了,不用疼了,不用在凌晨三点醒来的时候发现自己在翻一个不会再有新消息的对话框。但他发现绕过去不是解决方案,绕过去只是把问题推迟了。问题还在,在那条他不敢走的路的尽头,在那个他不敢点的对话框的底部,在那八个字母的背后。它一直在。
离职是在分手之后的第二个月。他把辞职信交给主管的时候,对方问他要去哪里,他说创业。对方说挺好的,年轻人该闯一闯。他没有说实话。他不是去闯,他是去躲。躲开那个空著的工位,躲开那把没有人坐的椅子,躲开那盆她留下来的仙人掌——她走的时候没有带走,他每天帮它浇水,浇了两个月,浇到根都烂了。他把仙人掌扔进垃圾桶的时候,花盆碎了,泥土散了一地。他蹲在地上收拾了很久,久到保洁阿姨过来说小伙子你让开我来扫。他说不用,我自己来。他用手指把那些碎土一点一点地捡起来,放进垃圾袋里。指甲缝里全是土,洗了三遍才洗干净。
创业的那两年他写了很多代码。前端、后端、资料库、运维,什么都写。他不挑项目,不挑客户,不挑技术栈。只要手指在键盘上,脑子就不会去想别的事情。他把自己变成了一个满载运行的系统——CPU百分之百,记忆体百分之九十五,没有空闲进程,没有多余资源。这样就不会有进程被分配到那个被她占用的记忆体位址。那个位址他没有释放,他只是把它标记为已删除。指针还在,指向的空间还在,数据还在。只是系统不会再去读取了。不会去读就不会知道那些数据还在。不知道还在就可以假装它们不在了。这是操作系统的逻辑,也是他的逻辑。
但他偶尔会读取错误。比如在写日志的时候,比如在编译的时候,比如在终端里输入指令的时候。手指会不听话,会打出那个名字。不是全名,是拼音首字母。c-s-b。三个字母,出现在命令行里,出现在档案路径里,出现在注释里。他看到的时候会愣一下,然后删掉。动作很快,快到像在处理一个异常——捕获,忽略,继续执行。但异常不会因为你忽略它就不存在。它在日志里,在堆叠里,在每一个你没有处理的catch区块里。它会积累,会溢出,会在某一个你没有防备的时刻,把整个系统冲垮。