• 首页
  • 博客
  • 专栏·视频
  • 下载
  • 论坛
  • 问答
  • 代码
  • 直播
  • 能力认证
  • 高校

会员中心

收藏

动态

消息

创作中心

02-下篇-SpringBoot下MySQL的读写分离

dusuanyun 2018-07-16 09:03:30  3095  收藏 3

分类专栏: 应用配置 文章标签: SpringBoot MySQL读写分离 SpringDataJPA AOP

版权

前言:关于MySQL读写主从实现,分两步:

第一步,需要现有主从的环境,利用docker快速实现; -----上篇

第二步,利用已有的环境进行JavaEE的Web项目配置。 -----下篇,基于SpringBoot的SpringDataJpa的实现!即本文

环境:

SpringBoot:2.0.3 DB:MySQL5.7.20 主从模式

持久化框架:SpringDataJpa

1.多数据源的配置application.yml:

 
  1. #####MySQL数据库的主从配置开始#####

  2. mysql:

  3. datasource:

  4. readSize: 1 #读库个数,可以有多个

  5. type: com.alibaba.druid.pool.DruidDataSource

  6. write:

  7. url: jdbc:mysql://192.168.1.121:3306/db_frms?useUnicode=true&characterEncoding=utf-8

  8. username: root

  9. password: 123456

  10. driver-class-name: com.mysql.jdbc.Driver

  11. minIdle: 5

  12. maxActive: 100

  13. initialSize: 10

  14. maxWait: 60000

  15. timeBetweenEvictionRunsMillis: 60000

  16. minEvictableIdleTimeMillis: 300000

  17. validationQuery: select 'x'

  18. testWhileIdle: true

  19. testOnBorrow: false

  20. testOnReturn: false

  21. poolPreparedStatements: true

  22. maxPoolPreparedStatementPerConnectionSize: 50

  23. removeAbandoned: true

  24. filters: stat

  25. read01:

  26. url: jdbc:mysql://192.168.1.121:3307/db_frms?useUnicode=true&characterEncoding=utf-8

  27. username: root

  28. password: 123456

  29. driver-class-name: com.mysql.jdbc.Driver

  30. minIdle: 5

  31. maxActive: 100

  32. initialSize: 10

  33. maxWait: 60000

  34. timeBetweenEvictionRunsMillis: 60000

  35. minEvictableIdleTimeMillis: 300000

  36. validationQuery: select 'x'

  37. testWhileIdle: true

  38. testOnBorrow: false

  39. testOnReturn: false

  40. poolPreparedStatements: true

  41. maxPoolPreparedStatementPerConnectionSize: 50

  42. removeAbandoned: true

  43. filters: stat

  44. # read02: #因为我只用docker配置了一个slave,所以没有第二个slave,故这段配置注释掉!

  45. # url: jdbc:mysql://192.168.1.121:3308/test_02?useUnicode=true&characterEncoding=utf-8

  46. # username: root

  47. # password: root

  48. # driver-class-name: com.mysql.jdbc.Driver

  49. # minIdle: 5

  50. # maxActive: 100

  51. # initialSize: 10

  52. # maxWait: 60000

  53. # timeBetweenEvictionRunsMillis: 60000

  54. # minEvictableIdleTimeMillis: 300000

  55. # validationQuery: select 'x'

  56. # testWhileIdle: true

  57. # testOnBorrow: false

  58. # testOnReturn: false

  59. # poolPreparedStatements: true

  60. # maxPoolPreparedStatementPerConnectionSize: 50

  61. # removeAbandoned: true

  62. # filters: stat

  63. #####MySQL数据库的主从配置结束#####

2.定义数据库的类型枚举类DataSourceType

 
  1. package com.ddbin.frms.config.datasource;

  2. import lombok.AllArgsConstructor;

  3. import lombok.Getter;

  4. /**

  5. * Description:数据源类型的枚举类

  6. *

  7. * @param

  8. * @author dbdu

  9. * @date 18-7-14 上午8:05

  10. */

  11. @Getter

  12. @AllArgsConstructor

  13. public enum DataSourceType {

  14. read("read", "从库"), write("write", "主库");

  15. /**

  16. * Description:类型,是读还是写

  17. *

  18. * @author dbdu

  19. * @date 18-7-14 上午8:14

  20. */

  21. private String type;

  22. /**

  23. * Description:数据源的名称

  24. *

  25. * @author dbdu

  26. * @date 18-7-14 上午8:15

  27. */

  28. private String name;

  29. }

要注意的是:枚举实例小写,大写会报错!!

read("read", "从库"), write("write", "主库");

3.多个数据源的实例化配置类DataSourceConfiguration

