2015-05-07 68 views
-1

我有幾個應用程序對幾個SQL Server數據庫運行相同查詢的實例。有一個手動的負載均衡機制:每個實例都使用一種算法來確定在給定時間要查詢哪個服務器。數據庫查詢負載平衡

查詢的處理時間以及服務器上的資源消耗因輸入參數而異,這些輸入參數在每次查詢被觸發時都會有所不同。

平衡算法的當前實現不時導致其中一個服務器結束爲多個「長/重」查詢的目標,而其他服務器仍處於未充分利用狀態。

正如我所知,如果查詢是一個沉重的問題,我該如何改進算法以防止服務器過載?

現在,每個應用程序實例都決定如何獨立進行平衡,所以我想我應該在所有實例之間共享負載信息,對吧?

謝謝!

+0

Ops! Downvoted ...我做錯了什麼? http://meta.stackexchange.com/questions/135/encouraging-people-to-explain-downvotes – GBrian

+3

除了「*我正在做負載均衡,您告訴我們您的問題沒有任何關係,我該如何讓它變得更好? *「 – RBarryYoung

+0

非常感謝@RBarryYoung,我已經重寫了我的問題更清楚。 – GBrian

回答

4

回答自己:

Intially我一直在尋找一些能夠實現不同勢類型的平衡http://www.peplink.com/technology/load-balancing-algorithms/的, 連我都找到了一個不錯的文章http://www.codeproject.com/Articles/3338/NET-Dynamic-Software-Load-Balancing

最後,我已經決定要保持它的簡單,因爲我知道請求的權重我只需要更少的費用服務器。 編輯:爲每個服務器添加基礎權重。現在平衡是通過重量和負載完成的。代碼可以在linqpad

// Define other methods and classes here 
public class LoadBalancer{ 

    class Server{ 
     public long Weight{ get; set;} 
     public long Load{ get; set;} 
     public string ConnectionString{ get; set;} 
     public long RequestCount; 
     // Return a weight based on the Load 
     public long CurrentWeight { 
      get{ 
       var w = Weight - Load; 
       return w <= 0 ? 1: w; 
      } 
     } 
    } 
    List<Server> Servers; 
    public LoadBalancer(){ 
     Servers = new List<Server>(); 
    } 

    public void AddServer(long weight, string connection){ 
     lock(Servers) 
      Servers.Add(new UserQuery.LoadBalancer.Server(){ ConnectionString = connection, Weight = weight }); 
    } 
    static Random rnd = new Random(); 
    // Returns server with less load 
    public string GetServer(int expectedLoad){ 
     var hit = rnd.Next(0, (int)Servers.Sum(s => s.CurrentWeight)); 
     long acc = 0; 
     foreach(var server in Servers){ 
      if(hit < server.CurrentWeight + acc){ 
       // Update load 
       lock(server){ 
        server.Load += expectedLoad; 
        server.RequestCount++; 
       } 
       return server.ConnectionString; 
      } 
      acc += server.CurrentWeight; 
     } 
     throw new Exception("No servers available"); 
    } 

    public void ReleaseServer(string conn, int expectedLoad){ 
     var server = Servers.First(s => s.ConnectionString == conn); 
     // Update load 
     lock(server){ 
      server.Load -= expectedLoad; 
      server.RequestCount--; 
     } 
    } 

    public IEnumerable<string> Dump(){ 
     return Servers.Select(s => string.Format("Server: {0}, Requests: {1}, Weight: {2}, CurrentWeight: {3}", 
      s.ConnectionString, s.RequestCount, s.Weight, s.CurrentWeight)); 
    } 

} 

void Main() 
{ 
    var balancer = new LoadBalancer(); 
    // Add servers 
    balancer.AddServer(100, "Server1"); 
    balancer.AddServer(100, "Server2"); 
    balancer.AddServer(800, "Server3"); 
    balancer.AddServer(200, "Server4"); 
    balancer.AddServer(1000, "Server5"); 

    var rnd = new Random(); 
    var servers = new List<dynamic>(); 
    Enumerable.Range(0, 100) 
    .All(i => { 
     var load = rnd.Next(1, 10); 
     var server = balancer.GetServer(load); 
     servers.Add(new {Server = server, Load = load}); 
     if(i % 10 == 0){ 
      balancer.Dump().Dump(); 
      // Remove some load 
      var items = rnd.Next(0, servers.Count); 
      servers.Take(items) 
      .All(s => { 
       balancer.ReleaseServer(s.Server, s.Load); 
       return true; 
      }); 
      servers = servers.Skip(items).ToList(); 
     } 
     return true; 
    }); 
    servers.All(s => { 
       balancer.ReleaseServer(s.Server, s.Load); 
       return true; 
      }); 
    balancer.Dump().Dump(); 
}