【算法】6、指数退避算法

今天简单跟大家聊下指数退避算法(Exponential Backoff ),关于指数避退算法的话题开始前首先向大家抛出几个问题:指数退避算法是什么呢?为什么要用指数退避算法呢?指数退避算法的应用场景有哪些呢?代码如何实现呢?带着这些疑问诸君且向下看。

指数退避算法到底是什么呢?wiki上有这么一段解释:"Exponential backoff is an algorithm that uses feedback to multiplicatively decrease the rate of some process, in order to gradually find an acceptable rate"。通俗点说, 退避算法就是网络上的节点在发送数据冲突后,等待一定时间后再发,等待时间是随指数增长,从而避免频繁的触发冲突。在计算机网络中,二进制指数退避算法或截断指数退避算法常常作为避免网络堵塞的一部分用于同一数据块的重发策略。发生n次冲突后,等待时间在0~2^n-1个间隙时间(slot times) 之间选择随机选择。比如,发生第一次冲突后,每个发送方将会等待0或1个间隙时间(slot times);第二次冲突后,每个发送方的等待时间将会在0到3个间隙时间(slot times) 之间任意选择;第三次冲突后,每个发送方的等待时间将会在0到7个间隙时间(slot times) 之间任意选择,以此类推,随着冲突次数的增加,发送方的等待时间将会有成倍增加的可能性。而从“截断( truncated)”的字面意思我们不妨可以猜出,到一定次数,指数运算会停止,也就是说等待时间不会再无限的增加下去。比如,设置上限n=10,则最长等待时间为1023个间隙时间。因为在等待时间内某些场景同样有冲突发生的可能性,所以一般流程会在16次重试后终止。具体的退避算法如下:

  1. 确定基本退避时间,它就是争用期(总线上的单程端到端传播时延记为 x,以太网的端到端往返时间2x)。以太网把争用期定为51.2us。对于10Mb/s以太网,在争用期内可发送512bit,即64字节。也可以说争用期是512比特时间。1比特时间就是发送1比特所需要的时间。所以这种时间单位与数据率密切相关。
  2. 从离散的整数集合[0,1,…,]中随机取出一个数,记为r。重传应推后的时间就是r倍的争用期。上面的参数k按下面的公式计算: k=Min[重传次数,10] 可见当重传次数不超过10时,参数k等于重传次数;但当重传次数超过10时,k就不在增大而一直等于10。
  3. 当重传达16次仍不能成功时(这表明同时打算发送的数据站太多,以致连续发生冲突),则丢弃该,并向高层报告。例如,在第1次重传时,k=1,随机数r从整数{0,1}中选一个数。因此重传推迟的时间是0或争用期,在这两个时间中随机选择一个。若再发生碰撞,则重传时,k=2,随机数r就从整数{0,1,2,3}中选一个数。因此重传推迟的时间是在0,2x ,4x和6x 这4个时间中随机抽取一个。同样,若在发生碰撞,则重传时k=3,随机数r就从整数{0,1,2,3,4,5,6,7}中选一个数。以此类推。若连续多次发生冲突,就表明可能有较多的站参与争用信道。但使用退避算法可使重传需要推迟的平均时间随重传次数而增大(这也称为动态退避),因而减小发生碰撞的概率,有利于整个系统的稳定。

相信读到这里,大家对第二个问题的答案也呼之欲出了吧, 大多数指数退避算法会利用抖动(随机延迟)来防止连续的冲突。 但是,如果使用并发客户端,抖动可帮助您更快地成功执行请求。