有多少个数据源,就配置多少个对应的Bean。

 
  1. package com.ddbin.frms.config.datasource;

  2. import lombok.extern.slf4j.Slf4j;

  3. import org.springframework.beans.factory.annotation.Value;

  4. import org.springframework.boot.context.properties.ConfigurationProperties;

  5. import org.springframework.boot.jdbc.DataSourceBuilder;

  6. import org.springframework.context.annotation.Bean;

  7. import org.springframework.context.annotation.Configuration;

  8. import org.springframework.context.annotation.Primary;

  9. import javax.sql.DataSource;

  10. /**

  11. * Description:MySQL读写主从数据库源配置

  12. *

  13. * @param

  14. * @author dbdu

  15. * @date 18-7-14 上午7:51

  16. * @return

  17. */

  18. @Configuration

  19. @Slf4j

  20. public class DataSourceConfiguration {

  21. @Value("${mysql.datasource.type}")

  22. private Class<? extends DataSource> dataSourceType;

  23. /**

  24. * 写库 数据源配置

  25. *

  26. * @return

  27. */

  28. @Bean(name = "writeDataSource")

  29. @Primary

  30. @ConfigurationProperties(prefix = "mysql.datasource.write")

  31. public DataSource writeDataSource() {

  32. log.info("writeDataSource init ...");

  33. return DataSourceBuilder.create().type(dataSourceType).build();

  34. }

  35. /**

  36. * 有多少个从库就要配置多少个

  37. *

  38. * @return

  39. */

  40. @Bean(name = "readDataSource01")

  41. @ConfigurationProperties(prefix = "mysql.datasource.read01")

  42. public DataSource readDataSourceOne() {

  43. log.info("read01 DataSourceOne init ...");

  44. return DataSourceBuilder.create().type(dataSourceType).build();

  45. }

  46. // @Bean(name = "readDataSource02")

  47. // @ConfigurationProperties(prefix = "mysql.datasource.read02")

  48. // public DataSource readDataSourceTwo() {

  49. // log.info("read02 DataSourceTwo init ...");

  50. // return DataSourceBuilder.create().type(dataSourceType).build();

  51. // }

  52. }

4.配置数据源的切换类DataSourceContextHolder

设置这个类的对应的read和write,就被内部用来读取不同的数据源

 
  1. package com.ddbin.frms.config.datasource;

  2. import lombok.extern.slf4j.Slf4j;

  3. /**

  4. * Description:本地线程,数据源上下文切换

  5. *

  6. * @author dbdu

  7. * @date 18-7-14 上午8:17

  8. */

  9. @Slf4j

  10. public class DataSourceContextHolder {

  11. //线程本地环境

  12. private static final ThreadLocal<String> local = new ThreadLocal<String>();

  13. public static ThreadLocal<String> getLocal() {

  14. return local;

  15. }

  16. /**

  17. * 读库

  18. */

  19. public static void setRead() {

  20. local.set(DataSourceType.read.getType());

  21. //log.info("数据库切换到READ库...");

  22. }

  23. /**

  24. * 写库

  25. */

  26. public static void setWrite() {

  27. local.set(DataSourceType.write.getType());

  28. // log.info("数据库切换到WRITE库...");

  29. }

  30. public static String getReadOrWrite() {

  31. return local.get();

  32. }

  33. public static void clear() {

  34. local.remove();

  35. }

  36. }

5.数据源的代理路由配置DatasourceAgentConfig---请读者特别注意这个类,网上很多说的都是mybatis框架的,这里是SpringDataJpa框架对应的关联代理数据源路由的配置,此处配置出错就会失败!

 
  1. package com.ddbin.frms.config.datasource;

  2. import com.ddbin.frms.FrmsApplication;

  3. import com.ddbin.frms.util.SpringContextsUtil;

  4. import lombok.extern.slf4j.Slf4j;

  5. import org.springframework.beans.factory.annotation.Autowired;

  6. import org.springframework.beans.factory.annotation.Qualifier;

  7. import org.springframework.beans.factory.annotation.Value;

  8. import org.springframework.boot.autoconfigure.AutoConfigureAfter;

  9. import org.springframework.context.annotation.Bean;

  10. import org.springframework.context.annotation.Configuration;

  11. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

  12. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;

  13. import org.springframework.orm.jpa.vendor.Database;

  14. import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

  15. import org.springframework.transaction.annotation.EnableTransactionManagement;

  16. import javax.persistence.EntityManagerFactory;

  17. import javax.sql.DataSource;

  18. import java.util.HashMap;

  19. import java.util.Map;

  20. @Configuration

  21. @AutoConfigureAfter(DataSourceConfiguration.class)

  22. @EnableTransactionManagement(order = 10)

  23. @Slf4j

  24. public class DatasourceAgentConfig {

  25. @Value("${mysql.datasource.readSize}")

  26. private String readDataSourceSize;

  27. private AbstractRoutingDataSource proxy;

  28. @Autowired

  29. @Qualifier("writeDataSource")

  30. private DataSource writeDataSource;

  31. @Autowired

  32. @Qualifier("readDataSource01")

  33. private DataSource readDataSource01;

  34. // @Autowired

  35. // @Qualifier("readDataSource02")

  36. // private DataSource readDataSource02;

  37. /**

  38. * 把所有数据库都放在路由中

  39. * 重点是roundRobinDataSouceProxy()方法,它把所有的数据库源交给AbstractRoutingDataSource类,

  40. * 并由它的determineCurrentLookupKey()进行决定数据源的选择,其中读库进行了简单的负载均衡(轮询)。

  41. *

  42. * @return

  43. */

  44. @Bean(name = "roundRobinDataSouceProxy")

  45. public AbstractRoutingDataSource roundRobinDataSouceProxy() {

  46. /**

  47. * Description:把所有数据库都放在targetDataSources中,注意key值要和determineCurrentLookupKey()中代码写的一至,

  48. * 否则切换数据源时找不到正确的数据源

  49. */

  50. Map<Object, Object> targetDataSources = new HashMap<Object, Object>();

  51. targetDataSources.put(DataSourceType.write.getType(), writeDataSource);

  52. targetDataSources.put(DataSourceType.read.getType() + "1", readDataSource01);

  53. //targetDataSources.put(DataSourceType.read.getType() + "2", readDataSource02);

  54. //路由类,寻找对应的数据源

  55. final int readSize = Integer.parseInt(readDataSourceSize);

  56. MyAbstractRoutingDataSource proxy = new MyAbstractRoutingDataSource(readSize);

  57. proxy.setTargetDataSources(targetDataSources);

  58. //默认库

  59. proxy.setDefaultTargetDataSource(writeDataSource);

  60. this.proxy = proxy;

  61. return proxy;

  62. }

  63. /**

  64. * Description:要特别注意,这个Bean是配置读写分离成败的关键,

  65. *

  66. * @param []

  67. * @return org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean

  68. * @author dbdu

  69. * @date 18-7-15 下午5:08

  70. */

  71. @Bean

  72. public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

  73. HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();

  74. vendorAdapter.setDatabase(Database.MYSQL);

  75. //是否生成表

  76.      vendorAdapter.setGenerateDdl(true);

  77. //是否显示sql语句

  78.     vendorAdapter.setShowSql(true);

  79. LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

  80. factory.setJpaVendorAdapter(vendorAdapter);

  81. //配置扫描的位置

  82. factory.setPackagesToScan(FrmsApplication.class.getPackage().getName());

  83. // 这个数据源设置为代理的数据源,----这是关键性配置!!!

  84. factory.setDataSource(proxy);

  85. return factory;

  86. }

  87. @Bean(name = "transactionManager")

  88. public MyJpaTransactionManager transactionManager() {

  89. MyJpaTransactionManager transactionManager = new MyJpaTransactionManager();

  90. transactionManager.setDataSource(proxy);

  91. transactionManager.setEntityManagerFactory((EntityManagerFactory) SpringContextsUtil.getBean("entityManagerFactory"));

  92. return transactionManager;

  93. }

  94. }

