实体
public class SlaveConfiguration
{
public string ConnectionString { get; set; }
public int Weight { get; set; }
public int Attach { get; set; }
}
轮巡算法接口
public interface ILoadBalancing
{
/// <summary>
/// 获取数据集合中的一条数据
/// </summary>
/// <param name="key">唯一标识,用于多数据库情况下的负载均衡</param>
/// <param name="slaves">从库数据库连接字符串集合</param>
/// <returns></returns>
string NextConnectionString(string key, IReadOnlyList<SlaveConfiguration> slaves);
}
随机轮巡算法
public class Randomer : ILoadBalancing
{
private readonly Random _random = new Random();
public string NextConnectionString(string key, IReadOnlyList<SlaveConfiguration> slaves)
{
if (slaves == null || slaves.Count == 0)
{
throw new ArgumentNullException(nameof(slaves));
}
int count = slaves.Count;
if (count == 1)
{
return slaves[0].ConnectionString;
}
return slaves[this._random.Next(count)].ConnectionString;
}
}
顺序轮巡算法
public class RoundRobiner : ILoadBalancing
{
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
private readonly ConcurrentDictionary<string, int> _indexDict = new ConcurrentDictionary<string, int>();
public string NextConnectionString(string key, IReadOnlyList<SlaveConfiguration> slaves)
{
if (slaves == null || slaves.Count == 0)
{
throw new ArgumentNullException(nameof(slaves));
}
int count = slaves.Count;
if (count == 1)
{
return slaves[0].ConnectionString;
}
string result = null;
try
{
this._lock.Wait();
key = $"{key}_{count}";
int index = this._indexDict.GetOrAdd(key, 0);
var slave = slaves[index];
index++;
if (index >= count)
{
index = 0;
}
this._indexDict[key] = index;
result = slave.ConnectionString;
}
finally
{
this._lock.Release();
}
return result;
}
}
权重轮巡算法
public class WeightedPoller : ILoadBalancing
{
private readonly SemaphoreSlim _lock = new SemaphoreSlim(1, 1);
public string NextConnectionString(string key, IReadOnlyList<SlaveConfiguration> slaves)
{
if (slaves == null || slaves.Count == 0)
{
throw new ArgumentNullException(nameof(slaves));
}
int count = slaves.Count;
if (count == 1)
{
return slaves[0].ConnectionString;
}
string result = null;
try
{
this._lock.Wait();
int index = -1;
int total = 0;
for (var i = 0; i < count; i++)
{
slaves[i].Attach += slaves[i].Weight;
total += slaves[i].Weight;
if (index == -1 || slaves[index].Attach < slaves[i].Attach)
{
index = i;
}
}
slaves[index].Attach -= total;
result = slaves[index].ConnectionString;
}
finally
{
this._lock.Release();
}
return result;
}
}