高并发场景下基于 Spring Boot 框架来实现 MySQL 读写分离(附源码)

总结

对于面试,一定要有良好的心态,这位小伙伴面试美团的时候没有被前面阿里的面试影响到,发挥也很正常,也就能顺利拿下美团的offer。
小编还整理了大厂java程序员面试涉及到的绝大部分面试题及答案,希望能帮助到大家,

在这里插入图片描述

在这里插入图片描述

最后感谢大家的支持,希望小编整理的资料能够帮助到大家!也祝愿大家都能够升职加薪!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

public class DataSourceRouter extends AbstractRoutingDataSource {

/**

  • 最终的determineCurrentLookupKey返回的是从DataSourceContextHolder中拿到的,因此在动态切换数据源的时候注解

  • 应该给DataSourceContextHolder设值

  • @return

*/

@Override

protected Object determineCurrentLookupKey() {

return DataSourceContextHolder.get();

}

}

三、数据源上下文环境

数据源上下文保存器,便于程序中可以随时取到当前的数据源,它主要利用ThreadLocal封装,因为ThreadLocal是线程隔离的,天然具有线程安全的优势。这里暴露了set和get、clear方法,set方法用于赋值当前的数据源名,get方法用于获取当前的数据源名称,clear方法用于清除ThreadLocal中的内容,因为ThreadLocal的key是weakReference是有内存泄漏风险的,通过remove方法防止内存泄漏;

/**

  • 利用ThreadLocal封装的保存数据源上线的上下文context

*/

public class DataSourceContextHolder {

private static final ThreadLocal context = new ThreadLocal<>();

/**

  • 赋值

  • @param datasourceType

*/

public static void set(String datasourceType) {

context.set(datasourceType);

}

/**

  • 获取值

  • @return

*/

public static String get() {

return context.get();

}

public static void clear() {

context.remove();

}

}

四、切换注解和Aop配置

首先我们来定义一个@DataSourceSwitcher注解,拥有两个属性①当前的数据源②是否清除当前的数据源,并且只能放在方法上,(不可以放在类上,也没必要放在类上,因为我们在进行数据源切换的时候肯定是方法操作),该注解的主要作用就是进行数据源的切换,在dao层进行操作数据库的时候,可以在方法上注明表示的是当前使用哪个数据源;

@DataSourceSwitcher注解的定义:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

@Documented

public @interface DataSourceSwitcher {

/**

  • 默认数据源

  • @return

*/

DataSourceEnum value() default DataSourceEnum.MASTER;

/**

  • 清除

  • @return

*/

boolean clear() default true;

}

DataSourceAop配置

为了赋予@DataSourceSwitcher注解能够切换数据源的能力,我们需要使用AOP,然后使用@Aroud注解找到方法上有@DataSourceSwitcher.class的方法,然后取注解上配置的数据源的值,设置到DataSourceContextHolder中,就实现了将当前方法上配置的数据源注入到全局作用域当中;

@Slf4j

@Aspect

@Order(value = 1)

@Component

public class DataSourceContextAop {

@Around(“@annotation(com.wyq.mysqlreadwriteseparate.annotation.DataSourceSwitcher)”)

public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {

boolean clear = false;

try {

Method method = this.getMethod(pjp);

DataSourceSwitcher dataSourceSwitcher = method.getAnnotation(DataSourceSwitcher.class);

clear = dataSourceSwitcher.clear();

DataSourceContextHolder.set(dataSourceSwitcher.value().getDataSourceName());

log.info(“数据源切换至:{}”, dataSourceSwitcher.value().getDataSourceName());

return pjp.proceed();

} finally {

if (clear) {

DataSourceContextHolder.clear();

}

}

}

private Method getMethod(JoinPoint pjp) {

MethodSignature signature = (MethodSignature) pjp.getSignature();

return signature.getMethod();

}

}

五、用法以及测试

在配置好了读写分离之后,就可以在代码中使用了,一般而言我们使用在service层或者dao层,在需要查询的方法上添加@DataSourceSwitcher(DataSourceEnum.SLAVE),它表示该方法下所有的操作都走的是读库;在需要update或者insert的时候使用@DataSourceSwitcher(DataSourceEnum.MASTER)表示接下来将会走写库。

其实还有一种更为自动的写法,可以根据方法的前缀来配置AOP自动切换数据源,比如update、insert、fresh等前缀的方法名一律自动设置为写库,select、get、query等前缀的方法名一律配置为读库,这是一种更为自动的配置写法。缺点就是方法名需要按照aop配置的严格来定义,否则就会失效

@Service

public class OrderService {

@Resource

private OrderMapper orderMapper;

/**

  • 读操作

  • @param orderId

  • @return

*/

@DataSourceSwitcher(DataSourceEnum.SLAVE)

public List getOrder(String orderId) {

return orderMapper.listOrders(orderId);

}

/**

  • 写操作

  • @param orderId

  • @return

*/

@DataSourceSwitcher(DataSourceEnum.MASTER)

public List insertOrder(Long orderId) {

Order order = new Order();

order.setOrderId(orderId);

return orderMapper.saveOrder(order);

}

}

六、总结

上面是基本流程简图,本篇博客介绍了如何实现数据库读写分离,注意读写分离的核心点就是数据路由,需要继承AbstractRoutingDataSource,复写它的determineCurrentLookupKey方法,同时需要注意全局的上下文管理器DataSourceContextHolder,它是保存数据源上下文的主要类,也是路由方法中寻找的数据源取值,相当于数据源的中转站.再结合jdbc-Template的底层去创建和管理数据源、事务等,我们的数据库读写分离就完美实现了。

作者:Yrion

cnblogs.com/wyq178/p/13352707.html

往期精选  点击标题可跳转

有没有搞错?Java 对象不使用时,为什么要赋值 null?

面试官问:Java 中如何处理含有泛型的 JSON 反序列化问题?

MySQL 数据库中 52 条 SQL 语句性能优化方法,干货必收藏!

“装 X ”就是牛,试一试 IDEA 解决 Maven 依赖冲突的超级神器!

如何用 Spring Cloud 构建面向企业的大型分布式、微服务快速开发框架?

代码总是被嫌弃写的太烂?装上这个 IDEA 插件再试试!

Java 中注解与反射的使用方法及场景分析,有必要解释一下!

终于来了,IDEA 2021.1 正式版本发布,一起看看又有哪些神奇功能!

你还在用 Logback ?Log4j2 功能与异步性能已经无敌了,还不快试试?
Spring Boot 项目不同环境打包配置与Shell脚本部署实践,太实用了!
Spring boot 项目中如何优雅停止服务的五种方法,值得收藏!
点个赞,就知道你“在看”!

最后

针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。

image

上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)

image

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

VSiKK8gD-1715720992879)]

上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)

[外链图片转存中…(img-jkzc4lRQ-1715720992880)]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值