`

Discuz!NT数据库读写分离方案-2

阅读更多

原文 http://www.cnblogs.com/daizhj/archive/2010/06/21/dbsnap_master_slave_database.html

 

   
       当然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();
    }

 

    
    它就是负载均衡算法的实现接口,为了便于说明在Discuz.EntLib中内置的两个负载均衡算法的实现情况,请先看下图:    
    
    
       内置的两个负载均衡算法,一个是RoundRobinScheduling,即轮叫调度(Round Robin Scheduling)算法,它的实现比较简单,就是对从数据库链接列表的依次遍历,如下:

代码
///   <summary>
///  轮叫调度(Round Robin Scheduling)算法
///   </summary>
public   class  RoundRobinScheduling : ILoadBalanceScheduling
{
    
private   static   object  lockHelper  =   new   object ();
    
///   <summary>
    
///  当前的快照索引和权重信息
    
///   </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 ++ ];
        }
    }
}

 

   
   
     而另一种负载均衡算法就相对负载了,不过它也更符合实际的应用场景,它使用了权重的方法来让性能优良的机器分到
更多的任务来均衡整个方案的性能,即权重轮询调度算法,实现代码如下:

 

代码
///   <summary>
///  权重轮询调度算法 
///   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>
    
///  快照的权重列表
    
///   </summary>
     static  List < int >  snapWeightList  =   new  List < int > ();
    
///   <summary>
    
///  当前的快照索引和权重信息
    
///   </summary>
     static   int  curentSnapIndex, currentWeight;
    
///   <summary>
    
///  快照权重列表中最大的权重值和最大公约数
    
///   </summary>
     static   int  maxWeight, gcd;

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

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

    
///   <summary>
    
///  获取应用当前负载均衡调度算法下的快照链接信息
    
///   </summary>
    
///   <returns></returns>
     public   DbSnapInfo GetConnectDbSnap()
    {
        
lock  (lockHelper)
        {
            DbSnapInfo current 
=  RoundRobinScheduling();
            
if  (current  !=   null )
                
return  current;
            
else
                
return  DbSnapConfigs.GetEnableSnapList()[ 0 ];
        }
    }

    
///   <summary>
    
///  获取快照权重的列表
    
///   </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>
    
///  权重轮询调度算法
    
///   </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>
    
///  获取最大权重
    
///   </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>
    
///  获取权重的最大公约数
    
///   </summary>
    
///   <returns></returns>
     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>
    
///  实现IComparer接口,用于对数字列表进行排序
    
///   </summary>   
     private   class  WeightCompare : System.Collections.Generic.IComparer < int >
    {
        
public   int  Compare( int  weightA,  int  weightB)
        {
            
return  weightA  -  weightB;
        }
    }
}

 

        到这里,主要的功能代码就介绍的差不多了,我们可以通过对dbsnap.config的相应节点配置,来灵活定制我们的负载均衡方案。同时,对一般开发者 而言,这种架构是透明的,大家可以完全在不了解它的情况下开发自己的数据访问功能,并通过相应开关来让自己的代码支持均衡负载。

        当然这个方案还有一些没考虑到的问题比如:
        1.对‘主从数据库的健康度检查’,即如果主或从数据库出现故障的时候该如何处理,当然在sqlserver中还提供了镜像功能 来解决类似问题,所以它也可做为一个备选方案。

        2.当主数据库被发布出去后,主数据库的表和存储过程就会被‘锁定’,其不允许被再次修改了,所以还要继续研究如何解决这一问题。

 

分享到:
评论

相关推荐

    Discuz!NT数据库读写分离方案详解

    当然这也是许多大型网站不断研究探索各式各样的方案来有效降低数据访问负荷的原 因, 其中的‘读写分离’方案就是一种被广泛采用的方案。 Discuz!NT这个产品在其企业版中提供了对‘读写分离’机制的支持,使对CPU...

    Discuz!NT v3.6.601 build 0714

    NT 3.1版本为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。Discuz!NT v3.6.601 build 0714 修复的问题删除7天帖时间期限失效编辑置顶...

    Discuz!NT v3.9 beta

    NT 为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。Discuz!NT v3.9 带来了多达百项的变动:云平台基础和QQConnect后台集成帖子调用...

    Discuz!NT v3.5.1 优秀的ASP.net社区论坛.rar

    NT 3.1版本为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。 2011-02-22 更新 修复错误(BUG): green和black模板在聚合首页报错 聚合...

    Discuz!NT 3.1正式版源码

    Discuz!NT 3.1版本功能亮点十足,安装、升级流程全面改善,产品安装升级...NT 3.1版本为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。

    Discuz!NT3.1免安装版源码

    NT 3.1版本为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。 新增功能列表 全新的门户化聚合首页 游客发帖时,帖子页面直接显示游客...

    Discuz!NT 3.1免安装版(0428)源码

    NT 3.1版本为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。 新增功能列表 1、全新的门户化聚合首页 2、游客发帖时,帖子页面直接...

    Discuz!NT官方版下载 v3.9 beta

    NT 为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。 Discuz!NT v3.9 带来了多达百项的变动: 云平台基础和QQConnect 后台集成帖子调用...

    discuz!nt 3.6.601 .net版论坛程序

    NT3.1版本为项目用户专门开发了负载均衡、数据库读写分离、分布式缓存和检测工具一系列套件,为超大型社区建设提供了完美的技术解决方案。 Discuz!NTv3.6.601修复的问题 游客查看附件的样式不正确 编辑器转义了不应...

    Discuz!NT 论坛 v3.5.2

    内容索引:.NET源码,论坛社区,Discuz,论坛 Discuz!NT是Discuz论坛的版,目前...NT就已具备了为其专门开发的负载均衡、数据库读写分离、分布式缓存和检测工具等一系列套件,为超大型社区建设提供了完美的技术解决方案。

Global site tag (gtag.js) - Google Analytics