无码色色,久久久久久免费精品喷水,美女把胸罩解开让男生摸,欧美一级在线观看视频,色亚洲天堂,色综合天天综合给合国产

咨詢電話:023-88959644    24小時服務(wù)熱線:400-023-8809
NEWS CENTER ·
新聞動態(tài)
關(guān)注中技互聯(lián) 關(guān)注前沿

Discuz!NT論壇數(shù)據(jù)庫讀寫分離方案!具體操作步驟。

發(fā)表日期:2010-09-21    文章編輯:王東    瀏覽次數(shù):36    標(biāo)簽:

目前在Discuz!NT這個產(chǎn)品中,數(shù)據(jù)庫作為數(shù)據(jù)持久化工具,必定在并發(fā)訪問頻繁且負(fù)載壓力較大的情況下成 為系統(tǒng)性能的‘瓶頸’。即使使用本地緩存等方式來解決頻繁訪問數(shù)據(jù)庫的問題,但仍舊會有大量的并發(fā)請求要訪問動態(tài)數(shù)據(jù),雖然 SQL2005及2008以上版本中性能不斷提升,查詢計(jì)劃和存儲過程運(yùn)行得越來越高效,但最終還是 要面臨‘瓶頸’這一問 題。當(dāng)然這也是許多大型網(wǎng)站不斷研究探索各式各樣的方案來有效降低數(shù)據(jù)訪問負(fù)荷的原 因, 其中的‘讀寫分離’方案就是一種被廣泛采用的方案。

      目前在Discuz!NT這個產(chǎn)品中,數(shù)據(jù)庫作為數(shù)據(jù)持久化工具,必定在并發(fā)訪問頻繁且負(fù)載壓力較大的情況下成 為系統(tǒng)性能的‘瓶頸’。即使使用本地緩存等方式來解決頻繁訪問數(shù)據(jù)庫的問題,但仍舊會有大量的并發(fā)請求要訪問動態(tài)數(shù)據(jù),雖然 SQL2005及2008以上版本中性能不斷提升,查詢計(jì)劃和存儲過程運(yùn)行得越來越高效,但最終還是 要面臨‘瓶頸’這一問 題。當(dāng)然這也是許多大型網(wǎng)站不斷研究探索各式各樣的方案來有效降低數(shù)據(jù)訪問負(fù)荷的原 因, 其中的‘讀寫分離’方案就是一種被廣泛采用的方案。
      Discuz!NT這個產(chǎn)品在其企業(yè)版中提供了對‘讀寫分離’機(jī)制的支持,使對CPU及內(nèi)存消耗嚴(yán)重的操作(CUD)被 分離到一臺或幾臺性能很高的機(jī)器上,而將頻繁讀取的操作(select)放到幾臺配置較低的機(jī)器上,然后通過‘事務(wù) 發(fā)布訂閱機(jī)制’,實(shí)現(xiàn)了在多個sqlserver數(shù)據(jù)庫之間快速高效同步數(shù)據(jù),從而達(dá)到了將‘讀寫請求’按實(shí)際負(fù)載 情況進(jìn)行均衡分布的效果。
 
      下面就簡要介紹一下其實(shí)現(xiàn)思路。注:有關(guān)數(shù)據(jù)同步的工具已在sqlserver中自帶了,可以參考這篇文章
     
      將相應(yīng)的數(shù)據(jù)由Master(主)數(shù)據(jù)庫中‘發(fā)布’出來,然后使用推送的方式(注:事務(wù)發(fā)布可以指定是‘通過主 數(shù)據(jù)庫推送’ 還是‘訂閱服務(wù)器去獲取’)發(fā)送到訂閱它的數(shù)據(jù)庫中,就實(shí)現(xiàn)了數(shù)據(jù)同步功能。
 
      下面就介紹一下如何通過改變既有代碼來實(shí)現(xiàn)在‘幾個從數(shù)據(jù)庫(類似快照)’間進(jìn)行讀取數(shù)據(jù)的負(fù)載均衡。
 
      原有的代碼中因?yàn)槭褂昧朔謱訖C(jī)制,所以我們只要在‘數(shù)據(jù)訪問層’動一下心思就可以了。在這里我的一個設(shè) 計(jì)思路就是不改變已有的數(shù)據(jù)庫訪問接口(包括參數(shù)等)的前提下,實(shí)現(xiàn)底層自動將現(xiàn)有的數(shù)據(jù)訪問操作進(jìn)行負(fù)載 均衡。這樣做的好處不用多說了,同時也讓這個負(fù)載均衡功能與數(shù)據(jù)訪問層相分離,不要耦合的太緊密,同時如果不曉得底層 的實(shí)現(xiàn)原理也可以只通過一個開關(guān)(后面會介紹),就可以讓自己的sql語句自動實(shí)現(xiàn)動態(tài)負(fù)載均衡。
    
      說到這里,我來對照代碼進(jìn)一步闡述:
 
      首先就是(Discuz.Data\DbHelper.cs)代碼,主要變動如下(新增方法部分):   
 

