我正在经历rpc语义,至少一次和最多一次的语义,它们是如何工作的?
无法理解其实施的概念。
答案 0 :(得分:48)
在这两种情况下,目标都是调用一次函数。但是,不同之处在于它们的故障模式。在“至少一次”中,系统将在失败时重试,直到它知道该函数被成功调用,而“最多一次”将不会尝试重试(或将确保对该函数的否定确认)重试前调用。)
至于如何实现这些,这可能会有所不同,但伪代码可能如下所示:
At least once:
request_received = false
while not request_received:
send RPC
wait for acknowledgement with timeout
if acknowledgment received and acknowledgement.is_successful:
request_received = true
At most once:
request_sent = false
while not request_sent:
send RPC
request_sent = true
wait for acknowledgement with timeout
if acknowledgment received and not acknowledgement.is_successful:
request_sent = false
你想做“最多一次”的一个例子就是支付(你不会不小心对某人的信用卡两次开票),其中一个例子是“至少一次”就像更新具有特定值的数据库(如果您碰巧连续两次将相同的值写入数据库,这对任何事情都没有任何影响)。你几乎总是想对非变异(a.k.a.幂等)操作使用“至少一次”;相比之下,大多数变异操作(或者至少是那些逐渐改变状态并因此在应用突变时依赖于当前/先前状态的操作)将需要“至多一次”。
我应该补充一点,在“至少一次”系统之上实现“最多一次”语义是相当普遍的,方法是在RPC的主体中包含一个唯一标识它的标识符,并确保在服务器上系统看到的每个ID只处理一次。您可以考虑TCP数据包中的序列号(确保数据包按顺序传送一次)作为此模式的特殊情况。然而,这种方法在分布式系统上正确实现可能有些挑战,在分布式系统上,同一RPC的重试可能会到达运行相同服务器软件的两台独立计算机。 (处理此问题的一种技术是记录接收RPC的事务,然后使用集中式系统对这些记录进行聚合和重复数据删除,然后再将系统内的请求重新分发以进行进一步处理;另一种技术是机会性地处理RPC,但是当服务器之间的同步最终检测到这种重复时,协调/恢复/回滚状态......这种方法可能不会用于付款,但在其他情况下(例如论坛帖子)可能会有用。