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

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

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

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

时间:2010-06-21 22:36来源: 作者: 点击:
它就是负载均衡算法的实现接口,为了便于说明在Discuz.EntLib中内置的两个负载均衡算法的实现情况,请先看下图: 内置的两个负载均衡算法,一个是RoundRobinScheduling,即轮叫调度(Round Robin Scheduling)算法

    
     它就是负载均衡算法的实现接口,为了便于说明在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.当主数据库被发布出去后,主数据库的表和存储过程就会被‘锁定’,其不允许被再次修改了,所以还要继续研究如何解决这一问题。

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