说明:entityManagerFactory是关键配置,网上很多说的都是mybatis的方式sqlSessionFactory的Bean会关联代理数据源,

SpringDataJpa的方式使用entityManagerFactory来关联代理数据源,否则读写分离是假的,这个可以通过主从库数据不同查询可以知道!

/**

* Description:要特别注意,这个Bean是配置读写分离成败的关键,

*

@param []

@return org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean

@author dbdu

@date 18-7-15 下午5:08

*/

@Bean

public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();

vendorAdapter.setDatabase(Database.MYSQL);

//是否生成表

vendorAdapter.setGenerateDdl(true);

//是否显示sql语句

vendorAdapter.setShowSql(true);

LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();

factory.setJpaVendorAdapter(vendorAdapter);

//配置扫描的位置

factory.setPackagesToScan(FrmsApplication.class.getPackage().getName());

// 这个数据源设置为代理的数据源,----这是关键性配置!!!

factory.setDataSource(proxy);

return factory;

}

6.自定义的路由数据源及事务管理器的子类:

 
  1. package com.ddbin.frms.config.datasource;

  2. import lombok.AllArgsConstructor;

  3. import lombok.Getter;

  4. import lombok.Setter;

  5. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

  6. /**

  7. * Description: 抽象数据源的路由的子类

  8. * Created at:2018-07-15 13:37,

  9. * by dbdu

  10. */

  11. @Getter

  12. @Setter

  13. @AllArgsConstructor

  14. public class MyAbstractRoutingDataSource extends AbstractRoutingDataSource {

  15. /**

  16. * Description:读库的数量,可以用来实现负载均衡

  17. */

  18. private int readSize;

  19. //private AtomicLong count = new AtomicLong(0);

  20. /**

  21. * 这是AbstractRoutingDataSource类中的一个抽象方法,

  22. * 而它的返回值是你所要用的数据源dataSource的key值,有了这个key值,

  23. * targetDataSources就从中取出对应的DataSource,如果找不到,就用配置默认的数据源。

  24. */

  25. @Override

  26. protected Object determineCurrentLookupKey() {

  27. String typeKey = DataSourceContextHolder.getReadOrWrite();

  28. if (typeKey == null || typeKey.equals(DataSourceType.write.getType())) {

  29. System.err.println("使用数据库write.............");

  30. return DataSourceType.write.getType();

  31. } else {

  32. //读库, 简单负载均衡

  33. // int number = count.getAndAdd(1);

  34. // int lookupKey = number % readSize;

  35. // System.err.println("使用数据库read-" + (lookupKey + 1));

  36. // return DataSourceType.read.getType() + (lookupKey + 1);

  37. return DataSourceType.read.getType() + "1";

  38. }

  39. }

  40. }

 
  1. package com.ddbin.frms.config.datasource;

  2. import lombok.extern.slf4j.Slf4j;

  3. import org.springframework.orm.jpa.JpaTransactionManager;

  4. import org.springframework.transaction.TransactionDefinition;

  5. import org.springframework.transaction.support.DefaultTransactionStatus;

  6. @SuppressWarnings("serial")

  7. @Slf4j

  8. public class MyJpaTransactionManager extends JpaTransactionManager {

  9. @Override

  10. protected void doBegin(Object transaction, TransactionDefinition definition) {

  11. if (definition.isReadOnly()) {

  12. DataSourceContextHolder.setRead();

  13. } else {

  14. DataSourceContextHolder.setWrite();

  15. }

  16. log.info("jpa-transaction:begin-----now dataSource is [" + DataSourceContextHolder.getReadOrWrite() + "]");

  17. super.doBegin(transaction, definition);

  18. }

  19. @Override

  20. protected void doCommit(DefaultTransactionStatus status) {

  21. log.info("jpa-transaction:commit-----now dataSource is [" + DataSourceContextHolder.getReadOrWrite() + "]");

  22. super.doCommit(status);

  23. }

  24. }

说明:如果方法命名不符合规则,也没有加注解,则typeKey会有可能为null,下面的逻辑是

typeKey为空使用写库!---也就是主库。

/**

* 这是AbstractRoutingDataSource类中的一个抽象方法,

* 而它的返回值是你所要用的数据源dataSource的key值,有了这个key值,

* targetDataSources就从中取出对应的DataSource,如果找不到,就用配置默认的数据源。

*/

