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

设计师找图网站wordpress导航栏下拉菜单代码

设计师找图网站,wordpress导航栏下拉菜单代码,网站备案网站名称怎么填,做网站要交钱吗文章目录 一.什么是MySQL 读写分离二.读写分离的几种实现方式(手动控制)1.基于Spring下的AbstractRoutingDataSource1.yml2.Controller3.Service实现4.Mapper层5.定义多数据源6.继承Spring的抽象路由数据源抽象类#xff0c;重写相关逻辑7. 自定义注解WR#xff0c;用于指定当… 文章目录 一.什么是MySQL 读写分离二.读写分离的几种实现方式(手动控制)1.基于Spring下的AbstractRoutingDataSource1.yml2.Controller3.Service实现4.Mapper层5.定义多数据源6.继承Spring的抽象路由数据源抽象类重写相关逻辑7. 自定义注解WR用于指定当前操作使用哪个库8. 切面逻辑9.源码简单分析10. 开始测试 2.基于Mybatis的SqlSessionFactory1.yml2.Controller3.Service实现4.Mapper层5.配置类1. 指定哪些Mapper接口使用读数据源2. 指定哪些Mapper接口使用写数据源 6. 开始测试 3.基于baomidou动态数据源实现读写分离(最简单)1. maven依赖2.yml3.Controller4.Service5.Mapper层6.开始测试 三.小结 一.什么是MySQL 读写分离 我记得实习的第一家公司做个一个项目就用过mysql多数据源的读写分离方案4年前了…依稀记得也是在mapper层面来分离的但那时候是我同事弄的完全不懂怎么实现的觉得他好厉害。从此成了心里的一道坎很久之前就了解了一直想着要写篇博客记录下ok那赶紧开始吧~ 先了解下概念什么是读写分离、优势、实现方式、注意事项、和使用场景。如果项目里面有用到数据库集群开始有性能方面问题结合业务场景及综合衡量下去考虑是否适用数据库读写分离方案。 以下解释来自chatgpt我觉得说的挺好的。 MySQL 读写分离是一种数据库优化策略通过将数据库的读操作和写操作分开分别交由不同的数据库实例处理以提高系统的性能和扩展性。具体来说读写分离通常涉及一个主数据库Master和一个或多个从数据库Slave它们通过复制机制保持数据的一致性。 以下是读写分离的核心概念 主从复制Master-Slave Replication 主库Master负责处理所有的写操作INSERT、UPDATE、DELETE 等也可以处理读操作。从库Slave主要用于处理读操作SELECT不会直接接收写操作。从库通过复制机制从主库同步数据确保数据一致性。 读写分离的优势 提高读性能由于从库处理读操作可以通过增加从库实例来扩展系统的读性能减轻主库的负担。 减少主库压力写操作集中在主库从库处理大部分的读操作主库的压力减少有助于提高写操作的响应速度。 容错性在某些情况下从库可以用作备份如果主库出现故障可以临时将从库提升为主库以保持服务的可用性。 实现方式 读写分离可以通过多种方式实现包括 手动分离应用程序通过逻辑代码手动决定读请求发送到从库写请求发送到主库。代理层中间件使用数据库中间件如 MySQL Proxy、MaxScale、MyCat等在应用和数据库之间自动实现读写分离和负载均衡。连接池支持某些数据库连接池如 Druid、HikariCP可以自动支持主从库的读写分离。 注意事项 数据一致性问题由于复制存在延迟从库上的数据可能会比主库滞后。如果应用程序对实时数据一致性要求较高需谨慎处理。负载均衡要合理分配读请求到不同的从库避免单个从库成为瓶颈。主库故障恢复需要设计可靠的故障转移机制确保主库出现问题时从库能够及时接管。 使用场景 读写分离适用于读操作远多于写操作的场景例如电商平台、社交媒体网站等。在这些场景中读请求往往占大多数通过读写分离可以有效提升系统的扩展性和性能。 二.读写分离的几种实现方式(手动控制) 这里只介绍手动分离读写库应用程序通过逻辑代码手动决定读请求发送到从库写请求发送到主库的几种实现方式。 1.基于Spring下的AbstractRoutingDataSource 根据大家平常开发习惯我还是从controller层开始吧。 1.yml 我的yml配置如下 spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedatasource1:url: jdbc:mysql://127.0.0.1:3306/tl_mall_master?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driverdatasource2:url: jdbc:mysql://127.0.0.1:3306/tl_mall_slave?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driver2.Controller RestController RequestMapping(friend) Slf4j public class FriendController {Autowiredprivate FriendService friendService;GetMapping(value select)public ListFriend select(){return friendService.list();}GetMapping(value insert)public String in(){Friend friend new Friend();friend.setName(jinbiao666);friendService.save(friend);return 主库插入成功;} }3.Service实现 Service public class FriendImplService implements FriendService {AutowiredFriendMapper friendMapper;OverrideWR(R) // 库2public ListFriend list() {return friendMapper.list();}OverrideWR(W) // 库1public void save(Friend friend) {friendMapper.save(friend);} }4.Mapper层 public interface FriendMapper {Select(SELECT * FROM friend)ListFriend list();Insert(INSERT INTO friend(name) VALUES (#{name}))void save(Friend friend); }5.定义多数据源 Configuration public class DataSourceConfig {BeanConfigurationProperties(prefix spring.datasource.datasource1)public DataSource dataSource1() {// 底层会自动拿到spring.datasource中的配置 创建一个DruidDataSourcereturn DruidDataSourceBuilder.create().build();}BeanConfigurationProperties(prefix spring.datasource.datasource2)public DataSource dataSource2() {// 底层会自动拿到spring.datasource中的配置 创建一个DruidDataSourcereturn DruidDataSourceBuilder.create().build();} }6.继承Spring的抽象路由数据源抽象类重写相关逻辑 继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource抽象类。重写determineCurrentLookupKey方法设置当前db操作应使用的数据源key重写afterPropertiesSet方法设置多数据源和默认数据源。 Component Primary public class DynamicDataSource extends AbstractRoutingDataSource {/*** 通过ThreadLocal设置当前线程所使用的数据源key*/public static ThreadLocalString name new ThreadLocal();// 写AutowiredDataSource dataSource1;// 读AutowiredDataSource dataSource2;// 返回当前数据源标识,根据返回的key决定最终使用的数据源Overrideprotected Object determineCurrentLookupKey() {return name.get();}/*** InitializingBean 是 Spring 框架中的一个接口用于在 Bean 初始化完成后执行特定的操作。它定义了一个方法 afterPropertiesSet()当 Bean 的属性设置完成后会被调用。* Spring 容器会在实例化该 Bean 并设置完属性后自动调用 afterPropertiesSet() 方法来执行一些初始化操作*/Overridepublic void afterPropertiesSet() {// 为targetDataSources初始化所有数据源MapObject, Object targetDataSourcesnew HashMap();targetDataSources.put(W,dataSource1);targetDataSources.put(R,dataSource2);super.setTargetDataSources(targetDataSources);// 为defaultTargetDataSource 设置默认的数据源super.setDefaultTargetDataSource(dataSource1);super.afterPropertiesSet();} }7. 自定义注解WR用于指定当前操作使用哪个库 Target({ElementType.METHOD,ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) public interface WR {String value() default W; }8. 切面逻辑 Component Aspect public class DynamicDataSourceAspect implements Ordered {// 前置Before(within(com.tuling.dynamic.datasource.service.impl.*) annotation(wr))public void before(JoinPoint point, WR wr){// 设置数据源key为注解值determineCurrentLookupKey()方法里面会去取这个key)DynamicDataSource.name.set(wr.value());}Overridepublic int getOrder() {return 0;} }9.源码简单分析 简单看下AbstractRoutingDataSource里面的determineTargetDataSource决定目标数据源方法。 10. 开始测试 给master写库的friend表清空写入写库 写库写入成功 给slave读库的friend表插入一条数据rise仅查询到读库的内容成功实现读写分离。 2.基于Mybatis的SqlSessionFactory 一样还是从yml开始吧目录结果清晰些。 1.yml spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedatasource1:url: jdbc:mysql://127.0.0.1:3306/tl_mall_master?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driverdatasource2:url: jdbc:mysql://127.0.0.1:3306/tl_mall_slave?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driver server:port: 80802.Controller RestController RequestMapping(friend) Slf4j public class FriendController {Autowiredprivate FriendService friendService;GetMapping(value select)public ListFriend select(){return friendService.select();}GetMapping(value insert)public void insert(){Friend friend new Friend();friend.setName(jinbiao666);friendService.insert(friend);} }3.Service实现 /**** 读数据源配置:* 1. 指定扫描的mapper接口包从库* 2. 指定使用sqlSessionFactory是哪个从库*/ Service public class FriendImplService implements FriendService {Autowiredprivate RFriendMapper rFriendMapper;Autowiredprivate WFriendMapper wFriendMapper;// 读-- 读库Overridepublic ListFriend select() {return rFriendMapper.select();}// 保存-- 写库Overridepublic void insert(Friend friend) {wFriendMapper.insert(friend);}}4.Mapper层 在mapper层做的读写区分。 public interface RFriendMapper {Select(SELECT * FROM friend)ListFriend select();Insert(INSERT INTO friend(name) VALUES (#{name}))void save(Friend friend); }public interface WFriendMapper {Select(SELECT * FROM friend)ListFriend list();Insert(INSERT INTO friend(name) VALUES (#{name}))void insert(Friend friend); }5.配置类 1. 指定哪些Mapper接口使用读数据源 通过MapperScan注解扫对应的mapper接口然后设置数据源为从数据源构造一个SqlSessionFactory 对象。事务管理器用作事务回滚暂不测试事务回滚了都是可成功的. /**** 写数据源配置:* 1. 指定扫描的mapper接口包主库* 2. 指定使用sqlSessionFactory是哪个主库*/ Configuration MapperScan(basePackages com.tuling.datasource.dynamic.mybatis.mapper.r, sqlSessionFactoryRefrSqlSessionFactory) public class RMyBatisConfig {BeanConfigurationProperties(prefix spring.datasource.datasource2)public DataSource dataSource2() {// 底层会自动拿到spring.datasource中的配置 创建一个DruidDataSourcereturn DruidDataSourceBuilder.create().build();}BeanPrimarypublic SqlSessionFactory rSqlSessionFactory() throws Exception {final SqlSessionFactoryBean sessionFactory new SqlSessionFactoryBean();// 指定主库sessionFactory.setDataSource(dataSource2());// 指定主库对应的mapper.xml文件/*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath:mapper/r/*.xml));*/return sessionFactory.getObject();}Beanpublic DataSourceTransactionManager rTransactionManager(){DataSourceTransactionManager dataSourceTransactionManager new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource2());return dataSourceTransactionManager;}Beanpublic TransactionTemplate rTransactionTemplate(){return new TransactionTemplate(rTransactionManager());} }2. 指定哪些Mapper接口使用写数据源 Configuration MapperScan(basePackages com.tuling.datasource.dynamic.mybatis.mapper.w, sqlSessionFactoryRefwSqlSessionFactory) public class WMyBatisConfig {BeanConfigurationProperties(prefix spring.datasource.datasource1)public DataSource dataSource1() {// 底层会自动拿到spring.datasource中的配置 创建一个DruidDataSourcereturn DruidDataSourceBuilder.create().build();}BeanPrimarypublic SqlSessionFactory wSqlSessionFactory() throws Exception {final SqlSessionFactoryBean sessionFactory new SqlSessionFactoryBean();// 指定主库sessionFactory.setDataSource(dataSource1());// 指定主库对应的mapper.xml文件/*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(classpath:mapper/order/*.xml));*/return sessionFactory.getObject();}BeanPrimarypublic DataSourceTransactionManager wTransactionManager(){DataSourceTransactionManager dataSourceTransactionManager new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource1());return dataSourceTransactionManager;}Beanpublic TransactionTemplate wTransactionTemplate(){return new TransactionTemplate(wTransactionManager());} }6. 开始测试 1.写写库成功之前只有1条现在2条。ok基于Mybatis在mapper层面的读写分离也成功了 2.读读库 其他场景比如写库失败回滚都是可以的因为我们给DataSourceTransactionManager注入了写库的数据源。这里不展示了。 3.基于baomidou动态数据源实现读写分离(最简单) 1. maven依赖 dependencygroupIdcom.baomidou/groupIdartifactIddynamic-datasource-spring-boot-starter/artifactIdversion3.5.0/version/dependency2.yml 一主两从 spring:datasource:dynamic:#设置默认的数据源或者数据源组,默认值即为masterprimary: master#严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源strict: falsedatasource:master:url: jdbc:mysql://127.0.0.1:3306/tl_mall_master?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driverslave_1:url: jdbc:mysql://127.0.0.1:3306/tl_mall_slave?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driverslave_2:url: jdbc:mysql://127.0.0.1:3306/tl_mall_user?serverTimezoneUTCuseUnicodetruecharacterEncodingUTF8useSSLfalseusername: rootpassword: 123456initial-size: 1min-idle: 1max-active: 20test-on-borrow: truedriver-class-name: com.mysql.cj.jdbc.Driver server:port: 80803.Controller RestController RequestMapping(frend) Slf4j public class FriendController {Autowiredprivate FriendService friendService;GetMapping(value select)public ListFriend select(){return friendService.select();}GetMapping(value insert)public void insert(){Friend friend new Friend();friend.setName(jinbiao666);friendService.insert(friend);} } 4.Service Service public class FriendImplService implements FriendService {AutowiredFriendMapper friendMapper;OverrideDS(slave2) // 从库2public ListFriend select() {return friendMapper.select();}OverrideDS(master) // 主库//DS(#session.userID) 基于session里面的用户id取数据源,sass化,数据源动态根据用户选择。DSTransactional //开启事务操作public void insert(Friend friend) {friendMapper.insert(friend);} }5.Mapper层 public interface FriendMapper {Select(SELECT * FROM friend)ListFriend select();Insert(INSERT INTO friend(name) VALUES (#{name}))void insert(Friend friend); }6.开始测试 使用是不是超级简单省去了很多自己注入的步骤如使用DS注解选择数据源、DSTransactional注解回滚对应的数据源事务等等都由baomidou帮我们实现了。 写写库成功之前只有2条现在3条。ok基于baomidou动态数据源实现读写分离也成功了 读slave_2(tl_mall_user)可以看到数据库3条数据 接口测试查询从库slave_2,没问题 事务回滚暂不在这里做测试了替大家测过了的没问题~ 三.小结 经过上面3种方式介绍多数据源读写分离是不是很简单。不过上面都是对单数据源写入操作的可以使用Transactional或者DSTransactional帮我们回滚单数据源的事务。如果涉及到多数据源的写入需要统一提交回滚怎么实现呢小伙伴们不妨也思考一下这个问题这其实就是相当于是分布式事务的回滚了。
http://www.dnsts.com.cn/news/223866.html