代碼
/// <summary>
/// 獲取使用的數(shù)據(jù)庫(或快照)鏈接串
/// </summary>

/// <param name="commandText">存儲過程名或都SQL命令文本</param>
/// <returns></returns>
public static string GetRealConnectionString(string commandText)
{
    
if (DbSnapConfigs.GetConfig() != null &&
 DbSnapConfigs.GetConfig().AppDbSnap)
    {
        commandText 
=
 commandText.Trim().ToLower();
        
if (commandText.StartsWith("select"|| ((commandText.StartsWith(BaseConfigs.GetTablePrefix) &&
 UserSnapDatabase(commandText))))
        {
            DbSnapInfo dbSnapInfo 
=
 GetLoadBalanceScheduling.GetConnectDbSnap();

            
if (DbSnapConfigs.GetConfig().RecordeLog && snapLogList.Capacity >
 snapLogList.Count)
                snapLogList.Add(
string.Format("{{'SouceID' : {0}, 'DbconnectString' : '{1}', 'CommandText' : '{2}', 'PostDateTime' : '{3}'}},"
,
                                 dbSnapInfo.SouceID,
                                 dbSnapInfo.DbconnectString,
                                 commandText.Replace(
"'",""
),
                                 Discuz.Common.Utils.GetDateTime()));

            
return
 dbSnapInfo.DbconnectString;
        }
    }

    
return
 ConnectionString;
}

       上面的方法將會對傳入的sql語句進(jìn)行分析,找出其中是CUD操作還是SELECT操作,來區(qū)別是讀還是寫操作。而snapLogList列表則是之前所配置的‘事務(wù)發(fā)布訂閱’模式下的相關(guān)‘從數(shù)據(jù)庫’(Slave Database)鏈接串的列表,例如(dbsnap.config文件的DbSnapInfoList節(jié)點(diǎn)): 

代碼
<?xml version="1.0"?>
<DbSnapAppConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  
<AppDbSnap>true</AppDbSnap>
  
<WriteWaitTime>1</WriteWaitTime>
  
<LoadBalanceScheduling>RoundRobinScheduling</LoadBalanceScheduling> --WeightedRoundRobinScheduling
  
<RecordeLog>false</RecordeLog>

  
<DbSnapInfoList>
    
<DbSnapInfo>
      
<SouceID>1</SouceID>
      
<Enable>true</Enable>
      
<DbconnectString>Data Source=DAIZHJ\DNT_DAIZHJ;User ID=sa;Password=123123;Initial Catalog=dnt_snap;Pooling=true</DbconnectString>
      
<Weight>4</Weight>
    
</DbSnapInfo>
      
<DbSnapInfo>
      
<SouceID>2</SouceID>
      
<Enable>true</Enable>
      
<DbconnectString>Data Source=DAIZHJ-PC\2222;User ID=sa;Password=123;Initial Catalog=tabletest;Pooling=true</DbconnectString>
      
<Weight>3</Weight>
    
</DbSnapInfo>
  
</DbSnapInfoList>
</DbSnapAppConfig>

       有關(guān)相應(yīng)配置節(jié)點(diǎn)和負(fù)載均衡算法會在后面提到,這里為了保持文章內(nèi)容的連續(xù)性暫且跳過,下面接著瀏覽一下上面調(diào)用的‘UserSnapDatabase’方法:

代碼
/// <summary>
/// 是否使用快照數(shù)據(jù)庫
/// </summary>

/// <param name="commandText">查詢</param>
/// <returns></returns>
private static bool UserSnapDatabase(string commandText)
{
    
// 如果上次刷新cookie間隔小于5分鐘, 則不刷新數(shù)據(jù)庫最后活動時間

    if (commandText.StartsWith(BaseConfigs.GetTablePrefix + "create"))
    {
        Utils.WriteCookie(
"JumpAfterWrite"
, Environment.TickCount.ToString());
        
return false
;
    }
    
else if (!String.IsNullOrEmpty(Utils.GetCookie("JumpAfterWrite")) && (Environment.TickCount - TypeConverter.StrToInt(Utils.GetCookie("JumpAfterWrite"), Environment.TickCount)) < DbSnapConfigs.GetConfig().WriteWaitTime * 1000
)
        
return false
;
    
else if (!commandText.StartsWith(BaseConfigs.GetTablePrefix + "get"
))
        
return false
;

    
return true
;
}

 

      該方法的作用很簡單,就是當(dāng)數(shù)據(jù)庫有CUD操作時,通過寫cookie的方式向客戶端寫一個鍵值‘JumpAfterWrite’,這個鍵值很重要,就是提供一個標(biāo)簽(flag)來指示:‘當(dāng)前用戶執(zhí)行cud操作時,頁面跳轉(zhuǎn)到其它頁面而主數(shù)據(jù)庫還沒來得及將數(shù)據(jù)推送到從數(shù)據(jù)庫’這一情況而造成的‘數(shù)據(jù)不同步’問題。
     舉了例子,當(dāng)在一個版塊中‘發(fā)表主題’后系統(tǒng)自動跳轉(zhuǎn)到‘顯示該主題頁面’時,如果主數(shù)據(jù)庫中插入了一個新主題而從數(shù)據(jù)庫沒有被及時更新這一主題信息時,就會報(bào)‘主題不存在’這個錯誤。所以這里加了一個設(shè)置,就是下面這一行: 

(Environment.TickCount - TypeConverter.StrToInt(Utils.GetCookie("JumpAfterWrite"), Environment.TickCount)) < DbSnapConfigs.GetConfig().WriteWaitTime * 1000)

 

    
      它所做的就是確保用戶cud操作之后,在規(guī)定的時間內(nèi)還是訪問主數(shù)據(jù)庫,當(dāng)時間超過時,才將當(dāng)前用戶的訪問請求(select)均衡到其它從數(shù)據(jù)庫中。

      當(dāng)然,在GetRealConnectionString()方法中,還有一行代碼很重要,就是下面這一行:    
    

