无处不在的“网络2将军”问题,重要性超出预期
共 869字,需浏览 2分钟
·
2021-08-20 15:11
越常识的事情越总是被忽视,从而带来认知盲区和错误的技术方案。网络2将军就是这样一个典型例子。
网络2将军本来的故事是这样的:
两个将军 A1 和 A2 决定共同攻打同一个敌人 B ,敌军正好位于两个将军之间,意味着任何一方派出的信使可能会被敌军抓住。
将军 A1 给将军 A2 送信说明天进攻,但信使出发后,A1 是没有办法确认信使是不是真的把信送到了的,这样 A1 就会选择不进攻。要让事情确定一些,A2 需要收到信之后给 A1 一个确认信息,说“我已经收到了你给我的要明天进攻的信息了”。信使在给 A1 回信的路上也可能会被抓,这样, A2 会倾向于不进攻,因为他知道 A1 如果收不到他的确认信息是不会发动进攻的。所以这里的逻辑顺推下来,不管双方试图确认多少次,都不能最终确认跟彼此达成了共识。每个将军都会怀疑最后给对方发的那条信息是否送到了,两军问题又被称为“两军悖论”,是一个无解问题。
网络2将军问题在日常工作中最典型的例子就是“网络超时”:
客户端给服务器发一个网络请求(假设http接口),然后网络超时,请问,服务器是收到了这个网络请求呢?还是没收到?
答案是:不确定。如果这是一个更新数据的http接口,意味着服务器可能接收到网络请求然后更新数据成功了,也可能压根没收到网络请求,数据没更新成功。
那客户端怎么办呢?超时重试,重试就必须要求服务器对于这个接口做到幂等。
这正是网络2将军问题,对于我们做技术方案最重要的启示之1:理论上,服务端提供的任何数据更新类的接口,都必须做到“幂等”,因为没有办法避免客户端的超时重试!不幂等,重试之后,就可能产生脏数据。
那如何实现接口“幂等”呢?有N种办法,下次再续。
另外补充一点:分布式事务问题,很大部分原因也是“网络超时”引起的,后续来专门讨论。