dynamic-datasource-spring-boot-starter 组件自带了两个负载均衡算法1:
LoadBalanceDynamicDataSourceStrategy 轮询。
RandomDynamicDataSourceStrategy 随机。
其中轮询是默认算法。
这两个算法类都实现了 DynamicDataSourceStrategy 接口:
所以如果需要自定义负载均衡算法,就可以实现DynamicDataSourceStrategy 接口。该接口只定义了一个determineDataSource方法,用于决定多个数据源的选择策略:
public interface DynamicDataSourceStrategy {
/**
* determine a database from the given dataSources
*
* @param dataSources given dataSources
* @return final dataSource
*/
DataSource determineDataSource(List<DataSource> dataSources);
}
(1)轮询算法
public class LoadBalanceDynamicDataSourceStrategy implements DynamicDataSourceStrategy {
/**
* 负载均衡计数器
*/
private final AtomicInteger index = new AtomicInteger(0);
@Override
public DataSource determineDataSource(List<DataSource> dataSources) {
return dataSources.get(Math.abs(index.getAndAdd(1) % dataSources.size()));
}
}
这里利用 AtomicInteger 类创建了一个线程安全2的 Integer作为计数器,默认为 0。
然后在 determineDataSource 实现方法中,利用 AtomicInteger#getAndAdd() 累加该计算器,接着把结果值除以数据源总数,求余数。
这里的 Math.abs() 似乎没有必要,因为被除数与除数肯定大于 0。
可以改造如下:
/**
* 计数器增长量
*/
public static final int INCREASE_AMOUNT = 1;
/**
* 计数器
*/
private final AtomicInteger counter = new AtomicInteger(0);
@Override
public DataSource determineDataSource(List<DataSource> dataSources) {
int newValue = counter.getAndAdd(INCREASE_AMOUNT);
int nextIndex = newValue % dataSources.size();
return dataSources.get(nextIndex);
}
(2)随机算法
public class RandomDynamicDataSourceStrategy implements DynamicDataSourceStrategy {
@Override
public DataSource determineDataSource(List<DataSource> dataSources) {
return dataSources.get(ThreadLocalRandom.current().nextInt(dataSources.size()));
}
}
这里使用了ThreadLocalRandom 来生成线程安全的随机数3,current() 方法是其静态工厂。