DbSnapInfo dbSnapInfo = GetLoadBalanceScheduling.GetConnectDbSnap();

 

    
    它的作用就是加載配置文件信息,其中最主要的就是相應(yīng)的‘負(fù)載均衡算法實(shí)例’來獲取相應(yīng)的從數(shù)據(jù)庫鏈接串,下面先看一
下‘靜態(tài)屬性’GetLoadBalanceScheduling的相關(guān)信息:

 

代碼
/// <summary>
/// 負(fù)載均衡調(diào)度接口
/// </summary>

private static ILoadBalanceScheduling m_loadBalanceSche;
/// <summary>

/// 初始化負(fù)載均衡調(diào)度接口實(shí)例
/// </summary>

private static ILoadBalanceScheduling GetLoadBalanceScheduling
{
    
get

    {
        
if (m_loadBalanceSche == null)
        {
            
try

            {
                m_loadBalanceSche 
= (ILoadBalanceScheduling)Activator.CreateInstance(Type.GetType(string.Format("Discuz.EntLib.{0}, Discuz.EntLib", DbSnapConfigs.GetConfig().LoadBalanceScheduling), falsetrue));
            }
            
catch

            {
                
throw new Exception("請檢查config/dbsnap.config中配置是否正確");
            }
        }
        
return
 m_loadBalanceSche;
    }
}

       它主要是通過反射的方法將Discuz.EntLib.dll文件中的相應(yīng)負(fù)載均衡算法實(shí)例進(jìn)行綁定,然后以m_loadBalanceSche這個靜態(tài)變量進(jìn)行保存,而m_loadBalanceSche本身就是ILoadBalanceScheduling接口變量,該接口即是相應(yīng)負(fù)載均衡算法的實(shí)現(xiàn)接口。同樣因?yàn)槲恼聝?nèi)容的連續(xù)性,這里先不深挖相應(yīng)的實(shí)現(xiàn)算法,我會在后面進(jìn)行介紹。下面再來看一下GetRealConnectionString()中還有一段代碼,如下:    

