我的编程空间,编程开发者的网络收藏夹
学习永远不晚

数据源管理 | 主从库动态路由,AOP模式读写分离

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

数据源管理 | 主从库动态路由,AOP模式读写分离

本文源码:GitHub·点这里 || GitEE·点这里

一、多数据源应用

1、基础描述

在相对复杂的应用服务中,配置多个数据源是常见现象,例如常见的:配置主从数据库用来写数据,再配置一个从库读数据,这种读写分离模式可以缓解数据库压力,提高系统的并发能力和稳定性,执行效率。

数据源管理 | 主从库动态路由,AOP模式读写分离

2、核心API

在处理这种常见问题,要学会查询服务基础框架的API,说直白点就是查询Spring框架的API(工作几年,还没用过Spring之外的框架搭建环境),这种常用的业务模式,基本上Spring都提供了API支持。

核心API:AbstractRoutingDataSource

底层维护Map容器,用来保存数据源集合,提供一个抽象方法,实现自定义的路由策略。

@Nullableprivate Map<Object, DataSource> resolvedDataSources;@Nullableprotected abstract Object determineCurrentLookupKey();

补刀一句:为何框架的原理很难通过一篇文章看明白?因为使用的不多,基本意识没有形成,熟悉框架原理的基本要求:对框架的各种功能都熟悉,经常使用,自然而然的就明白了,盐大晒的久,咸鱼才够味。

二、数据源路由

1、数据源管理

配置两个数据源

spring:  datasource:    type: com.alibaba.druid.pool.DruidDataSource    driverClassName: com.mysql.jdbc.Driver    master:      url: jdbc:mysql://localhost:3306/data_master      username: root      password: 123456    slave:      url: jdbc:mysql://localhost:3306/data_slave      username: root      password: 123456

从实际开发角度,这两个数据源需要配置主从复制流程,再基于安全角度,写库可以只给写权限,读库只给读权限。

Map容器加载

@Configurationpublic class DruidConfig {    // 忽略参数加载,源码中有    @Bean    @Primary    public DataSource primaryDataSource() {        Map<Object, Object> map = new HashMap<>();        map.put("masterDataSource", masterDataSource());        map.put("slaveDataSource", slaveDataSource());        RouteDataSource routeDataSource = new RouteDataSource();        routeDataSource.setTargetDataSources(map);        routeDataSource.setDefaultTargetDataSource(masterDataSource());        return routeDataSource ;    }    private DataSource masterDataSource() {        return getDefDataSource(masterUrl,masterUsername,masterPassword);    }    private DataSource slaveDataSource() {        return getDefDataSource(slaveUrl,slaveUsername,slavePassword);    }    private DataSource getDefDataSource (String url,String userName,String passWord){        DruidDataSource datasource = new DruidDataSource();        datasource.setDriverClassName(driverClassName);        datasource.setUrl(url);        datasource.setUsername(userName);        datasource.setPassword(passWord);        return datasource;    }}

这里的Map容器管理两个key,masterDataSource和slaveDataSource代表两个不同的库,使用不同的key即加载对应的库。

2、容器Key管理

使用ThreadLocal管理当前会会话中线程参数,存取使用极其方便。

public class RouteContext implements AutoCloseable {    private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();    public static void setRouteKey (String key){        threadLocal.set(key);    }    public static String getRouteKey() {        String key = threadLocal.get();        return key == null ? "masterDataSource" : key;    }    @Override    public void close() {        threadLocal.remove();    }}

3、路由Key实现

获取ThreadLocal中,当前数据源的key,适配相关联的数据源。

public class RouteDataSource extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return RouteContext.getRouteKey();    }}

三、读写分离

1、AOP思维

基于AOP的切面思想,不同的方法类型,去设置对应路由Key,这样就可以在业务逻辑执行之前,切换到不同的数据源。

Aspect@Component@Order(1)public class ReadWriteAop {    private static Logger LOGGER = LoggerFactory.getLogger(ReadWriteAop.class) ;    @Before("execution(* com.master.slave.controller.*.*(..))")    public void setReadDataSourceType() {        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();        String method = request.getRequestURI() ;        boolean rwFlag = readOrWrite(method) ;        if (rwFlag){            RouteContext.setRouteKey("slaveDataSource");        } else {            RouteContext.setRouteKey("masterDataSource");        }        LOGGER.info("请求方法:"+method+";执行库:"+RouteContext.getRouteKey());    }    private String[] readArr = new String[]{"select","count","query","get","find"} ;    private boolean readOrWrite (String method){        for (String readVar:readArr) {            if (method.contains(readVar)){                return true ;            }        }        return false ;    }}

常见的读取方法:select、count、query、get、find等等,方法的命名要遵循自定义的路由规则。

2、提供测试接口

控制层API

import com.master.slave.entity.User;import com.master.slave.service.UserService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestControllerpublic class UserController {    @Resource    private UserService userService ;    @GetMapping("/selectById")    public User selectById (@RequestParam("id") Integer id) {        return userService.selectById(id) ;    }    @GetMapping("/insert")    public String insert () {        User user = new User("张三","write") ;        userService.insert(user) ;        return "success" ;    }}

服务实现

@Servicepublic class UserService {    @Resource    private UserMapper userMapper ;    public User selectById (Integer id) {        return userMapper.selectById(id) ;    }    public void insert (User user){        userMapper.insert(user);    }}

这样数据源基于不同的类型方法就会一直的动态切换。

四、源代码地址

GitHub·地址https://github.com/cicadasmile/data-manage-parentGitEE·地址https://gitee.com/cicadasmile/data-manage-parent

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

数据源管理 | 主从库动态路由,AOP模式读写分离

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

数据源管理 | 主从库动态路由,AOP模式读写分离

本文源码:GitHub·点这里 || GitEE·点这里一、多数据源应用1、基础描述在相对复杂的应用服务中,配置多个数据源是常见现象,例如常见的:配置主从数据库用来写数据,再配置一个从库读数据,这种读写分离模式可以缓解数据库压力,提高系统
2023-06-02

Docker搭建MySQL读写分离主从模式 & 分布式数据库中间件Mycat分库分表应用

一、MySQL读写分离主从模式1. 下载镜像docker pull mysql当前最新版本:mysql Ver 8.0.19 for Linux on x86_64 (MySQL Community Server - GPL)2. 启动主节点并修改配置文件d
Docker搭建MySQL读写分离主从模式 & 分布式数据库中间件Mycat分库分表应用
2016-10-09

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录