至于指数避退算法的场景有哪些呢?指数退避算法在计算机网络中应用很广泛,这里简单说两个场景,第一个场景,接入三方支付服务,在三方支付提供的接入接口规范中,服务方交易结束结果通知和商户主动查询交易结果都用到重发机制,这就是所谓的退避算法,这地方其实也引出了另一个知识点——接口的幂等性( 使用相同参数对同一资源重复调用某个接口的结果与调用一次的结果相同),这里不再过多赘述。第二个场景,在app应用中,很多场景会遇到轮询一类的问题,一般的轮询对于app性能和电量的消耗都是个巨大的灾难。那如何解决这种问题呢?app在上一次更新操作之后还未被使用的情况下,使用指数退避算法来减少更新频率,从而节省资源和减少电的消耗。

最后一个问题,这里简单的用伪代码和java代码的方式给大家演示一下增量延迟轮询的实现方法。

伪代码

Do some asynchronous operation.·
retries = 0
DO
    wait for (2^retries * 100) milliseconds
    status = Get the result of the asynchronous operation.
    IF status = SUCCESS
        retry = false
    ELSE IF status = NOT_READY
        retry = true
    ELSE IF status = THROTTLED
        retry = true
    ELSE
        Some other error occurred, so stop calling the API.
        retry = false
    END IF
    retries = retries + 1
WHILE (retry AND (retries < MAX_RETRIES))

java代码

public enum Results {
    SUCCESS,
    NOT_READY,
    THROTTLED,
    SERVER_ERROR
}

/*
 * Performs an asynchronous operation, then polls for the result of the
 * operation using an incremental delay.
 */
public static void doOperationAndWaitForResult() {
    try {
        // Do some asynchronous operation.
        long token = asyncOperation();
        int retries = 0;
        boolean retry = false;
        do {
            long waitTime = Math.min(getWaitTimeExp(retries), MAX_WAIT_INTERVAL);
            System.out.print(waitTime + "\n");
            // Wait for the result.
            Thread.sleep(waitTime);
            // Get the result of the asynchronous operation.
            Results result = getAsyncOperationResult(token);
            if (Results.SUCCESS == result) {
                retry = false;
            } else if (Results.NOT_READY == result) {
                retry = true;
            } else if (Results.THROTTLED == result) {
                retry = true;
            } else if (Results.SERVER_ERROR == result) {
                retry = true;
            }
            else {
                // Some other error occurred, so stop calling the API.
                retry = false;
            }
        } while (retry && (retries++ < MAX_RETRIES));
    }
    catch (Exception ex) {
    }
}

/*
 * Returns the next wait interval, in milliseconds, using an exponential
 * backoff algorithm.
 */
public static long getWaitTimeExp(int retryCount) {
    long waitTime = ((long) Math.pow(2, retryCount) * 100L);
    return waitTime;
}

ok,就谈到这啦,源于自己认知的局限性,也许谈的一些地方会有错误之处,欢迎大牛指正。

时间: 2024-08-01 15:10:21

【算法】6、指数退避算法的相关文章

指数退避算法exponential back-off algorithm

在很多场景下,我们都需要解决一些诸如轮训这样的问题.如果这样的算法出现在app上,这种轮训对于app性能和电量的消耗都是个巨大的灾难,那如何解决这种问题呢? app在上一次更新操作之后还未被使用的情况下,使用指数退避算法exponential back-off algorithm来减少更新频率.这里我们介绍下指数退避算法. SharedPreferences sp = context.getSharedPreferences(PREFS, Context.MODE_WORLD_READABLE)

二进制指数退避算法

2019/12/18 二进制指数退避算法(来自于百度百科) CSMA/CD采用二进制指数退避算法,又称为二元指数后退算法.退避算法是以冲突窗口大小为基准的,每个节点有一个冲突计数器C.退避的时间与冲突次数具有指数关系,冲突次数越多,退避的时间就可能越长,若达到限定的冲突次数,该节点就停止发送数据. 定义 二进制退避技术(Binary Exponential Back off). 指在遇到重复的冲突时,站点将重复传输,但在每一次冲突之后,随着时延的平均值将加倍.二进制指数退避算法提供了一个处理重负

golang backoff重试指数退避算法

