學無止境,精益求精
十年河東,十年河西,莫欺少年窮
學歷代表你的過去,能力代表你的現在,學習代表你的將來
首先說下這個算法的背景:
假設公司需要存儲的信息量非常非常大而且訪問量也是非常非常滴大(例如淘寶,天貓,京東等數據存儲量和訪問量都很大)
就拿天貓來舉例:
馬雲:小陳啊,最近公司業務發展,數據存儲量及訪問量灰常灰常大,為減輕服務器的負載,限你們技術部提出一個解決方案?
小陳:馬大帥,你一個當老師的瞎操心什么技術(不屑的眼神)
馬雲:你知道杭州電子科技大學嗎?
小陳:一臉懵逼...
馬雲:這所學校的前身是杭州師范學院 ~_~ 注:(馬雲從杭州師范學院外國語系英語專業畢業)
小陳:馬大帥您竟然是電子科技大的高材生,佩服佩服。我馬上召集技術部人員,集思廣益。~_~ 注:(小陳並不知道馬雲英語專業畢業)
半小時后小陳提出了解決方案:負載均衡
要想做到負載均衡,就必須寫一套負載均衡算法:
在介紹負載均衡算法之前,我們來介紹下負載均衡的使用場景,如下:
還是以阿里巴巴天貓舉例:假設天貓只有一台數據庫服務器,隨着數據存儲量及訪問量的直線式增加,這台服務器的吞吐量達到了極值,造成了訪問速度越來越慢。馬總看到眼里,急在心里!於是就有了上述的對話!
小陳提出的負載均衡是怎么一回事呢?
把原來的一台服務器擴充至幾十台或者幾百台服務器,當第一台服務器吞吐量高時,將用戶的請求轉向第二台服務器。同理,當第二台服務器的吞吐量高時,將用戶的請求轉向第三台服務器,以此類推...
那么,如果自動做到負載均衡呢?這里就需要負載均衡的算法了!
假設:天貓總共有數據庫服務器四台,每台服務器的性能不同,第一台可提供的最大連接數為2,第二台服務器可提供的最大連接數為4,第三台服務器可提供的最大連接數為8,最后一台為12
假設:現在可用的服務器為第三台和第四台。
負載均衡算法如下:

namespace SJMS.test { public class Test { static int maxLinkCount; // private static object lockHelper = new object(); /// <summary> /// 所有快照/服務器的權重列表 所謂權重我們可理解為最大連接數 /// </summary> static List<int> snapWeightList = new List<int>() { 2,4,8,12}; //可用的服務器權重列表 static List<int> EnableWeightList = new List<int>() { 8,12 }; /// <summary> /// 當前的快照索引和權重信息 /// </summary> static int curentSnapIndex, currentWeight, EnableWeight; /// <summary> /// 快照權重列表中最大的權重值和最大公約數 /// </summary> static int maxWeight, gcd; static Test() { curentSnapIndex = -1; currentWeight = 0; EnableWeight = 0; maxWeight = GetMaxWeight(snapWeightList); EnableWeight = GetMaxWeight(EnableWeightList); gcd = GCD(snapWeightList); maxLinkCount = EnableWeightList.Sum(); } /// <summary> /// 獲取最大值 權重 /// </summary> /// <param name="snapWeightList"></param> /// <returns></returns> public static int GetMaxWeight(List<int> snapWeightList) { int maxWeight = 0; foreach (int snapWeight in snapWeightList) { if (maxWeight < snapWeight) maxWeight = snapWeight; } return maxWeight; } /// <summary> /// 獲取最大公約數 /// </summary> /// <param name="snapWeightList"></param> /// <returns></returns> public static int GCD(List<int> snapWeightList) { // 排序,得到數字中最小的一個 snapWeightList.Sort(new WeightCompare()); int minNum = snapWeightList[0]; // 最大公約數肯定大於等於1,且小於等於最小的那個數。 // 依次整除,如果余數全部為0說明是一個約數,直到打出最大的那個約數 int gcd = 1; for (int i = 1; i <= minNum; i++) { bool isFound = true; foreach (int snapWeight in snapWeightList) { if (snapWeight % i != 0) { isFound = false; break; } } if (isFound) gcd = i; } return gcd; } /// <summary> /// 權重輪詢調度算法/負載均衡算法 /// </summary> public static int RoundRobinScheduling() { lock (lockHelper) { while (true) { curentSnapIndex = (curentSnapIndex + 1) % EnableWeightList.Count; if (curentSnapIndex == 0) { currentWeight = currentWeight - gcd; if (currentWeight <= 0) { currentWeight = maxWeight; if (currentWeight == 0) return -1; } } int A = snapWeightList[curentSnapIndex]; if (A >= currentWeight) { return EnableWeightList[curentSnapIndex]; } } } } } public class WeightCompare : System.Collections.Generic.IComparer<int> { public int Compare(int weightA, int weightB) { return weightA - weightB; } } public class DbSnapInfo { public int SouceID { get; set; } public bool Enable { get; set; } public int Weight { get; set; } } }
這段代碼有個比較難理解的地方:最大公約數的使用!(只可意會不可言傳)
要想弄清楚最大公約數的使用,建議大家多次調試(調試時:變更服務器及服務器連接數)。
總之:算法的結果是幫你找到一個可用的服務器連接!
@陳卧龍的博客