@Override

protected Object determineCurrentLookupKey() {

String typeKey = DataSourceContextHolder.getReadOrWrite();

if (typeKey == null || typeKey.equals(DataSourceType.write.getType())) {

System.err.println("使用数据库write.............");

return DataSourceType.write.getType();

} else {

//读库, 简单负载均衡

// int number = count.getAndAdd(1);

// int lookupKey = number % readSize;

// System.err.println("使用数据库read-" + (lookupKey + 1));

// return DataSourceType.read.getType() + (lookupKey + 1);

return DataSourceType.read.getType() + "1";

}

}

7.读写数据源的注解,非必需,有则可以更加灵活:

 
  1. package com.ddbin.frms.config.datasource;

  2. import java.lang.annotation.*;

  3. /**

  4. * Description:读数据源的注解

  5. *

  6. * @author dbdu

  7. * @date 18-7-14 上午8:21

  8. */

  9. @Target({ElementType.METHOD, ElementType.TYPE})

  10. @Retention(RetentionPolicy.RUNTIME)

  11. @Inherited

  12. @Documented

  13. public @interface ReadDataSource {

  14. }

 
  1. package com.ddbin.frms.config.datasource;

  2. import java.lang.annotation.*;

  3. /**

  4. * Description:写数据源的注解

  5. *

  6. * @author dbdu

  7. * @date 18-7-14 上午8:21

  8. */

  9. @Target({ElementType.METHOD, ElementType.TYPE})

  10. @Retention(RetentionPolicy.RUNTIME)

  11. @Inherited

  12. @Documented

  13. public @interface WriteDataSource {

  14. }

8.配置service切面,来切换不同的数据源:

 
  1. package com.ddbin.frms.config.datasource;

  2. import org.aspectj.lang.annotation.Aspect;

  3. import org.aspectj.lang.annotation.Before;

  4. import org.springframework.context.annotation.EnableAspectJAutoProxy;

  5. import org.springframework.core.PriorityOrdered;

  6. import org.springframework.stereotype.Component;

  7. /**

  8. * Description:在service层决定数据源

  9. * 必须在事务AOP之前执行,所以实现Ordered,order的值越小,越先执行

  10. * 如果一旦开始切换到写库,则之后的读都会走写库;

  11. * 方法名符合切入点规则或加上读写注解都可以使用对应的数据库!!

  12. *

  13. * @author dbdu

  14. * @date 18-7-14 上午8:32

  15. */

  16. @Aspect

  17. @EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)

  18. @Component

  19. public class DataSourceAopInService implements PriorityOrdered {

  20. @Before("execution(* com.ddbin.frms.service..*.find*(..)) "

  21. + " or execution(* com.ddbin.frms.service..*.get*(..)) "

  22. + " or execution(* com.ddbin.frms.service..*.query*(..))"

  23. + " or execution(* com.ddbin.frms.service..*.list*(..))"

  24. + " or @annotation(com.ddbin.frms.config.datasource.ReadDataSource) "

  25. )

  26. public void setReadDataSourceType() {

  27. //如果已经开启写事务了,那之后的所有读都从写库读

  28. if (!DataSourceType.write.getType().equals(DataSourceContextHolder.getReadOrWrite())) {

  29. DataSourceContextHolder.setRead();

  30. }

  31. }

  32. @Before("execution(* com.ddbin.frms.service..*.insert*(..)) "

  33. + " or execution(* com.ddbin.frms.service..*.add*(..))"

  34. + " or execution(* com.ddbin.frms.service..*.save*(..))"

  35. + " or execution(* com.ddbin.frms.service..*.create*(..))"

  36. + " or execution(* com.ddbin.frms.service..*.update*(..))"

  37. + " or execution(* com.ddbin.frms.service..*.mod*(..))"

  38. + " or execution(* com.ddbin.frms.service..*.delete*(..))"

  39. + " or execution(* com.ddbin.frms.service..*.del*(..))"

  40. + " or execution(* com.ddbin.frms.service..*.truncate*(..))"

  41. + " or @annotation(com.ddbin.frms.config.datasource.WriteDataSource) "

  42. )

  43. public void setWriteDataSourceType() {

  44. DataSourceContextHolder.setWrite();

  45. }

  46. @Override

  47. public int getOrder() {

  48. /**

  49. * 值越小,越优先执行

  50. * 要优于事务的执行

  51. * 在启动类中加上了@EnableTransactionManagement(order = 10)

  52. */

  53. return 1;

  54. }

  55. }

说明:

A.如果方法的命名符合切入点的规则,则自动设定使用需要的数据源;

B.如果不符合A 的方法命名规则,使用注解也一样。

C.如果方法命名不符合A 的规则也没有对应的注解 ,则默认使用主库!

特别注意:

一定不要对从库或说read库进行写操作,这样做的后果是,轻者导致数据不一致(主库到从库的单向同步),重者导致从库同步失败,主库的更改不会同步到从库!

因此,写库注解可以加到service的任意方法上,因为是操作主库,但是读库注解不能加到写的方法上!

9.测试用类:读者自己去写就好了。

 
  1. /**

  2. * Description:这个方法用来测试 方法名不符合规范及注解不同是什么效果!!

  3. * 方法名不符合规则也没有注解,默认走主库!

  4. *

  5. * @author dbdu

  6. * @date 18-7-15 下午5:45

  7. */

  8. @ReadDataSource

  9. @Override

  10. public Page<Employee> pageByName(String userName, Pageable page) {

  11. Page<Employee> page1 = employeeRepository.findByName(userName, page);

  12. return page1;

  13. }

参考地址:

