建站学 - 轻松建站从此开始!

建站学-个人建站指南,网页制作,网站设计,网站制作教程

当前位置: 建站学 > 建站指南 > 建站经验 >

Discuz!NT论坛数据库读写分离方案(2)

时间:2010-06-21 22:36来源: 作者: 点击:
它主要是通过反射的方法将Discuz.EntLib.dll文件中的相应负载均衡算法实例进行绑定,然后以m_loadBalanceSche这个静态变量进行保存,而m_loadBalanceSche本身就是ILoadBalanceScheduling接口变量,该接口即是相应负

       它主要是通过反射的方法将Discuz.EntLib.dll文件中的相应负载均衡算法实例进行绑定,然后以m_loadBalanceSche这个静态变量进行保存,而m_loadBalanceSche本身就是ILoadBalanceScheduling接口变量,该接口即是相应负载均衡算法的实现接口。同样因为文章内容的连续性,这里先不深挖相应的实现算法,我会在后面进行介绍。下面再来看一下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;

 

     
     上面代码将当前的负载均衡得到的链接串保存到一个snapLogList列表中,该列表声明如下:     
    

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

 

     
      为什么要提供这个列表并进行记录?主要是为了考查负载均衡算法的工作情况,因为在数据访问层获取相应链接串信息并进行记录很不方便,所以我用这个变量记录大约400条‘负载均衡’数据链接串,以便在相应的Discuz.EntLib.ToolKit工具包中进行观察,监视其‘工作情况’。这里我们只要知道通过GetRealConnectionString()方法就实现了对sql语句或存储过程进行分析并进行负载均衡的效果了(注:该操作可能会耗时,所以在DbSnapConfigs中提供了一个开关‘RecordeLog’来进行控制,后面会介绍)。
    

     下面再来简单介绍一下,如何改造DbHelper.cs中原有方法,使其支持负载均衡功能。这里强调一点,就是:
    
     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);//负载均衡改造完成的方法
    connection.Open();

    
// 创建DbCommand命令,并进行预处理

    DbCommand cmd = Factory.CreateCommand();

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

    
// 执行DbCommand命令,并返回结果.

    object retval = cmd.ExecuteScalar();

    
// 清除参数,以便再次使用.

    cmd.Parameters.Clear();

    
if
 (mustCloseConnection)
        connection.Close();

    
return
 retval;
}

    
      上面的 ‘connection.ConnectionString =’之前绑定的ConnectionString这个静态属性,而这个属性链接的就是‘主数据库’,
这里我们只要将GetRealConnectionString(commandText)赋值给它就可以了,还是那句话,在GetRealConnectionString()就实现了
数据库链接串的负载均衡,呵呵。类似上面的变动在DbHelper.cs还有几处,好在变化不太大,当然更不需要改变原有的数据访问层
(比如IDataProvider.cs文件)了。

      其实本文中介绍的数据库层负载均衡实现方法在MYSQL中早有相应的插件实现了,参见这篇文章。      
  

     

 

 

        该文章中的LUA脚本实现方式与本文类似,如下:    
    

代码
--发送所有的非事务性SELECT到一个从数据库
    
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]
           
--
 选择一个拥有空闲连接的从数据库
           
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
    .....

      接着,我再介绍一下相应的配置文件和负载均衡算法的实现情况:)
   
   
      配置文件(比如: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就是相应的slave数据库链接列表,其中它的相应节点信息说明如下(Discuz.Config\DbSnapInfo.cs):     

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

    
/// 源ID,用于唯一标识快照在数据库负载均衡中的信息
    
/// </summary>

    private int _souceID;
    
/// <summary>

    
/// 源ID,用于唯一标识快照在数据库负载均衡中的信息
    
/// </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>

    
/// 权重信息,该值越高则意味着被轮循到的次数越多
    
/// </summary>

    private int _weight;
    
/// <summary>

    
/// 权重信息,该值越高则意味着被轮循到的次数越多
    
/// </summary>

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

 
      
       当然DbSnapAppConfig作为DbSnapInfo列表的容器,其结构如下:    

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

    
/// 是否启用快照,如不使用,则即使DbSnapInfoList已设置有效快照信息也不会使用。
    
/// </summary>

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

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

    
/// 写操作等待时间(单位:秒), 说明:在执行完写操作之后,在该时间内的sql请求依旧会被发往master数据库
    
/// </summary>

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

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

    
/// 负载均衡调度算法,默认为权重轮询调度算法 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; }
    }
}

    通过这两个配置文件,就可以实现对数据访问层负载均衡的灵活配置了,不过上面的DbSnapAppConfig还有一个非常重要的
属性没有介绍清楚,就是‘LoadBalanceScheduling’,其接口声明如下:

代码
    /// <summary>
    
///  负载均衡调度接口
    
/// </summary>

    public interface ILoadBalanceScheduling
    {
        
/// <summary>

        
/// 获取应用当前负载均衡调度算法下的快照链接信息
        
/// </summary>

        
/// <returns></returns>
        DbSnapInfo GetConnectDbSnap();
    }
(责任编辑:admin)
织梦二维码生成器
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
推荐内容