
springboot+mysql读写分离
发布日期:2021-05-27 02:54:11
浏览次数:2
分类:技术文章
本文共 7582 字,大约阅读时间需要 25 分钟。
在javaweb开发中数据库表数据量会越来越大,为了减轻数据库读写压力,对数据库进行主从模式部署(一主一从,多主多从),在应用层面可以通过spring提供的路由数据源+注解+切面进行控制,在代码层面切换不同数据库源,不同操作选择不同数据库。
代码如下:
com.alibaba druid-spring-boot-starter 1.1.9 org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 mysql mysql-connector-java
spring.datasource.master.url=jdbc:mysql://localhost:3306/master?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=falsespring.datasource.master.username=rootspring.datasource.master.password=123456spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.slave.url=jdbc:mysql://localhost:3306/slave?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=falsespring.datasource.slave.username=rootspring.datasource.slave.password=123456spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, TransactionAutoConfiguration.class})@MapperScan("com.*.mapper")public class AnnotationAopReflectionApplication { public static void main(String[] args) { SpringApplication.run(AnnotationAopReflectionApplication.class, args); }}
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic @interface DataSourceAnnotation { /** * 默认数据源 */ DataSourceEnum value() default DataSourceEnum.MASTER; /** * 清除 */ boolean clear() default true;}public enum DataSourceEnum { //数据源主库、从库 MASTER("1","master"), SLAVE("2","slave"); private String code; private String name; private DataSourceEnum(String code,String name){ this.code = code; this.name = name; } public static DataSourceEnum getByCode(String code) { for (DataSourceEnum event : DataSourceEnum.values()) { if (event.code.equals(code)) { return event; } } return null; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; }}public class DataSourceContextHolder { private static final ThreadLocalcontext = new ThreadLocal<>(); /** * 赋值 */ public static void set(String datasourceType) { context.set(datasourceType); } /** * 获取值 */ public static String get() { return context.get(); } /** * 清空 */ public static void clear() { context.remove(); }}public class RoutingDataSource extends AbstractRoutingDataSource { /** * 最终的determineCurrentLookupKey返回的是从DataSourceContextHolder中拿到的,因此在动态切换数据源的时候注解 * 应该给DataSourceContextHolder设值 */ @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.get(); }}@Configuration@MapperScan(basePackages = "com.", sqlSessionTemplateRef = "sqlSessionTemplate")public class DataSourceConfig { /** * 主库 */ @Bean @ConfigurationProperties(prefix = "spring.datasource.master") public DataSource master() { return DruidDataSourceBuilder.create().build(); } /** * 从库 */ @Bean @ConfigurationProperties(prefix = "spring.datasource.slave") public DataSource slaver() { return DruidDataSourceBuilder.create().build(); } /** * 实例化数据源路由 */ @Bean public RoutingDataSource routingDataSource(@Qualifier("master") DataSource masterDataSource,@Autowired(required = false) @Qualifier("slaver") DataSource slaveDataSource) { RoutingDataSource routingDataSource = new RoutingDataSource(); Map
@Servicepublic class DemoService { @Autowired private UserMapper userMapper; @Autowired private AuthUserMapper authUserMapper; /** * 读操作 */ @DataSourceAnnotation(DataSourceEnum.SLAVE) public AuthUser getAuthUser() { String userId = "001"; AuthUser authUser = authUserMapper.getAuthUserById(userId); //User user = userMapper.getUserById(1); return authUser; } /** * 写操作 */ @DataSourceAnnotation(DataSourceEnum.MASTER) public User updateUser() { User user = userMapper.getUserById(1); return user; }}@RestControllerpublic class DemoController { @Autowired private DemoService demoService; @GetMapping("/readSlave") public Object readSlave() { return demoService.getAuthUser(); } @GetMapping("/writeMaster") public Object writeMaster() { return demoService.updateUser(); }}
前提是部署好mysql主从数据库或准备不同数据库。注意读写分离的核心点就是数据路由,需要继承AbstractRountingDataSource,覆写它的determinCurrentLookupKey方法,同时需要注意全局的上下文管理器DataSourceContextHolder,它是保存数据源上下文的主要类,也是路由方法中寻找的数据源取值,相当于数据源的中转站,此例配置了3个数据源。再结合jdbc底层、事务等,数据库读写分离就实现了。
转载地址:https://blog.csdn.net/leijie0322/article/details/112589287 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2023年11月26日 22时22分14秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
[PythonCookBook][并发] 判断线程启动与否的方法
2019-03-25
[云数据中心] 《云数据中心网络架构与技术》读书笔记 第八章 构建云数据中心端到端安全
2019-03-25
【哲学向】《反脆弱》一书带给我的启示(5)
2019-03-25
【哲学向】《反脆弱》一书带给我的启示(5.1. 时间和脆弱性)
2019-03-25
【心理学向】《思考,快与慢》带给我的启示(1)
2019-03-25
[SRv6]《SRv6网络编程》SRv6网络的演进
2019-03-25
N1文法「第1-第5」
2019-03-25
【日语】【歌词】「ヤキモチ」--高橋優
2019-03-25
[SRv6]《SRv6网络编程》SRv6网络在电信云中的应用
2019-03-25
[SRv6]《SRv6网络编程》SRv6网络在SD-WAN中的应用
2019-03-25
[SRv6]《SRv6网络编程》SRv6 OAM与随路网络测量(1/2:OAM)
2019-03-25
[转载] 最深的云网融合:多接入边缘计算(MEC)
2019-03-25
[SRv6]《SRv6网络编程》SRv6 OAM与随路网络测量(2/2:IFIT)
2019-03-25
【日语】【歌词】「Lemon」--米津玄师
2019-03-25
[5GC]《5G核心网-赋能数字化时代》| 6.3用户面处理
2019-03-25
Clion安装配置(Windows)
2019-03-25