代碼
    if (DbSnapConfigs.GetConfig().RecordeLog && snapLogList.Capacity > snapLogList.Count)
                        snapLogList.Add(
string.Format("{{'SouceID' : {0}, 'DbconnectString' : '{1}', 'CommandText' : '{2}', 'PostDateTime' : '{3}'}},"
,
                                         dbSnapInfo.SouceID,
                                         dbSnapInfo.DbconnectString,
                                         commandText.Replace(
"'",""
),
                                         Discuz.Common.Utils.GetDateTime()));

     
return dbSnapInfo.DbconnectString;

 

     
     上面代碼將當(dāng)前的負(fù)載均衡得到的鏈接串保存到一個snapLogList列表中,該列表聲明如下:     
    

 List<string> snapLogList = new List<string>(400)

 

     
      為什么要提供這個列表并進(jìn)行記錄?主要是為了考查負(fù)載均衡算法的工作情況,因?yàn)樵跀?shù)據(jù)訪問層獲取相應(yīng)鏈接串信息并進(jìn)行記錄很不方便,所以我用這個變量記錄大約400條‘負(fù)載均衡’數(shù)據(jù)鏈接串,以便在相應(yīng)的Discuz.EntLib.ToolKit工具包中進(jìn)行觀察,監(jiān)視其‘工作情況’。這里我們只要知道通過GetRealConnectionString()方法就實(shí)現(xiàn)了對sql語句或存儲過程進(jìn)行分析并進(jìn)行負(fù)載均衡的效果了(注:該操作可能會耗時,所以在DbSnapConfigs中提供了一個開關(guān)‘RecordeLog’來進(jìn)行控制,后面會介紹)。
    

     下面再來簡單介紹一下,如何改造DbHelper.cs中原有方法,使其支持負(fù)載均衡功能。這里強(qiáng)調(diào)一點(diǎn),就是:
    
     GetRealConnectionString()方法只是造了一個房子,里面的家具還是要自己搬。
    
     而家具就是那些老的方法,比如:

 

代碼
public static object ExecuteScalar(DbConnection connection, CommandType commandType, string commandText, params DbParameter[] commandParameters)
{
    
if (connection == nullthrow new ArgumentNullException("connection"
);

    
//connection.Close();

    connection.ConnectionString = GetRealConnectionString(commandText);//負(fù)載均衡改造完成的方法
    connection.Open();

    
// 創(chuàng)建DbCommand命令,并進(jìn)行預(yù)處理

    DbCommand cmd = Factory.CreateCommand();

    
bool mustCloseConnection = false
;
    PrepareCommand(cmd, connection, (DbTransaction)
null, commandType, commandText, commandParameters, out
 mustCloseConnection);

    
// 執(zhí)行DbCommand命令,并返回結(jié)果.

    object retval = cmd.ExecuteScalar();

    
// 清除參數(shù),以便再次使用.

    cmd.Parameters.Clear();

    
if
 (mustCloseConnection)
        connection.Close();

    
return
 retval;
}

    
      上面的 ‘connection.ConnectionString =’之前綁定的ConnectionString這個靜態(tài)屬性,而這個屬性鏈接的就是‘主數(shù)據(jù)庫’,
這里我們只要將GetRealConnectionString(commandText)賦值給它就可以了,還是那句話,在GetRealConnectionString()就實(shí)現(xiàn)了
數(shù)據(jù)庫鏈接串的負(fù)載均衡,呵呵。類似上面的變動在DbHelper.cs還有幾處,好在變化不太大,當(dāng)然更不需要改變原有的數(shù)據(jù)訪問層
(比如IDataProvider.cs文件)了。

