故事

关中旱了三年。第一年,朝廷还按旧例征粮,各州县把仓底刮净,凑足数字押往长安。第二年,有些州县开始谎报灾情,说本地颗粒无收,请求豁免——其实私下留了种子粮,怕第三年更惨。第三年,朝廷换了宰相,新宰相是个务实人,他下了两道令,不是一道。

第一道令:今年不收「足额」,改收「实额」——各州县报上来多少算多少,不追、不罚、不问去年为什么少。第二道令:秋收期间,各仓口不得关门,从早开到晚,百姓随时能粜、随时能籴,价由市定,官不干预。

老吏们看不懂。一个说:「这不就是放任自流?仓口不关,奸商囤粮怎么办?实额不定,明年军饷从哪来?」另一个说:「前两年倒是定了额,结果呢?州县虚报,仓吏受贿,粮到了长安一半是陈谷,一半是沙子。定得越死,谎越大。」

新宰相没解释。他只让各州县在仓口挂两块牌子。

左牌写:「今日可粜」——列的是今天仓里实际有的粮,陈谷是陈谷,新麦是新麦,沙子就是沙子,不混着说。右牌写:「今日开仓」——列的是今天这扇门的时辰,卯时开、戌时关,风雨无阻,除非仓 itself 塌了。

百姓很快看懂了。左牌是收多少,右牌是能收多久。左牌上的数字可能少,可能丑,可能今天有明天无——但它不骗你。右牌上的时辰是硬的,你卯时来,门开着;你戌时后来,门关了,但你知道明天卯时它还开。

有个从河东来的粮商,姓崔,跑了三十年漕运。他头一回见到这种挂法,站在仓口看了半天。他看懂了新宰相的算盘:往年朝廷要的是「足额」——一个死数字,为了凑这个数字,州县层层加码,最后到百姓手里的是强征、是预借、是明年后年的粮都先征上来。足额是收得满,但收得满的结果是门关了——百姓跑三次,三次没粮,第四次就不来了,门开着也跟关着一样。

新宰相把「足额」拆成了两块。左牌 Harvest——今天能给你什么,如实写,不夸大。右牌 Yield——这扇门开多久,如实写,不缩短。两块牌子之间没有换算关系:左牌少的时候右牌不少,右牌短的时候左牌不因此变多。崔粮商后来跟人解释:「往年是『我要一百石,给你三天』,今年是『我有三十石,给你三十天』。一百石三天,很多人抢不上,抢到的人也可能只拿到八十石,剩下二十石是欠条。三十石三十天,来的人都能拿到,拿到的是实的,但总数确实少了。」

崔粮商自己选了后者。他往年给长安的官仓供粮,走的是「足额」路:秋天一次性收足,船队赶在封河前北上,风险大,但一笔结清。今年他改了做法,把船队拆成三拨,每拨只运往年三分之一的量,但每月走一趟。左牌上的 Harvest 少了——每次到岸的粮只有过去的三分之一。右牌上的 Yield 长了——仓口每月见他一次,长安的粮价因此稳了,没有往年那种「新粮上市价崩、青黄不接价涨」的锯齿。

有同行走老路,笑他保守。那年冬天来得早,走老路的船队在黄河口遇上凌汛,沉了三条船,足额的一百石只到了六十石,还晚了两个月。崔粮商的三十石三十天,九十月各到了三十石,十一月到了二十石——最后一批船也遇上凌汛,但只损失了一条船。他总量也没到一百石,但长安的仓口没断过粮,他的门没关过。

宰相的牌子挂到第五年,旱情缓解了,但牌子没撤。有御史弹劾,说这种挂法「示人以弱」,让朝廷显得没有掌控力。宰相回了一本,只举了一个例子:前年潼关地震,官道断了半个月,走「足额」路的州县,粮运不到,仓口只能关门,百姓聚众哄抢;走「实额」路的州县,左牌上的数字当天就减了,但右牌上的时辰没变,仓口还开着,只是今天能粜的从麦变成了豆,从新粮变成了陈谷。哄抢没发生,因为百姓知道门还开着,今天没有,明天可能有,不必抢。

御史没再说话。

概念解析

1999 年,Armando Fox 和 Eric Brewer 在提出 CAP 定理的同一时期,还提出了另一组概念:HarvestYield。这组概念后来没有像 CAP 那样广为流传,但在分布式系统的工程实践里,它比 CAP 更贴近日常决策。

Harvest:一次操作能拿到多少有效数据。 左牌上的数字。在分布式数据库里,它对应的是查询返回的结果完整度——是全部节点都参与了,还是只有部分节点响应?是精确值,还是近似值?是当天的数据,还是昨天的缓存?

Yield:系统处于可用状态的时间比例。 右牌上的时辰。它对应的是服务正常运行时间的百分比——不是「能不能启动」,而是「门开着的时候,请求能不能进来、能不能被处理」。

关键:两者独立,不能互相兑换。 这是 Fox 和 Brewer 的核心洞察。很多工程师直觉上觉得「少给点数据,就能多撑会儿可用性」——但 Harvest 和 Yield 不是零和关系。一个系统可以低 Harvest 高 Yield(仓口开着,但只有陈谷),也可以高 Harvest 低 Yield(足额粮到了,但门只开三天),还可以两者都低或都高。它们各自有各自的优化路径。

CAP 是特殊情况。 当网络分区发生时,系统必须在一致性(C)和可用性(A)之间选。Harvest/Yield 把这个框架推广到了没有分区的日常状态——即使网络完好,你也得回答:我要不要为了查询速度牺牲结果精度?要不要为了系统稳定牺牲功能完整度?

现代应用。 搜索引擎的「近似结果」、推荐系统的「缓存兜底」、大数据平台的「采样查询」——这些都是低 Harvest 高 Yield 的策略:门开着,但左牌上的数字不是全部。金融交易的「熔断停机」、医疗系统的「降级模式」——这是高 Harvest 低 Yield:要么全对,要么关门。

崔粮商的「三十石三十天」是工程上的经典权衡:把批量拆成流,把峰值削成平谷,用可预期的低 Harvest 换取稳定的 Yield。走老路的同行「一百石三天」则是另一种策略:赌一次性收足,赌赢了效率极高,赌输了门就关了。

宰相的牌子为什么没撤。 旱情结束后,足额征粮技术上又可行了。但牌子挂久了,人学会了另一种计算方式:不是「今年总共收了多少」,而是「今年门开了多少天、多少人拿到了粮」。前者是会计数字,后者是系统指标。分布式系统的监控仪表盘上,QPS 和延迟是 Yield,缓存命中率和结果精度是 Harvest——两者都得看,看一个会瞎。

御史说的「示人以弱」也没错。挂两块牌子确实显得没有「足额」那种雷霆掌控感。但分布式系统里没有宰相,只有无数个仓口和无数个崔粮商,每个人都在根据左牌和右牌做自己的决定。假装左牌永远是足额、右牌永远不关,是温韬砸石人式的安全感——看着吓人,一碰就碎。