美文网首页
Spring实现数据库读写分离

Spring实现数据库读写分离

作者: 田真的架构人生 | 来源:发表于2018-08-01 20:40 被阅读0次

数据库读写分离是最基本的DB扩展方式,我们可以在应用中自己实现,决定什么业务访问写库,什么业务访问读库。
Spring提供了一套机制可以声明式地实现读写分离,简化我们的开发。下面把最主要的几块列出来。
1,AbstractRoutingDataSource,这是Spring提供的最核心的组件,由它来管理所有的写库、读库,并统一对外提供dataSource。
在这里,DynamicDataSource继承了AbstractRoutingDataSource,并在配置中指明了所有的读写库。dynamicDs_galaxy就是统一对外提供的dataSource,
之后,注入DAO、transaction管理,都将使用dynamicDs_galaxy。

在代码里实现determineCurrentLookupKey方法,该方法就一个作用:获取key,以便根据key获取哪个datasource。
点击(此处)折叠或打开
package com.sogou.earth.api.common.db;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public final class DynamicDataSource extends AbstractRoutingDataSource {

private static final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);

protected Object determineCurrentLookupKey() {
    Object object = DynamicDataSourceKeyHolder.getDataSourceKey();
    logger.debug("determineCurrentLookupKey:" + object);
    return object;
}

}

2,DynamicDataSourceInterceptor,这是个拦截器,最终会以advice的形式拦截所有需要访问DB的业务,它的作用是给需要DB访问的业务分配一个key,
这个key用来determineCurrentLookupKey,最终确定访问哪个dataSource。
点击(此处)折叠或打开

            query*,slave
            count*,slave
            find*,slave
            get*,slave
            list*,slave
            *,master

代码:根据业务方法名来分配key。
点击(此处)折叠或打开
package com.sogou.earth.api.common.db;

import java.util.ArrayList;
import java.util.List;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.PatternMatchUtils;

/**

  • 设置数据源KEY的拦截器

*/
public class DynamicDataSourceInterceptor implements MethodInterceptor {

private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceInterceptor.class);
/**
 * 方法和使用数据源key的对应关系
 */
private List attributeSource = new ArrayList();

public Object invoke(MethodInvocation invocation) throws Throwable {
    final String methodName = invocation.getMethod().getName();
    String key = null;
    for (String value : attributeSource) {
        String mappedName = value.split(\",\")[0];
        if (isMatch(methodName, mappedName)) {
            key = value.split(\",\")[1];
            break;
        }
    }
    logger.debug(\"methodName:\" + methodName);
    if (null != key) {
        DynamicDataSourceKeyHolder.setKey(key);
    }

    return invocation.proceed();
}

private boolean isMatch(String methodName, String mappedName) {
    return PatternMatchUtils.simpleMatch(mappedName, methodName);
}

public List getAttributeSource() {
    return attributeSource;
}

public void setAttributeSource(List attributeSource) {
    this.attributeSource = attributeSource;
}

}

DynamicDataSourceKeyHolder里面持有ThreadLocal,是线程安全的。
点击(此处)折叠或打开
package com.sogou.earth.api.common.db;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DynamicDataSourceKeyHolder {

private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceKeyHolder.class);

private static final ThreadLocal dataSourceHolder = new ThreadLocal();

public static void setKey(String key) {
    dataSourceHolder.set(key);
}

public static String getDataSourceKey() {
    return (String) dataSourceHolder.get();
}

}

相关文章

网友评论

      本文标题:Spring实现数据库读写分离

      本文链接:https://www.haomeiwen.com/subject/qhtulxtx.html