A.https://blog.csdn.net/dream_broken/article/details/72851329 https://github.com/269941633/spring-boot-mybatis-mysql-write-read        ----主要参考这篇文章!!

B.https://blog.csdn.net/u011493599/article/details/53930394

C.https://www.cnblogs.com/pier2/p/spring-boot-read-write-split.html

D.https://www.jianshu.com/p/8813ec02926a

E.https://my.oschina.net/wxdl/blog/1628007

F.http://blog.51cto.com/13645072/2090313

datajpa:

https://blog.csdn.net/hangge111/article/details/51605558

https://blog.csdn.net/ba5189tsl/article/details/47341425

LocalContainerEntityManagerFactoryBean创建的方法:

http://www.javased.com/index.php?api=org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean

  • 点赞
  • 评论7
  • 分享
  • 收藏3
  • 打赏
  • 关注
  • 一键三连

SpringBoot+ProxySql 配置读写分离代理 解决 java.sql.SQLException: Unknown system variable query_cache

weixin_43193729的博客

 369

ProxySql 简介 ProxySQL 是基于 MySQL 一款开源中间件产品,是一个灵活 MySQL 代理层,可以实现读写分离,支持 Query 路由功能,支持动态指定某个 SQL 进行缓存,支持动态加载(无需重启 ProxySQL 服务),故障切换和一些 SQL 过滤功能。 具体介绍请参考:ProxySQL 基础篇 文章中指出 主从库配置文件中 要有 read_only节点 这个在我上一篇配置主从数据库中有配置 但是在MySQL配置文件中写话 必须要写成 read-on...

SpringBoot+MySQLRouter 8 (mysql读写分离代理)ubuntu20.04 配置mysqlrouter8

weixin_43193729的博客

 397

mysql router 特性 (1)Router实现读写分离,程序不是直接连接数据库IP,而是固定连接到mysql router。MySQL Router对前端应用是透明。 应用程序把MySQL Router当作是普通mysql实例,把查询发给MySQL Router,而MySQL Router会把查询结果返回给前端应用程序。 (2)从数据库服务器故障,业务可以正常运行。由MySQL Router来进行自动线不可用服务器。程序配置不需要任何修改。 (3)主数据库故障,由MySQL R..

  • 「已注销」:import com.ddbin.frms.util.SpringContextsUtil;这个类没有啊2 年前回复

    • dusuanyun回复:

       
      1. @Component

      2. public class SpringContextUtils implements ApplicationContextAware {

      3. public static ApplicationContext applicationContext;

      4. @Override

      5. public void setApplicationContext(ApplicationContext applicationContext)

      6. throws BeansException {

      7. SpringContextUtils.applicationContext = applicationContext;

      8. }

      9. public static Object getBean(String name) {

      10. return applicationContext.getBean(name);

      11. }

      12. public static <T> T getBean(String name, Class<T> requiredType) {

      13. return applicationContext.getBean(name, requiredType);

      14. }

      15. public static boolean containsBean(String name) {

      16. return applicationContext.containsBean(name);

      17. }

      18. public static boolean isSingleton(String name) {

      19. return applicationContext.isSingleton(name);

      20. }

      21. public static Class&lt;? extends Object> getType(String name) {

      22. return applicationContext.getType(name);

      23. }

      24. }

      2 年前回复

    • 「已注销」回复:applicationContext.getBean("entityManagerFactory"));
       
      1. 我改成这样不知道对不对

      2 年前回复

  • BnuzLeon:兄弟,可以。 网上的确有很多假主从,都是拿主表来读写的。2 年前回复

    • dusuanyun回复: 是的,谢谢认可.我个人也非常在意是否是真的读写,这个研究很久整理出来的文章,还是有一定的参考价值的.2 年前回复

  • qingqianxiaoyao:博主啊 能不能把那个yml配置文件修改成yml格式的文件,不然有点不清楚到底是怎么配置的2 年前回复

    • dusuanyun回复:已经调整,谢谢提醒2 年前回复

相关推荐

基于SpringBootMYSQL数据库读写分离(二)——项目搭建...

5-7

在前一章中,我们介绍完了数据库读写分离所需要基础环境搭建。详见:【基于SpringBootMYSQL数据库读写分离(一)——基础环境搭建】在本章中,将介绍如何使用Springboot去实现动态切换数据源。

崛起于Springboot2.X之Mysql读写分离(6)_weixin_342040...

5-4

序言:这个读写分离摘自于Springboot多数据源快速启动器,读写分离话并不是按照传统方式springmvc看方法命名那样,而是在每个方法上加注解或者类上添加注解表明选用数据源。支持事物! 1、创建Springboot项目 ...

MySQLSpringBoot实现MySQL读写分离

头号码农的博客

 452

SpringBoot MySQL读写分离读写分离实现编码思想实现步骤添加pom依赖application.properties配置配置数据源配置切面类用到其他类动态数据源读写类型记录操作类型业务方法标记注解 MySQL数据库安装请参考:CentOS7安装MySQL数据库及MariaDB MySQL数据库主从复制环境搭建请参考:CentOS7实现MySQL读写分离环境搭建 读写分离实现 读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做

MySQL Proxy笔记

星猿

 37

版本 mysql-proxy 0.8.5 命令行方式启动,监听4040端口 mysql-proxy --proxy-read-only-backend-addresses=10.1.1.1 --log-level=debug --daemon 2021-01-06 15:15:31: (message) proxy listening on port :4040 2021-01-06 15:15:31: (message) added read/write backend: 127.0.0.1:330

springboot mysql实现读写分离_ccr1001ccr1001博客

4-14