      其實(shí)本文中介紹的數(shù)據(jù)庫層負(fù)載均衡實(shí)現(xiàn)方法在MYSQL中早有相應(yīng)的插件實(shí)現(xiàn)了,參見這篇文章。      
  

     

 

 

        該文章中的LUA腳本實(shí)現(xiàn)方式與本文類似,如下:    
    

代碼
--發(fā)送所有的非事務(wù)性SELECT到一個從數(shù)據(jù)庫
    
if is_in_transaction == 0 and packet:byte() == proxy.COM_QUERY and packet:sub(27== "SELECT"
 then
      local max_conns 
= -1
   
      local max_conns_ndx 
=
 0    
      
for i = 1#proxy.servers do 

           local s = proxy.servers[i]
           
--
 選擇一個擁有空閑連接的從數(shù)據(jù)庫
           
if s.type == proxy.BACKEND_TYPE_RO and s.idling_connections >
 0 then   
              
if max_conns == -1 or  s.connected_clients <
 max_conns then          
                  max_conns 
=
 s.connected_clients          
                  max_conns_ndx 
=
 i        
              end 
           end
      end
    .....

      接著,我再介紹一下相應(yīng)的配置文件和負(fù)載均衡算法的實(shí)現(xiàn)情況:)
   
   
      配置文件(比如:Discuz.EntLib.ToolKit\config\dbsnap.config):     
     
 

代碼
<?xml version="1.0"?>
<DbSnapAppConfig xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  
<AppDbSnap>true</AppDbSnap>
  
<WriteWaitTime>1</WriteWaitTime>
  
<LoadBalanceScheduling>RoundRobinScheduling</LoadBalanceScheduling> --WeightedRoundRobinScheduling
  
<RecordeLog>false</RecordeLog>

  
<DbSnapInfoList>
    
<DbSnapInfo>
      
<SouceID>1</SouceID>
      
<Enable>true</Enable>
      
<DbconnectString>Data Source=DAIZHJ\DNT_DAIZHJ;User ID=sa;Password=123123;Initial Catalog=dnt_snap;Pooling=true</DbconnectString>
      
<Weight>4</Weight>
    
</DbSnapInfo>
    
<DbSnapInfo>
      
<SouceID>2</SouceID>
      
<Enable>true</Enable>
      
<DbconnectString>Data Source=DAIZHJ-PC\2222;User ID=sa;Password=123;Initial Catalog=tabletest;Pooling=true</DbconnectString>
      
<Weight>3</Weight>
    
</DbSnapInfo>
    
<DbSnapInfo>
      
<SouceID>3</SouceID>
      
<Enable>true</Enable>
      
<DbconnectString>Data Source=DAIZHJ-PC\333333;User ID=sa;Password=123;Initial Catalog=tabletest;Pooling=true</DbconnectString>
      
<Weight>2</Weight>
    
</DbSnapInfo>
    
<DbSnapInfo>
      
<SouceID>4</SouceID>
      
<Enable>true</Enable>
      
<DbconnectString>Data Source=DAIZHJ-PC\44444444;User ID=sa;Password=123;Initial Catalog=tabletest;Pooling=true</DbconnectString>
      
<Weight>2</Weight>
    
</DbSnapInfo>
  
</DbSnapInfoList>
</DbSnapAppConfig>

