加法增大乘法減小(AIMD)
/ A-I-M-D /
想像你在水龍頭下裝水,但你看不見杯子,所以不知道它何時會滿出來。一個明智的策略:每次只加一點點水,一旦溢出就大幅減小水流——比方說減半——然後再回到慢慢加。久而久之,你就會懸停在恰好低於杯緣的高度。AIMD,加法增大/乘法減小(additive increase / multiplicative decrease),正是這個策略,也是 TCP 試探自己能安全送多快的核心。
這條法則分兩半。加法增大:在沒看到遺失時,每個往返就把壅塞視窗加上一個固定的小量——大約每個 RTT 多一個封包份。這是溫和的線性攀升。乘法減小:一旦遺失發出壅塞信號,就以一個乘法因子縮小視窗——傳統 TCP 把它砍半。增大是加法的(緩慢而穩定,+1),減小卻是乘法的(突然而成比例,×0.5)。把視窗對時間畫出來,你會得到著名的 TCP 鋸齒:緩緩爬升、急遽下墜、再緩緩爬升,如此永遠循環。
為什麼是這種特定的不對稱?事實證明,「加法增大搭配乘法減小」這條法則,能驅使彼此競爭的流走向對一條連結公平、穩定的分享,同時又恢復得夠快而保有效率。若兩個流共用一條連結,AIMD 會推著它們趨向均分:用得多的那個流在每次砍半時絕對損失也多,於是經過許多次鋸齒後它們便收斂。遇到遺失就用力砍,讓網路保持安全;溫和地上升,讓它不至於劇烈震盪。其他大多數的增大/減小組合,不是不公平,就是無法收斂。
某個流的視窗每個 RTT 成長為 1、2、3、4、5、6、7、8 個封包(加法增大)。到 8 時它撐爆連結而遺失一個封包,於是砍半到 4(乘法減小)。接著再爬升到 5、6、7、8,又遺失,再砍半到 4。那不斷重複的 /\/\/\ 樣式——爬升、砍半、再爬升——就是鋸齒,而它的平均值就落在連結真正容量附近。
溫和的線性上升,加上遇到遺失就大幅砍半,便產生了 TCP 的鋸齒與它大致的公平性。
AIMD 的公平性只是大致的,而且偏袒往返較短的流:兩個 RTT 差很多的流並不會得到相等的份額,因為 RTT 較短的那個每秒能增大視窗的次數更多。較新的演算法如 CUBIC 與 BBR 改變了攀升方式,以修正或繞開這種 RTT 不公平。