springboot mysql实现读写分离 mysql主从设置参考:mysql主从设置 1. pom设置 springdata: master: driver-class-name: com.mysql.jdbc.Driver jdbc-url:jdbc:mysql://192.168.1.47:3306/im-block?autoReconnect=true&useUnicode=...

基于SpringBoot,来实现MySQL读写分离技术_里奥ii博客

4-29

基于SpringBoot,来实现MySQL读写分离技术 前言 首先思考一个问题:在高并发场景中,关于数据库都有哪些优化手段?常用有以实现方法:读写分离、加缓存、主从架构集群、分库分表等,在互联网应用中,大部分都是读多写少场景,...

SpringBoot进行MySql动态数据源配置实现读写分离(连接池Druid)

Autumn、的博客

 4077

1.简介 前面使用C3P0连接池进行过数据库读写分离实验,今天换一数据库连接池改造一,原理还是和原来一样。 Druid是阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置JDBC组件库,一个 SQL Parser。支持所有JDBC兼容数据库,包括Oracle、MySql、Derby、Postgresql、SQL S...

SpringBoot MySql读写分离-多数据源集成

zhuyu19911016520

 1327

1.业务场景 客户给了3台MySQL数据库服务器,一主二从,程序需要集成读写分离,充分提升数据处理能力 数据层使用了MyBatis-Plus,它有一个多数据源中间件 dynamic-datasource-spring-boot-starter 参考:MyBatis-Plus 2.MySql主从 一主二从,搭建方式参考:docker搭建mysql读写分离 3.SpringBoot快速集成 1.新建SpringBoot项目,核心依赖 <dependency> <groupId&g

基于SpringBootMYSQL数据库读写分离(一)——基础环境...

5-10

首先需要明确是使用数据库读写分离,它主要应用场景是为了解决数据库“读”瓶颈问题,在对数据库进行一定程度优化后,任然不能满足“读”数据业务需求,这样我们就需要引入数据库读写分离了。

SpringBoot+MyBatis+MySQL读写分离(实例)_javafirst

5-8

SpringBoot+MyBatis+MySQL读写分离(实例) 1. 引言 读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做。因此,一般来讲,读写分离有两种实现方式...

mysql读写分离springboot集成

lipeng的博客

 2823

springbootmysql实现读写分离 1、首先在springcloud config中配置读写数据库 mysqldatasource: readSize: 1 #读库个数 type: com.alibaba.druid.pool.DruidDataSource write: url: jdbc:mysql://200...

SpringBoot+MyBatis+MySQL读写分离(实例)

java面试笔试

 701

1. 引言读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做。因此,一般来讲,读写分离...

SpringBoot+MyBatis+MySQL读写分离_lisheng19870305专栏

5-6

SpringBoot+MyBatis+MySQL读写分离 原文地址:https://www.cnblogs.com/cjsblog/p/9712457.html 1. 引言 读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,...

Spring/SpringBoot系列之springboot+mysql+mybatis实现...

5-4

--lookup parent from repository--></parent><groupId>com.linyf</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>springboot+mysql+mybatis实现读写分离实战</...

SpringBoot + MyBatis + MySQL 读写分离实战

勇往直前的专栏

 688

1. 引言 读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做。因此,一般来讲,读写分离有两种实现方式。第一种是依靠中间件(比如:MyCat),也就是说应用程序连接到中间件,中间件帮我们做SQL分离;第二种是应用程序自己去做分离。这里我们选择程序自己来做,主要是利用Spring提供路由数据源,以及AOP。 然...

SpringBoot + MyBatis + MySQL 读写分离实战

HollisChuang's Blog

 1302

作者:废物大师兄来源:http://t.cn/AiKuJEB91. 引言读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个...

springboot实现mysql读写分离_SunQIXin博客-CSDN博...

4-14

springboot实现mysql读写分离 描述 读写分离就是对于一条SQL该选择哪一个数据库去执行,至于谁来做选择数据库这件事,有两个,要么使用中间件帮我们做,要么程序自己做。一般来说,读写分离有两种实现方式。第一种是依靠中间件MyCat,...

SpringBoot+MyBatis+MySQL读写分离

weixin_30848775的博客

 124

1. 引言 读写分离要做事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做。因此,一般来讲,读写分离有两种实现方式。第一种是依靠中间件(比如:MyCat),也就是说应用程序连接到中间件,中间件帮我们做SQL分离;第二种是应用程序自己去做分离。这里我们选择程序自己来做,主要是利用Spring提供路由数据源,以及AOP ...

springboot+springAOP实现数据库读写分离及数据库同步(MySQL)

wsbgmofo的博客

 5788

网上找了很多资料,发现根据获取bean时候报空指针,不知道是哪里有问题,后来稍作修改就可以了 1,数据源配置文件,如 datasource.readSize=1 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource # 主数据源,默认 spring.master.driver-class-name=com.my

Springboot Mybatis MySQL读写分离及事物配置

wantnrun的专栏

 5936

为什么需要读写分离 当项目越来越大和并发越来大情况,单个数据库服务器压力肯定也是越来越大,最终演变成数据库成为性能瓶颈,而且当数据越来越多时,查询也更加耗费时间,当然数据库数据过大时,可以采用数据库分库分表,同时数据库压力过大时,也可以采用Redis等缓存技术来降低压力,但是任何一种技术都不是万金油,很多时候都是通过多种技术搭配使用,而本文主要就是介绍通过读写分离来加快数据库读取速度

mysql使用mysql-proxy实现读写分离

橙汁Iter的博客

 1349

一、主从分离原理 1.简介 对于很多大型网站(pv值百万、千万)来说,在所处理业务中,其中有70%业务是查询(select)相关业务操作(新闻网站,插入一条新闻。查询操作),剩则是写(insert、update、delete,只要能对MySQL数据造成更改操作都叫写操作)操作。在使用负载均衡集群之后,可以很大程度提升网站整体性能,但是最终数据处理压力还是会落到MySQ...