相关文章:

  • ppt模板网站排行榜公司门户网站是什么
  • 专门做lolh的网站免费做网络推广
  • dw是做静态网站还是动态的网络程序设计实验报告
  • 做视频网站需要什么条件WordPress文章批量生成器
  • 网站建设 检查 通报2345浏览器网址
  • 郑州网站建设报价微信企业邮箱
  • 安徽合肥网站制作纸业建站服务
  • 淘宝客怎么做推广网站英文网站建设公司
  • 广州南沙建设和交通局网站厦门app制作
  • 网站开发的背景如何在对方网站上做外链
  • vue适合什么网站开发新手做网站做什么样的
  • 手机响应式网站wordpress摘要插件
  • 移动网站转码友情链接检测
  • 微信公众号怎么做成微网站万网网站发布
  • wordpress调用当前分类列表西安seo优化公司
  • 个人网站建设公司微信软件如何开发
  • 网站高速下载如何做域名及对应网站
  • 衡阳网站开发定制网站开发蒙特
  • 做网站是干嘛的上海网站 备案查询
  • 做招聘网站的需求分析中国菲律宾最新消息
  • 做优惠卷网站倒闭了多少wordpress启动ssl
  • 如何防止网站被采集杭州有做网站
  • 建筑论坛网站软件培训班学费多少
  • 微信公众号建立网站网站 怎么备案
  • 全球网站访问量排名WordPress手机不显示
  • 如何做好公司网站建设中山 网站定制
  • 广告图片网站关键词优化诊断
  • 建设的网站都是怎么赚钱wordpress图片快速主题
  • 有什么好的提供外链网站订单拆单在电商网站建设
  • 新网站推广方法智慧团建官网登录口入口