       上面的DbSnapInfoList就是相應(yīng)的slave數(shù)據(jù)庫鏈接列表,其中它的相應(yīng)節(jié)點(diǎn)信息說明如下(Discuz.Config\DbSnapInfo.cs):     
 

代碼
[Serializable]
public class
 DbSnapInfo 
{
    
/// <summary>

    
/// 源ID,用于唯一標(biāo)識快照在數(shù)據(jù)庫負(fù)載均衡中的信息
    
/// </summary>

    private int _souceID;
    
/// <summary>

    
/// 源ID,用于唯一標(biāo)識快照在數(shù)據(jù)庫負(fù)載均衡中的信息
    
/// </summary>

    public int SouceID
    {
        
get { return
 _souceID; }
        
set { _souceID =
 value; }
    }

    
/// <summary>

    
/// 快照是否有效
    
/// </summary>

    private bool _enable;    
    
/// <summary>

    
/// 是否有效
    
/// </summary>

    public bool Enable
    {
        
get { return
 _enable; }
        
set { _enable =
 value; }
    }

    
/// <summary>

    
/// 快照鏈接
    
/// </summary>

    private string _dbConnectString;
    
/// <summary>

    
/// 快照鏈接
    
/// </summary>

    public string DbconnectString
    {
        
get { return
 _dbConnectString; }
        
set { _dbConnectString =
 value; }
    }

    
/// <summary>

    
/// 權(quán)重信息,該值越高則意味著被輪循到的次數(shù)越多
    
/// </summary>

    private int _weight;
    
/// <summary>

    
/// 權(quán)重信息,該值越高則意味著被輪循到的次數(shù)越多
    
/// </summary>

    public int Weight
    {
        
get { return
 _weight; }
        
set { _weight =
 value; }
    }
}

 
      
       當(dāng)然DbSnapAppConfig作為DbSnapInfo列表的容器,其結(jié)構(gòu)如下:    
 

代碼
[Serializable]
public class
 DbSnapAppConfig : Discuz.Config.IConfigInfo
{
    
private bool
 _appDbSnap;
    
/// <summary>

    
/// 是否啟用快照,如不使用,則即使DbSnapInfoList已設(shè)置有效快照信息也不會使用。
    
/// </summary>

    public bool AppDbSnap
    {
        
get { return
 _appDbSnap; }
        
set { _appDbSnap =
 value; }
    }

    
private int _writeWaitTime = 6
;
    
/// <summary>

    
/// 寫操作等待時間(單位:秒), 說明:在執(zhí)行完寫操作之后,在該時間內(nèi)的sql請求依舊會被發(fā)往master數(shù)據(jù)庫
    
/// </summary>

    public int WriteWaitTime
    {
        
get { return
 _writeWaitTime; }
        
set { _writeWaitTime =
 value; }
    }

    
private string _loadBalanceScheduling = "WeightedRoundRobinScheduling"
;
    
/// <summary>

    
/// 負(fù)載均衡調(diào)度算法,默認(rèn)為權(quán)重輪詢調(diào)度算法 http://www.pcjx.com/Cisco/zhong/209068.html
    
/// </summary>
    public string LoadBalanceScheduling
    {
        
get { return
 _loadBalanceScheduling; }
        
set { _loadBalanceScheduling =
 value; }
    }

    
private bool _recordeLog = false
;
    
/// <summary>

    
/// 是否記錄日志
    
/// </summary>

    public bool RecordeLog
    {
        
get { return
 _recordeLog; }
        
set { _recordeLog =
 value; }
    }
    

    
private  List<DbSnapInfo>
 _dbSnapInfoList;
    
/// <summary>

    
/// 快照輪循列表
    
/// </summary>

    public  List<DbSnapInfo> DbSnapInfoList
    {
        
get { return
 _dbSnapInfoList; }
        
set { _dbSnapInfoList =
 value; }
    }
}

    通過這兩個配置文件,就可以實(shí)現(xiàn)對數(shù)據(jù)訪問層負(fù)載均衡的靈活配置了,不過上面的DbSnapAppConfig還有一個非常重要的
屬性沒有介紹清楚,就是‘LoadBalanceScheduling’,其接口聲明如下:

代碼
    /// <summary>
    
///  負(fù)載均衡調(diào)度接口
    
/// </summary>

    public interface ILoadBalanceScheduling
    {
        
/// <summary>

        
/// 獲取應(yīng)用當(dāng)前負(fù)載均衡調(diào)度算法下的快照鏈接信息
        
/// </summary>

        
/// <returns></returns>
        DbSnapInfo GetConnectDbSnap();
    }

