Druid07-高可用案例

1、简介

​ 当系统并发越来高时数据库服务器的压力也是越来越大,最终成为性能的瓶颈,可以采用缓存、读写分离、分库分表等技术来降低服务器压力,Druid 提供了高可用数据源 ( HighAvailableDataSource ) 是基于Druid数据源之上进行了二次封装,通过名称选择数据源的高可用数据源配置。

​ 数据源配置

 	@Bean(name = "masterDataSource", initMethod = "init", destroyMethod = "close")
    public DataSource masterDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverName);
        dataSource.setUrl(masterUrl);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean(name = "slaveDataSource", initMethod = "init", destroyMethod = "close")
    public DataSource slaveDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverName);
        dataSource.setUrl(slaveUrl);
        dataSource.setUsername(user);
        dataSource.setPassword(password);
        return dataSource;
    }

    @Bean(name = "haDataSource")
    @Primary
    public DataSource haDataSource(@Qualifier("masterDataSource") DataSource master, @Qualifier("slaveDataSource") DataSource slave) {
        HighAvailableDataSource haDataSource = new HighAvailableDataSource();
        haDataSource.setSelector(DataSourceSelectorEnum.BY_NAME.getName());
        Map<String, DataSource> dataSource = new ConcurrentHashMap<>();
        dataSource.put("default", master);
        dataSource.put("slave", slave);
        dataSource.put("master", master);
        haDataSource.setDataSourceMap(dataSource);
        return haDataSource;
    }

​ 使用自定义注解切换数据源

    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSource {
        String value() default "slave";
    }

​ AOP 选择数据源,使用后进行重置

    @Aspect
    @Component
    public class DataSourceAspect {
        @Pointcut("@annotation(com.manage.DataSource)")
        private void pointCut() {
        }
        
        @Autowired
        @Qualifier("haDataSource")
        private HighAvailableDataSource haDataSource;

        @Around("pointCut() && @annotation(dataSource)")
        public Object around(ProceedingJoinPoint joinPoint, DataSource dataSource) throws Throwable {
            String value = dataSource.value();
            if (StringUtils.isEmpty(value)) {
                return joinPoint.proceed();
            } else {
                DataSourceSelector dataSourceSelector = haDataSource.getDataSourceSelector();
                try {
                    haDataSource.setTargetDataSource(value);
                    return joinPoint.proceed();
                } finally {
                    if (dataSourceSelector instanceof NamedDataSourceSelector) {
                        NamedDataSourceSelector selector = (NamedDataSourceSelector) dataSourceSelector;
                        //重置连接池数据源
                        selector.resetDataSourceName();
                    }
                }
            }
        }
    }

使用场景

  1. 读写分离场景中,有多个数据库的从库提供读服务;
  2. 使用了分库分表中间件进行分库分表,部署了多台中间件服务;
  3. 以上实现目的是默认操作都使用主数据源,使用注解标记的使用从库数据源,从而实现读写分离。
2、路由选择-selector
  1. byName 名称的数据源选择。
  2. random 随机的数据源选择 (默认)。
  3. stickyRandom 粘性随机数据源选择 (同一线程中多次通过HighAvailableDataSource 获取连接时始终会返回同一个数据源)。
3、随机节点的健康检查

​ 在使用随机的数据源选择(random)或粘性随机数据源选择(stickyRandom)时,HighAvailableDataSource 会检查后端节点的健康状态。

  1. druid.ha.random.checkingIntervalSeconds 设定健康检查的间隔时间
  2. 针对每个节点,使用数据源的配置信息新建后端节点的数据库连接,调用dataSource.validateConnection() 方法检查连接状态,完成检查后关闭新建的连接
  3. druid.ha.random.blacklistThreshold 节点连续健康检查失败多少次后会被加入黑名单
  4. 黑名单会有另外一个线程进行探活检查druid.ha.random.recoveryIntervalSeconds 每隔多少秒进行一次探活,如果探活成功,则会将其从黑名单中移除
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值