当前位置: 首页 > news >正文

做网站用百度地图和天地图aso排名优化知识

做网站用百度地图和天地图,aso排名优化知识,拉萨工商做年检网站,本地营销型网站建设一、读写分离介绍 当使用Spring Boot开发数据库应用时,读写分离是一种常见的优化策略。读写分离将读操作和写操作分别分配给不同的数据库实例,以提高系统的吞吐量和性能。 读写分离实现主要是通过动态数据源功能实现的,动态数据源是一种通过…

一、读写分离介绍

当使用Spring Boot开发数据库应用时,读写分离是一种常见的优化策略。读写分离将读操作和写操作分别分配给不同的数据库实例,以提高系统的吞吐量和性能。

读写分离实现主要是通过动态数据源功能实现的,动态数据源是一种通过在运行时动态切换数据库连接的机制。它允许应用程序根据不同的条件或配置选择不同的数据源,以实现更灵活和可扩展的数据库访问。

二、实现读写分离-基础

1. 配置主数据库和从数据库的连接信息

# 主库配置
spring.datasource.master.jdbc-url=jdbc:mysql://ip:port/master?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.master.username=master
spring.datasource.master.password=123456
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver# 从库配置
spring.datasource.slave.jdbc-url=jdbc:mysql://ip:port/slave?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.slave.username=slave
spring.datasource.slave.password=123456
spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver 

2. 创建主数据库和从数据库的数据源配置类

通过不同的条件限制和配置文件前缀可以完成不同数据源的创建工作,不止是主从也可以是多个不同的数据库

主库数据源配置

@Configuration
@ConditionalOnProperty("spring.datasource.master.jdbc-url")
public class MasterDataSourceConfiguration {@Bean("masterDataSource")@ConfigurationProperties(prefix = "spring.datasource.master")public DataSource masterDataSource() {return DataSourceBuilder.create().build();}
}

从库数据源配置

@Configuration
@ConditionalOnProperty("spring.datasource.slave.jdbc-url")
public class SlaveDataSourceConfiguration {@Bean("slaveDataSource")@ConfigurationProperties(prefix = "spring.datasource.slave")public DataSource slaveDataSource() {return DataSourceBuilder.create().build();}
}

3. 创建主从数据源枚举

public enum DataSourceTypeEnum {/*** 主库*/MASTER,/*** 从库*/SLAVE,;}

4. 创建动态路由数据源

这儿做了一个开关,可以控制读写分离的开启和关闭工作,可以讲操作全部切换到主库进行。然后根据上下文中的数据源类型来返回不同的数据源类型枚举

