当代码等待延迟时间不确定的某种情况时,看起来很多人选择使用指数退避,即等待N秒,检查条件是否满足;如果没有,等待2N秒,检查条件等。这对于检查恒定/线性增加的时间跨度有什么好处?
答案 0 :(得分:4)
这是TCP拥塞控制的行为。如果网络非常拥挤,实际上没有流量通过。如果每个节点在检查之前等待一段时间,那么仅用于检查的流量将继续阻塞网络,并且拥塞永远不会解决。同样,对于检查之间的线性增加时间,可能需要很长时间才能解决拥塞问题。
答案 1 :(得分:3)
当同时尝试做某事会相互干扰,使 none 成功时,指数退避很有用。在这种情况下,让设备随机尝试在太小的窗口中进行操作将导致大多数尝试失败并且必须重试。只有当窗口变得足够大时,尝试才有可能取得成功。
如果事先知道16个设备想要通信,则可以选择对于该加载级别最佳的窗口大小。但实际上,竞争设备的数量通常是未知的。每次重试时窗口大小加倍的指数退避的优点是,无论竞争实体的数量是多少:
大多数操作成功的窗口大小通常在大多数操作成功的最小窗口大小的两倍之内,
大多数在该窗口大小失败的操作将在下一次尝试时成功(因为大多数早期操作都会成功,这将使不到一半的操作竞争一个两倍大的窗口),和
如果不是每次加倍,而是将窗口简单地增加一定量,那么重试操作直到窗口达到可用大小所花费的时间将与所需窗口大小的平方成比例。虽然最终窗口大小可能比指数退避时使用的小,但所有尝试的总成本会更高。
答案 2 :(得分:1)
假设您指的是在执行操作之前测试条件:
例如,如果您的条件是对数据库的复杂(慢)查询,并且该操作是对同一数据库的更新,那么每次检查该条件都会对数据库性能产生负面影响,并且在某些时候,没有指数退避,多个参与者检查条件就足以使用所有数据库资源。
但是如果条件只是一个轻量级的内存检查(关键部分),并且操作仍然是数据库的更新(最多比检查慢几千分之一),并且如果条件被翻转在动作开始时(通过进入临界区),在一个可忽略的时间内,那么恒定或线性退避就可以了。实际上,在这种特定情况下,指数退避将是有害的,因为它会在低负载情况下引入延迟,并且更有可能导致高负载情况下的超时(即使处理带宽足够)。
总而言之,指数退避是一把锤子:它适用于指甲,而不是螺钉:)