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

沾化网站建设广州天河区建设网站

沾化网站建设,广州天河区建设网站,网站建设服务费怎么入账,怎么制作网站设计前言: 首先思考一个问题:在高并发的场景中,关于数据库都有哪些优化的手段#xff1f;常用的有以下的实现方法:读写分离、加缓存、主从架构集群、分库分表等#xff0c;在互联网应用中,大部分都是读多写少的场景,设置两个库,主库和读库,主库的职能是负责写,从库主要是负责读…前言:   首先思考一个问题:在高并发的场景中,关于数据库都有哪些优化的手段常用的有以下的实现方法:读写分离、加缓存、主从架构集群、分库分表等在互联网应用中,大部分都是读多写少的场景,设置两个库,主库和读库,主库的职能是负责写,从库主要是负责读,可以建立读库集群,通过读写职能在数据源上的隔离达到减少读写冲突、释压数据库负载、保护数据库的目的。在实际的使用中,凡是涉及到写的部分直接切换到主库读的部分直接切换到读库这就是典型的读写分离技术。本篇博文将聚焦读写分离,探讨如何实现它。 主从同步的局限性这里分为主数据库和从数据库,主数据库和从数据库保持数据库结构的一致,主库负责写,当写入数据的时候,会自动同步数据到从数据库从数据库负责读,当读请求来的时候,直接从读库读取数据,主数据库会自动进行数据复制到从数据库中。不过本篇博客不介绍这部分配置的知识,因为它更偏运维工作一点。这里涉及到一个问题:主从复制的延迟问题,当写入到主数据库的过程中,突然来了一个读请求,而此时数据还没有完全同步,就会出现读请求的数据读不到或者读出的数据比原始值少的情况。具体的解决方法最简单的就是将读请求暂时指向主库,但是同时也失去了主从分离的部分意义。也就是说在严格意义上的数据一致性场景中,读写分离并非是完全适合的,注意更新的时效性是读写分离使用的缺点。 好了,这部分只是了解,接下来我们看下具体如何通过java代码来实现读写分离: 该项目需要引入如下依赖springBoot、spring-aop、spring-jdbc、aspectjweaver等 一: 主从数据源的配置 我们需要配置主从数据库,主从数据库的配置一般都是写在配置文件里面。通过ConfigurationProperties注解,可以将配置文件(一般命名为:application.Properties)里的属性映射到具体的类属性上,从而读取到写入的值注入到具体的代码配置中,按照习惯大于约定的原则,主库我们都是注为master,从库注为slave,本项目采用了阿里的druid数据库连接池,使用build建造者模式创建DataSource对象,DataSource就是代码层面抽象出来的数据源,接着需要配置sessionFactory、sqlTemplate、事务管理器等 /*** 主从配置** author wyq* date 2020年07月24日01:24:42*/ Configuration MapperScan(basePackages com.wyq.mysqlreadwriteseparate.mapper, sqlSessionTemplateRef sqlTemplate) public class DataSourceConfig {/*** 主库*/BeanConfigurationProperties(prefix spring.datasource.master)public DataSource master() {return DruidDataSourceBuilder.create().build();}/*** 从库*/BeanConfigurationProperties(prefix spring.datasource.slave)public DataSource slaver() {return DruidDataSourceBuilder.create().build();}/*** 实例化数据源路由*/Beanpublic DataSourceRouter dynamicDB(Qualifier(master) DataSource masterDataSource,Autowired(required false) Qualifier(slaver) DataSource slaveDataSource) {DataSourceRouter dynamicDataSource new DataSourceRouter();MapObject, Object targetDataSources new HashMap();targetDataSources.put(DataSourceEnum.MASTER.getDataSourceName(), masterDataSource);if (slaveDataSource ! null) {targetDataSources.put(DataSourceEnum.SLAVE.getDataSourceName(), slaveDataSource);}dynamicDataSource.setTargetDataSources(targetDataSources);dynamicDataSource.setDefaultTargetDataSource(masterDataSource);return dynamicDataSource;}/*** 配置sessionFactory* param dynamicDataSource* return* throws Exception*/Beanpublic SqlSessionFactory sessionFactory(Qualifier(dynamicDB) DataSource dynamicDataSource) throws Exception {SqlSessionFactoryBean bean new SqlSessionFactoryBean();bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath*:mapper/*Mapper.xml));bean.setDataSource(dynamicDataSource);return bean.getObject();}/*** 创建sqlTemplate* param sqlSessionFactory* return*/Beanpublic SqlSessionTemplate sqlTemplate(Qualifier(sessionFactory) SqlSessionFactory sqlSessionFactory) {return new SqlSessionTemplate(sqlSessionFactory);}/*** 事务配置** param dynamicDataSource* return*/Bean(name dataSourceTx)public DataSourceTransactionManager dataSourceTransactionManager(Qualifier(dynamicDB) DataSource dynamicDataSource) {DataSourceTransactionManager dataSourceTransactionManager new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dynamicDataSource);return dataSourceTransactionManager;} } 二: 数据源路由的配置 路由在主从分离是非常重要的,基本是读写切换的核心。Spring提供了AbstractRoutingDataSource 根据用户定义的规则选择当前的数据源作用就是在执行查询之前设置使用的数据源,实现动态路由的数据源在每次数据库查询操作前执行它的抽象方法 determineCurrentLookupKey() 决定使用哪个数据源,为了能有一个全局的数据源管理器,此时我们需要引入DataSourceContextHolder这个数据库上下文管理器,可以理解为全局的变量,随时可取(见下面详细介绍),它的主要作用就是保存当前的数据源; public class DataSourceRouter extends AbstractRoutingDataSource {/*** 最终的determineCurrentLookupKey返回的是从DataSourceContextHolder中拿到的,因此在动态切换数据源的时候注解* 应该给DataSourceContextHolder设值** return*/Overrideprotected 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 ThreadLocalString 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 {Resourceprivate OrderMapper orderMapper;/*** 读操作** param orderId* return*/DataSourceSwitcher(DataSourceEnum.SLAVE)public ListOrder getOrder(String orderId) {return orderMapper.listOrders(orderId);}/*** 写操作** param orderId* return*/DataSourceSwitcher(DataSourceEnum.MASTER)public ListOrder insertOrder(Long orderId) {Order order new Order();order.setOrderId(orderId);return orderMapper.saveOrder(order);} }
http://www.pierceye.com/news/379534/