手把手搭建Java学生信息管理系统【附源码】(毕设)

02-24

<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业正在做毕设学生与需要项目实战练习Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含:<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑和远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图:</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>

Windows版YOLOv4-tiny目标检测实战:训练自己数据集

07-06

<p> 课程演示环境:Windows10  </p> <p> 需要学习<span>Ubuntus</span>系统<span>YOLOv4-tiny</span>同学请前往《<span>YOLOv4-tiny</span>目标检测实战:训练自己数据集》 <span></span> </p> <p> <span> </span> </p> <p> <span style="color:#E53333;">YOLOv4-tiny</span><span style="color:#E53333;">来了!速度大幅提升!</span><span></span> </p> <p> <span> </span> </p> <p> <span>YOLOv4-tiny</span>在<span>COCO</span>上性能可达到:<span>40.2% AP50, 371 FPS (GTX 1080 Ti)</span>。相较于<span>YOLOv3-tiny</span>,<span>AP</span>和<span>FPS</span>性能有巨大提升。并且,<span>YOLOv4-tiny</span>权重文件只有<span>23MB</span>,适合在移动端、嵌入式设备、边缘计算设备上部署。<span></span> </p> <p> <span> </span> </p> <p> 本课程将手把手地教大家使用<span>labelImg</span>标注和使用<span>YOLOv4-tiny</span>训练自己数据集。课程实战分为两个项目:单目标检测(足球目标检测)和多目标检测(足球和梅西同时检测)。<span></span> </p> <p> <span> </span> </p> <p> 本课程<span>YOLOv4-tiny</span>使用<span>AlexAB/darknet</span>,在<span>Windows10</span>系统上做项目演示。包括:<span>YOLOv4-tiny</span>网络结构、安装<span>YOLOv4-tiny</span>、标注自己数据集、整理自己数据集、修改配置文件、训练自己数据集、测试训练出网络模型、性能统计<span>(mAP</span>计算<span>)</span>和先验框聚类分析。 <span> </span> </p> <p> <span> </span> </p> <p> 除本课程《<span>Windows</span>版<span>YOLOv4-tiny</span>目标检测实战:训练自己数据集》外,本人推出了有关<span>YOLOv4</span>目标检测系列课程。请持续关注该系列其它视频课程,包括:<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:训练自己数据集》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:人脸口罩佩戴识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:中国交通标志识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测:原理与源码解析》<span></span> </p> <p> <span> <img alt="" src="https://img-bss.csdnimg.cn/202007061503586145.jpg" /></span> </p> <p> <span><img alt="" src="https://img-bss.csdnimg.cn/202007061504169339.jpg" /><br /> </span> </p>

C语言入门--必须基础17讲

07-28

适合没有基础人群学习C语言,简单入门教程。帮助小白理解什么是开发,什么是编程。做很简单,很多细节没有详细讲解,不适合用来深入研究。学了这个,你能理解什么是编程,什么是C语言。

python入门

12-18

<p> <br /> </p> <p style="font-family:"color:#3D3D3D;font-size:16px;background-color:#FFFFFF;"> 您观看课程学习后<br /> 免费入群领取【超全Python资料包+17本学习电子书】 </p> <p style="font-family:"color:#3D3D3D;font-size:16px;background-color:#FFFFFF;"> <img src="https://img-bss.csdn.net/201909261025418774.jpg" alt="" /> </p> <p> <br /> </p> <p> 帮助与数百万年轻人打开人工智能学习大门! </p>

JAVA入门精品课程

12-20

课程目标: 1、让初学者从小白开始,善于运用知识点,解脱学习苦恼 2、能够学习更多工作中使用技巧,成为编程高手

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页

  • 关于我们
  • 招贤纳士
  • 广告服务
  • 开发助手
  • 400-660-0108
  • kefu@csdn.net
  • 在线客服
  • 工作时间 8:30-22:00
  • 公安备案号11010502030143
  • 京ICP备19004658号
  • 京网文〔2020〕1039-165号
  • 经营性网站备案信息
  • 北京互联网违法和不良信息举报中心
  • 网络110报警服务
  • 中国互联网举报中心
  • 家长监护
  • Chrome商店下载
  • ©1999-2021北京创新乐知网络技术有限公司
  • 版权与免责声明
  • 版权申诉
  • 出版物许可证
  • 营业执照

dusuanyun

码龄9年 暂无认证

23

原创

10万+

周排名

18万+

总排名

3万+

访问

等级

582

积分

8

粉丝

3

获赞

16

评论

21

收藏

私信

关注

热门文章

  • 在SpringBoot项目中使用SpringSecurity权限认证框架  8677
  • Thymeleaf页面通过获取Spring容器中配置的Bean来取得配置文件中的参数值  4912
  • 02-下篇-SpringBoot下MySQL的读写分离  3095
  • Deepin15.11稳定源可以支持小米笔记本Pro-GTX版的指纹设备  2953
  • 使用Eclipse创建并运行scala项目--Spark实战的方式  2560

最新评论

  • 关于Feign在微服务间调用引用参数传递的问题

    dusuanyun: 后面的有道云笔记链接里有附件,附件里有这个方法

  • 关于Feign在微服务间调用引用参数传递的问题

    恛忆: 请问buildQuery是怎么写的呢?

  • 使用Eclipse创建并运行scala项目--Spark实战的方式

    jacsoney: 感觉有点文不对题

  • Thymeleaf页面通过获取Spring容器中配置的Bean来取得配置文件中的参数值

    dusuanyun 回复 杭电鬼先生: 建议你看看thymeleaf的官方文档,可能会有帮助

  • Thymeleaf页面通过获取Spring容器中配置的Bean来取得配置文件中的参数值

    杭电鬼先生 回复 dusuanyun: 我当时遇到的问题是我使用了它的母版页,然后我同时从yml文件中获取了我配置的一个ip地址,然后模板引擎直接把这个ip地址作为html内容加载进去了,但是html中直接写入这些内容是非法的,html就有错误了