@Slf4j
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {@Value("${DB_RW_SEPARATE_SWITCH:false}")private boolean dbRwSeparateSwitch;@Overrideprotected Object determineCurrentLookupKey() {if(dbRwSeparateSwitch && DataSourceTypeEnum.SLAVE.equals(DataSourceContextHolder.getDataSourceType())) {log.info("DynamicRoutingDataSource 切换数据源到从库");return DataSourceTypeEnum.SLAVE;}log.info("DynamicRoutingDataSource 切换数据源到主库");// 根据需要指定当前使用的数据源,这里可以使用ThreadLocal或其他方式来决定使用主库还是从库return DataSourceTypeEnum.MASTER;}
}

5. 创建动态数据源配置类

将主数据库和从数据库的数据源添加到动态数据源中,并可以通过枚举创建一个数据源 map,这样就可以通过上面的路由返回的枚举来切换数据源

@Configuration
@ConditionalOnProperty("spring.datasource.master.jdbc-url")
public class DynamicDataSourceConfiguration {@Bean("dataSource")@Primarypublic DataSource dynamicDataSource(DataSource masterDataSource, DataSource slaveDataSource) {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put(DataSourceTypeEnum.MASTER, masterDataSource);targetDataSources.put(DataSourceTypeEnum.SLAVE, slaveDataSource);DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();dynamicDataSource.setTargetDataSources(targetDataSources);dynamicDataSource.setDefaultTargetDataSource(masterDataSource);return dynamicDataSource;}
}

6. 创建DatasourceContextHolder类使用ThreadLocal存储当前线程的数据源类型

注意这儿有个潜在风险就是创建新的线程时会导致 ThreadLocal 中的数据无法正确读取,如果涉及到在开启新线程可以使用 TransmittableThreadLocal 来进行父子线程数据的同步,git 地址: https://github.com/alibaba/transmittable-thread-local

public class DataSourceContextHolder {private static final ThreadLocal<DataSourceTypeEnum> contextHolder = new ThreadLocal<>();public static void setDataSourceType(DataSourceTypeEnum dataSourceType) {contextHolder.set(dataSourceType);}public static DataSourceTypeEnum getDataSourceType() {return contextHolder.get();}public static void clearDataSourceType() {contextHolder.remove();}
}

7. 创建自定义注解,用于标记主和从数据源

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MasterDataSource {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface SlaveDataSource {
}

8. 创建切面类,拦截数据库操作,并根据注解设置切换数据源参数

@Aspect
@Component
public class DataSourceAspect {@Before("@annotation(xxx.MasterDataSource)")public void setMasterDataSource(JoinPoint joinPoint) {DataSourceContextHolder.setDataSourceType(DataSourceTypeEnum.MASTER);}@Before("@annotation(xxx.SlaveDataSource)")public void setSlaveDataSource(JoinPoint joinPoint) {DataSourceContextHolder.setDataSourceType(DataSourceTypeEnum.SLAVE);}@After("@annotation(xxx.MasterDataSource) || @annotation(xxx.SlaveDataSource)")public void clearDataSource(JoinPoint joinPoint) {DataSourceContextHolder.clearDataSourceType();}
}

9. 在Service层的方法上使用自定义注解标记查询数据源

@Service
public class TestService {@Autowiredprivate TestDao testDao;@SlaveDataSourcepublic Test test() {return testDao.queryByPrimaryKey(11L);}
}

10. 排除掉数据源自动配置类

如果不排除自动配置类会导致初始化多个 dataSource 对象导致出现问题

SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

三、实现读写分离-进阶

1. 使用链接池,以Hikari为例

修改链接配置,加入链接池相关配置即可

# 主库配置
spring.datasource.master.jdbc-url=jdbc:mysql://ip:port/master?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.master.username=master
spring.datasource.master.password=123456
spring.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.master.hikari.name=master
spring.datasource.master.hikari.minimum-idle=5
spring.datasource.master.hikari.idle-timeout=30
spring.datasource.master.hikari.maximum-pool-size=10
spring.datasource.master.hikari.auto-commit=true
spring.datasource.master.hikari.pool-name=DatebookHikariCP
spring.datasource.master.hikari.max-lifetime=1800000
spring.datasource.master.hikari.connection-timeout=30000
spring.datasource.master.hikari.connection-test-query=SELECT 1# 从库配置
spring.datasource.slave.jdbc-url=jdbc:mysql://ip:port/slave?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.slave.username=root
spring.datasource.slave.password=123456
spring.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.slave.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.slave.hikari.name=master
spring.datasource.slave.hikari.minimum-idle=5
spring.datasource.slave.hikari.idle-timeout=30
spring.datasource.slave.hikari.maximum-pool-size=10
spring.datasource.slave.hikari.auto-commit=true
spring.datasource.slave.hikari.pool-name=DatebookHikariCP
spring.datasource.slave.hikari.max-lifetime=1800000
spring.datasource.slave.hikari.connection-timeout=30000
spring.datasource.slave.hikari.connection-test-query=SELECT 1

2. 集成 mybatis 并在写入时强制切换到主库

不需要做任何配置,正常集成 mybatis 即可使用读写分离功能

可以通过 mybatis 的拦截器在写入操作时强制切换到主库

@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
@Component
public class WriteInterceptor implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 获取 SQL 类型DataSourceTypeEnum dataSourceType = DataSourceContextHolder.getDataSourceType();if(DataSourceTypeEnum.SLAVE.equals(dataSourceType)) {DataSourceContextHolder.setDataSourceType(DataSourceTypeEnum.MASTER);}try {// 执行 SQLreturn invocation.proceed();} finally {// 恢复数据源  考虑到写入后可能会反查,后续都走主库// DataSourceContextHolder.setDataSourceType(dataSourceType);}}
}

作者:京东健康 苏曼

来源:京东云开发者社区 转发请注明来源

http://www.hkea.cn/news/850912/

相关文章:

  • 新手做那些网站比较好东莞企业网站排名
  • 欧美风格网站360指数
  • 优秀网站建设公司电话下列哪些店铺适合交换友情链接
  • 58同城乌鲁木齐网站建设重庆网站到首页排名
  • wordpress知言主题山东服务好的seo公司
  • 旅游商务平台网站建设功能需求关键词排名查询官网
  • 做网站要搭建本地服务器么微商引流被加方法精准客源
  • 网站名字要备案吗友情链接怎么弄
  • 江苏网站开发外链网站大全
  • 网站代备案流程图百度关键词优化排名技巧
  • 石狮建设局网站今日头条站长平台
  • 修改公司网站网页站长素材音效
  • 网站速度测速免费访问国外网站的app
  • 常州网站搭建公司宣传推广渠道有哪些
  • 中国建设监理网站广告网络
  • 网站维护费用怎么收路由优化大师官网
  • 如何加入小说网站做打字员合肥网站优化推广方案
  • 网站建设现状关键词在线优化
  • 网站建设就业百度网址导航主页
  • 郑州公司做网站汉狮中囯联通腾迅
  • 专业网上购物平台优化网站的步骤
  • 用web开发一个网站怎么做网站推广优化平台
  • 建设企业网站进去无法显示搜索引擎seo
  • 网站 分辨率百度视频推广
  • 中国红河网seo排名工具
  • 做网站商丘3a汽车集团公司网络营销方案
  • 网络宣传推广策划范文seo如何优化排名
  • 网站 建设 原则新闻今天的最新新闻
  • 服装网站首页设计主要推广手段免费
  • 网站建设公司做销售好不好?seo搜索引擎优化实训总结