前言: 前时间出了一个小问题,下游的服务时不时的阻塞,我这边为了确保数据一致性,不断的重试请求,这样的后果自然是雪上加霜.当然,下游处理的有待提高,但我们是否有更好的办法来优化重试? backoff 指数退避算法就是干这事的. 该文章后续仍在不断的更新修改中, 请移步到原文地址http://xiaorui.cc/?p=5836 backoff 退避算法 什么是退避算法?通常我们的某服务发生故障时,我们会固定间隔时间来重试一次?但这样会带来一些问题,同一时间有很多请求在重试可能会造成无意义的请求.

Golang指数退避算法

package main import ( "fmt" "time" ) const MAXSLEEP = 128 func main() { for numsec := 1; numsec <= MAXSLEEP; numsec <<= 1 { // TODO if numsec <= MAXSLEEP/2 { time.Sleep(time.Second * time.Duration(numsec)) fmt.Println("

[Android Traffic] 调整定时更新的频率(C2DM与退避算法)

转载自: http://blog.csdn.net/kesenhoo/article/details/7395253 Minimizing the Effect of Regular Updates[最小化定时更新操作的副作用] 最佳的定时更新频率是不确定的,通常由设备状态,网络连接状态,用户行为与用户定义明确的偏好而决定. Optimizing Battery Life([Android Training - 04]优化电池寿命)这一章有讨论如何根据设备状态来修改更新频率.里面介绍了当断开网络

指数平滑算法

对时间序列的预测,用的最多的是指数平滑算法,算法不复杂. 首先理解一个基本公式: 指数平滑法的基本公式是: 式中, St--时间t的平滑值: yt--时间t的实际值: St ? 1--时间t-1的平滑值: a--平滑常数,其取值范围为[0,1]: 说明: 1. 此公式用t-1时刻的平滑值和t时刻的hi实际值来计算t时刻的平滑值 2. a是系数,越接近1的话,远期数据对于计算结果影响越小,越接近0,则影响越大 用newlisp表达公式如下: (define (cal-basic real-t1 s

时间序列挖掘-预测算法-三次指数平滑法(Holt-Winters)——三次指数平滑算法可以很好的保存时间序列数据的趋势和季节性信息

from:http://www.cnblogs.com/kemaswill/archive/2013/04/01/2993583.html 在时间序列中,我们需要基于该时间序列当前已有的数据来预测其在之后的走势,三次指数平滑(Triple/Three Order Exponential Smoothing,Holt-Winters)算法可以很好的进行时间序列的预测. 时间序列数据一般有以下几种特点:1.趋势(Trend)  2. 季节性(Seasonality). 趋势描述的是时间序列的整体走势

静态频繁子图挖掘算法用于动态网络——gSpan算法研究

摘要 随着信息技术的不断发展,人类可以很容易地收集和储存大量的数据,然而,如何在海量的数据中提取对用户有用的信息逐渐地成为巨大挑战.为了应对这种挑战,数据挖掘技术应运而生,成为了最近一段时期数据科学的和人工智能领域内的研究热点.数据集中的频繁模式作为一种有价值的信息,受到了人们的广泛关注,成为了数据挖掘技术研究领域内的热门话题和研究重点. 传统的频繁模式挖掘技术被用来在事务数据集中发现频繁项集,然而随着数据挖掘技术应用到非传统领域,单纯的事务数据结构很难对新的领域的数据进行有效的建模.因此,频繁

8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,循环控制及其优化

上两篇博客 8皇后以及N皇后算法探究,回溯算法的JAVA实现,递归方案 8皇后以及N皇后算法探究,回溯算法的JAVA实现,非递归,数据结构“栈”实现 研究了递归方法实现回溯,解决N皇后问题,下面我们来探讨一下非递归方案 实验结果令人还是有些失望,原来非递归方案的性能并不比递归方案性能高 代码如下: package com.newflypig.eightqueen; import java.util.Date; /** * 使用循环控制来实现回溯,解决N皇后 * @author [email pr