相关文章:

  • 辽宁建设工程信息网网站python 网站开发
  • 企业网站.net免费做ppt的网站
  • 浦城 做网站wordpress下载页面
  • 广西住房城乡建设部网站网站优化怎么看
  • 网站建设负责人证明网络营销的10个特点
  • 泉州市服务好的网站设计塘沽网吧开门了吗
  • 商城网站建设哪家公司好wordpress输出到模板
  • 建站报价网站建设培训学校
  • 杭州高端网站定制手机网站开发应注意
  • 深圳网站建设选云聚达做二手元器件那个网站查价格
  • 网站建设公司企业模板微网站开发制作
  • 北京网站制作计划合理的网站结构
  • 网站建设如何搭建框架兰州seo排名
  • 网站作为医院形象建设cms搭建网站
  • 如何做个购物网站网站开发好不好
  • wordpress国内打开速度慢东莞搜索seo关键词
  • 鹿泉建设网站广安市建设局官方网站
  • 用花生棒自己做网站如何看网站的浏览量
  • 大连网站排名电商线上培训
  • 做金融网站做简历的网站
  • 求网站建设合伙人wordpress子页面怎么修改密码
  • 怎样登录建设互联网站厦门海绵城市建设官方网站
  • 网站怎么做权重互联网平台推广怎么做
  • 网站建设如果登录失败男生和男生做污的视频网站
  • 备案ip 查询网站查询系统制作一个网站的成本
  • 微网站排版p9制作公司
  • 国产在线免费观看高甜电影推荐爱站网seo工具包
  • 建设银行官方网站首页入口建立网站如何推广
  • 网站登录界面图片用什么软件做wordpress qiniu
  • 设计素材网站好融资吗关键词排名怎么做好