     它就是負(fù)載均衡算法的實(shí)現(xiàn)接口,為了便于說明在Discuz.EntLib中內(nèi)置的兩個負(fù)載均衡算法的實(shí)現(xiàn)情況,請先看下圖:    
    
    
       內(nèi)置的兩個負(fù)載均衡算法,一個是RoundRobinScheduling,即輪叫調(diào)度(Round Robin Scheduling)算法,它的實(shí)現(xiàn)比較簡單,就是對從數(shù)據(jù)庫鏈接列表的依次遍歷,如下:
代碼
/// <summary>
/// 輪叫調(diào)度(Round Robin Scheduling)算法
/// </summary>

public class RoundRobinScheduling : ILoadBalanceScheduling
{
    
private static object lockHelper = new object
();
    
/// <summary>

    
/// 當(dāng)前的快照索引和權(quán)重信息
    
/// </summary>

    static int curentSnapIndex = 0;

    
static
 RoundRobinScheduling()
    {}

    
public
  DbSnapInfo GetConnectDbSnap()
    {
        
lock
 (lockHelper)
        {
            
if (curentSnapIndex >=
 DbSnapConfigs.GetEnableSnapList().Count)
                curentSnapIndex 
= (curentSnapIndex) %
 DbSnapConfigs.GetEnableSnapList().Count;
         
            
return DbSnapConfigs.GetEnableSnapList()[curentSnapIndex++
];
        }
    }
}

 
   
     而另一種負(fù)載均衡算法就相對負(fù)載了,不過它也更符合實(shí)際的應(yīng)用場景,它使用了權(quán)重的方法來讓性能優(yōu)良的機(jī)器分到
更多的任務(wù)來均衡整個方案的性能,即權(quán)重輪詢調(diào)度算法,實(shí)現(xiàn)代碼如下:


 

代碼
/// <summary>
/// 權(quán)重輪詢調(diào)度算法 
/// http://www.pcjx.com/Cisco/zhong/209068.html
 
/// http://id-phatman.spaces.live.com/blog/cns
!CA763CA8DB2378D1!627.entry
/// </summary>

public class WeightedRoundRobinScheduling : ILoadBalanceScheduling
{
    
private static object lockHelper = new object
();
    
/// <summary>

    
/// 快照的權(quán)重列表
    
/// </summary>

    static List<int> snapWeightList = new List<int>();
    
/// <summary>

    
/// 當(dāng)前的快照索引和權(quán)重信息
    
/// </summary>

    static int curentSnapIndex, currentWeight;
    
/// <summary>

    
/// 快照權(quán)重列表中最大的權(quán)重值和最大公約數(shù)
    
/// </summary>

    static int maxWeight, gcd;

    
static
 WeightedRoundRobinScheduling()
    {
        curentSnapIndex 
= -1
;
        currentWeight 
= 0
;

        snapWeightList 
=
 GetSnapWeightList();
        maxWeight 
=
 GetMaxWeight(snapWeightList);
        gcd 
=
 GCD(snapWeightList);
    }

    
/// <summary>

    
/// 獲取應(yīng)用當(dāng)前負(fù)載均衡調(diào)度算法下的快照鏈接信息
    
/// </summary>

    
/// <returns></returns>
    public  DbSnapInfo GetConnectDbSnap()
    {
        
lock
 (lockHelper)
        {
            DbSnapInfo current 
=
 RoundRobinScheduling();
            
if (current != null
)
                
return
 current;
            
else

                
return DbSnapConfigs.GetEnableSnapList()[0];
        }
    }

    
/// <summary>

    
/// 獲取快照權(quán)重的列表
    
/// </summary>

    
/// <returns></returns>
    static List<int> GetSnapWeightList()
    {
        List
<int> snapWeightList = new List<int>
();

        
foreach (DbSnapInfo dbSnapInfo in
 DbSnapConfigs.GetEnableSnapList())
        {
            snapWeightList.Add(dbSnapInfo.Weight);
        }
        
return
 snapWeightList;
    }

    
/// <summary>

    
/// 權(quán)重輪詢調(diào)度算法
    
/// </summary>

