演算法練習 20 平滑加權輪詢演算法

2022-09-22 04:45:12 字數 1677 閱讀 7973

所有負載均衡的場景幾乎都會用到這個演算法:假設有2個伺服器a、b,其中a的分配權重為80,b的分配權重為20,當有5個請求過來時,a希望分到4次,b希望分到1次。

乙個很自然的想法:a-a-a-a-b ,按權重順序依次分配,同時計數,每分配1次,計數減1,減到0後,再分配『次權重』的伺服器。

看上去好象也湊合能用,但如果a:b的權重是100:1,a-a...-a-...(100次後),才分到b,b要坐很長時間的冷板凳,這顯然不太好。

於是就有了個這個演算法,它的思路如下:

初始狀態時,配置的權重為:,然後給每個伺服器,加1個動態的當前權重(curweight),預設為0,按以下步驟:

1、curweight += weight (注:weight為配置的權重)

2、挑選curweight最大的,做為本次分配的結果,然後將curweight -= sum(weight) ,即:分到的伺服器,其動態權重- sum(配置權重)

3、開始下1次分配,分配前將每台伺服器上的curweight += weight(即:重複步驟1)

不斷重複上述過程即可,下面分解下具體過程:

weight 初始狀態:,curweight初始狀態:

請求次數

curweight += weight

max(curweight)

curweight -= sum(weight)

1+ =

80,即a

=  2+ =

60,即a

= 3+=60,即b

= 4+=120,即a

= 5+=100,即a

= 注:所有伺服器curweight歸0時,這一輪分配就結束,

下次又回到原點,開始輪迴

所以,最終分配的順序就是 a - a - b - a - a,比原來的a - a - a - a - b,是不是更為合理? 這個演算法巧妙的地方在於,每一輪分配完成,所有伺服器的動態權重都會歸0,回到初始狀態!另外1個優勢在於,它能讓所有權重的伺服器,盡早分配到,而非等到高權重的伺服器分配完,才輪到自己。

想想這其中的數學原理也不複雜,每次分到的伺服器,其curweight 減掉了 配置權重的總和sum(weight),然後下次分配前,又將配置權重加回來了,所以一減一加,正好抵消。

理解其中的原理後,用j**a**來實現一把:

先定義乙個伺服器類:

@data

@allargsconstructor

@noargsconstructor

public class serverinfo

然後開幹:

/**

* 平滑加權輪詢演算法 示例

* by 菩提樹下的楊過 yjmyzz.cnblogs.com

** @param args

*/public static void main(string args)

}//輸出本次請求的選中結果,並更新選中節點的動態權重

if (currentserver != null)

//(以下為輔助**) 每輪結束時,輔助輸出換行

boolean roundend = true;

for (serverinfo serverinfo : serverlist)

}if (roundend)

}}

輸出:a a b a a

a a b a a

C 實現Nginx平滑加權輪詢演算法

很簡單,演算法很經典!1.定義實體類 public struct serverconfig 當前權重 public int current 服務名稱 public string name 2.演算法 public static int nextserverindex serverconfig ser...

加權輪詢和加權隨機演算法

今天在看 大型分布式 架構設計與實踐 一書中,看到了一種比較簡單的加權的演算法,在這裡記下來 var serverweightmap new dictionary serverweightmap.add 192.168.1.100 1 serverweightmap.add 192.168.1.10...

負載均衡演算法 加權輪詢

輪詢演算法沒有考慮每台伺服器的處理能力,實際情況是每台伺服器的配置 安裝的業務應用等不同,其處理能力會不一樣。所以,加權輪詢演算法的原理就是 根據伺服器的不同處理能力,給每個伺服器分配不同的權值,使其能接受相應權值數的服務請求。首先看乙個簡單的nginx負載均衡配置。按照上述配置,nginx每收到7...