最新文章

  • Deepin20配置CLion作为Qt5开发环境
  • 关于SpringDataJpa框架的多数据源支持功能实现
  • 解决ip2region.db在执行反射查询的时候报错的问题

2020年7篇

2019年5篇

2018年7篇

2017年1篇

2016年3篇

分类专栏

  • 环境配置3篇
  • 编程实现5篇
  • SpringDataJpa2篇
  • 多租户1篇
  • 隔离的redis1篇
  • 设备驱动1篇
  • 读书笔记3篇
  • 应用配置9篇
  • 小技巧3篇
  • 开发坑解决6篇

举报

SpringBoot下MySQL的读写分离相关推荐

  1. Springboot实现Mysql的读写分离

    一.描述 读写分离就是对于一条SQL该选择哪一个数据库去执行,至于谁来做选择数据库这件事,有两个,要么使用中间件帮我们做,要么程序自己做.一般来说,读写分离有两种实现方式.第一种是依靠中间件MyCat ...

  2. linux mysql安装 读写分离_linux下安装mysql-proxy 配置读写分离

    一.软件列表 ncurses-5.7.tar.gz wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-5.7.tar.gz mysql-proxy-0.8 ...

  3. Sharding-jdbc教程:Springboot整合sharding-jdbc实现读写分离

    点击上方"方志朋",选择"置顶公众号" 技术文章第一时间送达! Sharding-JDBC简介 Sharding-JDBC是的分布式数据库中间件解决方案.Sha ...

  4. Amoeba实现mysql主从读写分离

    Amoeba实现mysql主从读写分离 这段在网上看了下关于amoeba的文章,总体感觉好像要比mysql-proxy好的多,也参考了不少的资料,此文章可能与其他文章作者会有雷同的地方,请谅解,但是此 ...

  5. Centos7源码安装mysql及读写分离,互为主从

       Linux服务器 -源码安装mysql 及读写分离,互为主从   一.环境介绍: Linux版本: CentOS 7 64位 mysq版本: mysql-5.6.26 这是我安装时所使用的版本, ...

  6. MySQL Router实现MySQL的读写分离

    1.简介 MySQL Router是MySQL官方提供的一个轻量级MySQL中间件,用于取代以前老版本的SQL proxy. 既然MySQL Router是一个数据库的中间件,那么MySQL Rout ...

  7. MySQL面试 - 读写分离

    MySQL面试 - 读写分离 面试题 你们有没有做 MySQL 读写分离?如何实现 MySQL 的读写分离?MySQL 主从复制原理的是啥?如何解决 MySQL 主从同步的延时问题? 面试官心理分析 ...

  8. SpringBoot 整合 MyCat 实现读写分离

    作者:颜不喜 cnblogs.com/muycode/p/12603037.html MyCat一个彻底开源的,面向企业应用开发的大数据库集群.基于阿里开源的Cobar产品而研发.能满足数据库数据大量 ...

  9. amoeba实现mysql主从读写分离_利用Amoeba实现MySQL主从复制和读写分离

    在实际生产环境中,如果对数据库的读和写都在同一个数据库服务器中操作,无论是在安全性.高可用性,还是高并发等各个方面都是完全不能满足实际需求的,因此,一般来说都是通过主从复制(Master-Slave) ...

最新文章

  1. SourceTree 3.0.17如何跳过注册进行安装? — git图形化工具(一)
  2. 公司CRM的三个阶段
  3. 英伟达jetson tx1开发套件配置tensorflow
  4. php文件名函数,php 获取文件名basename()函数的用法总结
  5. Python网络编程中的select 和 poll I/O复用的简单使用
  6. CentOS 6.8 虚拟机安装详解
  7. Telnet发邮件过程
  8. React.js组件化开发第一步(框架搭建)
  9. php 识别图片指定区域,简单实现图片局部识别的方法
  10. 读书笔记3——《用户故事与敏捷方法》
  11. 软件开发成本度量之类比法估算软件工作量
  12. 中学-综合素质【2】
  13. GTK使用cairo绘图教程
  14. 学习JAVABEANS
  15. Android 9 P静默安装/卸载App适配终极指南
  16. nodejs zip 解压zip文件
  17. 微信支付通用支付接口
  18. 大模型时代,视觉推理任务竟然只用语言数据也能学习
  19. O2OA开源免费办公平台:在PAAS平台上部署O2OA开发平台
  20. 安卓-使用腾讯TBS浏览服务(X5WebView) - 打开打开PDF,WORD,EXCLE等文件

热门文章

  1. java 文件包含_java的文件包含漏洞
  2. python统计文章中的高频词汇_使用Python 统计高频字数的方法
  3. 02 IPy模块的应用
  4. java文档注释return_Java-文档注释
  5. 文件之获取文件夹路径/data/data/
  6. 卷积神经网络中卷积和池化特征图的维度变化(不能被整除问题)
  7. Ubuntu 20.04解决idea/ jetbrain系列产品 搜狗输入法/其他输入法 一直显示在左下角,不跟随打字的问题
  8. 拼多多“因为灰黑产被薅走200亿”的谣言
  9. Android Tv连接charles
  10. 微信跳一跳外挂辅助及使用教程