    static DbSnapInfo RoundRobinScheduling()
    {
        
while (true
)
        {
            curentSnapIndex 
= (curentSnapIndex + 1%
 DbSnapConfigs.GetEnableSnapList().Count;
            
if (curentSnapIndex == 0
)
            {
                currentWeight 
= currentWeight -
 gcd;
                
if (currentWeight <= 0
)
                {
                    currentWeight 
=
 maxWeight;
                    
if (currentWeight == 0
)
                        
return null
;
                }
            }
            
if (DbSnapConfigs.GetEnableSnapList()[curentSnapIndex].Weight >=
 currentWeight)
                
return
 DbSnapConfigs.GetEnableSnapList()[curentSnapIndex];
        }
    }

    
/// <summary>

    
/// 獲取最大權(quán)重
    
/// </summary>

    
/// <param name="snapList"></param>
    
/// <returns></returns>
    static int GetMaxWeight(List<int> snapWeightList)
    {
        
int maxWeight = 0
;
        
foreach (int snapWeight in
 snapWeightList)
        {
            
if (maxWeight <
 snapWeight)
                maxWeight 
=
 snapWeight;
        }
        
return
 maxWeight;
    }

    
/// <summary>

    
/// 獲取權(quán)重的最大公約數(shù)
    
/// </summary>

    
/// <returns></returns>
    static int GCD(List<int> snapWeightList)
    {
        
// 排序,得到數(shù)字中最小的一個 

        snapWeightList.Sort(new WeightCompare());
        
int minNum = snapWeightList[0
];

        
//
 最大公約數(shù)肯定大于等于1,且小于等于最小的那個數(shù)。 
        
// 依次整除,如果余數(shù)全部為0說明是一個約數(shù),直到打出最大的那個約數(shù) 

        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>

    
/// 實(shí)現(xiàn)IComparer接口,用于對數(shù)字列表進(jìn)行排序
    
/// </summary>  

    private class WeightCompare : System.Collections.Generic.IComparer<int>
    {
        
public int Compare(int weightA, int weightB)
        {
            
return weightA -
 weightB;
        }
    }
}

        到這里,主要的功能代碼就介紹的差不多了,我們可以通過對dbsnap.config的相應(yīng)節(jié)點(diǎn)配置,來靈活定制我們的負(fù)載均衡方案。同時,對一般開發(fā)者而言,這種架構(gòu)是透明的,大家可以完全在不了解它的情況下開發(fā)自己的數(shù)據(jù)訪問功能,并通過相應(yīng)開關(guān)來讓自己的代碼支持均衡負(fù)載。

        當(dāng)然這個方案還有一些沒考慮到的問題比如:
        1.對‘主從數(shù)據(jù)庫的健康度檢查’,即如果主或從數(shù)據(jù)庫出現(xiàn)故障的時候該如何處理,當(dāng)然在sqlserver中還提供了鏡像功能來解決類似問題,所以它也可做為一個備選方案。

        2.當(dāng)主數(shù)據(jù)庫被發(fā)布出去后,主數(shù)據(jù)庫的表和存儲過程就會被‘鎖定’,其不允許被再次修改了,所以還要繼續(xù)研究如何解決這一問題。

重慶中技互聯(lián)網(wǎng)信息咨詢有限公司
重慶網(wǎng)站建設(shè)事業(yè)部官方網(wǎng):www.tmsmall666.cn
電子商務(wù)建站事業(yè)部咨詢電話:023-67742189
門戶網(wǎng)站品牌加盟推廣電話:023-67742189
7*24小時服務(wù)電話:023-67742189
媒體合作電話:13883323406
投資合作電話:13896068183
QQ及郵件地址:446515345@qq.com

如沒特殊注明,文章均為中技互聯(lián)原創(chuàng),轉(zhuǎn)載請注明來自www.tmsmall666.cn
相關(guān)新聞

CopyrightZJCOO technology Co., LTD. All Rights Reserved.    

渝ICP 備11003429號

  • qq客服
  • 公眾號
  • 手機(jī)版
  • 新浪微博