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

新公司网络推广推广关键词优化

新公司网络推广,推广关键词优化,公司多个门户是做二级域名还是做多个网站,cms 开源读写分离的作用是为了缓解写库,也就是主库的压力,但一定要基于数据一致性的原则,就是保证主从库之间的数据一定要一致。如果一个方法涉及到写的逻辑,那么该方法里所有的数据库操作都要走主库。 一、环境部署 数据库:…

读写分离的作用是为了缓解写库,也就是主库的压力,但一定要基于数据一致性的原则,就是保证主从库之间的数据一定要一致。如果一个方法涉及到写的逻辑,那么该方法里所有的数据库操作都要走主库。

一、环境部署

  • 数据库:MySql
  • 2个,一主一从
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (`user_id` bigint(20) NOT NULL COMMENT '用户id',`user_name` varchar(255) DEFAULT '' COMMENT '用户名称',`user_phone` varchar(50) DEFAULT '' COMMENT '用户手机',`address` varchar(255) DEFAULT '' COMMENT '住址',`weight` int(3) NOT NULL DEFAULT '1' COMMENT '权重,大者优先',`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `user` VALUES ('1196978513958141952', '测试1', '18826334748', '广州市海珠区', '1', '2019-11-20 10:28:51', '2019-11-22 14:28:26');
INSERT INTO `user` VALUES ('1196978513958141953', '测试2', '18826274230', '广州市天河区', '2', '2019-11-20 10:29:37', '2019-11-22 14:28:14');
INSERT INTO `user` VALUES ('1196978513958141954', '测试3', '18826273900', '广州市天河区', '1', '2019-11-20 10:30:19', '2019-11-22 14:28:30');

二、依赖

<dependencies><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.10</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>2.1.5</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.16</version></dependency><!-- 动态数据源 所需依赖 ### start--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><scope>provided</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId><scope>provided</scope></dependency><!-- 动态数据源 所需依赖 ### end--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.4</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency>
</dependencies>

在这里插入图片描述

三、application.yml配置主从数据源

server:port: 8001
spring:jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Drivermaster:url: jdbc:mysql://127.0.0.1:3307/user?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=trueusername: rootpassword:slave:url: jdbc:mysql://127.0.0.1:3308/user?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&useSSL=false&zeroDateTimeBehavior=convertToNull&allowMultiQueries=trueusername: rootpassword:

四、Config配置

@Getter
public enum DynamicDataSourceEnum {MASTER("master"),SLAVE("slave");private String dataSourceName;DynamicDataSourceEnum(String dataSourceName) {this.dataSourceName = dataSourceName;}
}
@Configuration
@MapperScan(basePackages = "com.xjt.proxy.mapper", sqlSessionTemplateRef = "sqlTemplate")
public class DataSourceConfig{//主库@Bean@ConfigurationProperties(prefix = "spring.datasource.master")public DataSource masterDb(){return DruidDataSourceBuilder.create().build();}//从库@Bean@ConditionalOnProperty(prefix = "spring.datasource", name = "slave", matchIfMissing = true)@ConfigurationProperties(prefix = "spring.datasource.slave")public DataSource slaveDb() {return DruidDataSourceBuilder.create().build();}//主从动态配置@Beanpublic DynamicDataSource dynamicDb(@Qualifier("masterDb") DataSource masterDataSource,@Autowired(required = false) @Qualifier("slaveDb") DataSource slaveDataSource){DynamicDataSource dynamicDataSource = new DynamicDataSource();Map<Object,Object> targetDataSources = new HashMap<>();targetDataSources.put(DynamicDataSourceEnum.MASTER.getDataSourceName(), masterDataSource);if(slaveDataSource != null){targetDataSources.put(DynamicDataSourceEnum.SLAVE.getDataSourceName(), slaveDataSource);}dynamicDataSource.setTargetDataSources(targetDataSources);dynamicDataSource.setDefaultTargetDataSource(masterDataSource);return dynamicDataSource;}@Beanpublic SqlSessionFactory sessionFactory(){SqlSessionFactoryBean bean = new SqlSessionFactoryBean();bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*Mapper.xml"));bean.setDataSource(dynamicDataSource);return bean.getObject();}@Beanpublic SqlSessionTemplate sqlTemplate(){return new SqlSessionTemplate(sqlSessionFactory);}@Bean(name = "dataourceTx")public DataSourceTransactionManager dataSourceTx(){DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dynamicDataSource);return dataSourceTransactionManager;}
}

五、设置路由

为了方便查找对应的数据源,我们可以用ThreadLocal保存数据源的信息到每个线程中,方便我们需要时获取

pubic class DataSourceContextHolder{private static final ThreadLocal<String> DYNAMIC_DATASOURCE_CONTEXT = new ThreadLocal<>();public static void set(String datasourceType) {DYNAMIC_DATASOURCE_CONTEXT.set(datasourceType);}public static String get() {return DYNAMIC_DATASOURCE_CONTEXT.get();}public static void clear() {DYNAMIC_DATASOURCE_CONTEXT.remove();}
}

AbstractRoutingDataSource的作用是基于查找key路由到对应的数据源,它内部维护了一组目标数据源,并且做了路由key与目标数据源之间的映射,提供基于key查找数据源的方法。

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.get();}
}

六、数据源的注解

方便切换数据源,注解中包含数据源对应的枚举值,默认是主库

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSourceSelector {DynamicDataSourceEnum value() default DynamicDataSourceEnum.MASTER;boolean clear() default true;
}

七、Aop切换数据源

定义一个aop类,对有注解的方法做切换数据源的操作

@Slf4j
@Aspect
@Order(value = 1)
@Component
public class DataSourceContextAop {@Around("@annotation(com.xjt.proxy.dynamicdatasource.DataSourceSelector)")public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {boolean clear = true;try {Method method = this.getMethod(pjp);DataSourceSelector dataSourceImport = method.getAnnotation(DataSourceSelector.class);//获取注解标注的方法clear = dataSourceImport.clear();DataSourceContextHolder.set(dataSourceImport.value().getDataSourceName());log.info("========数据源切换至:{}", dataSourceImport.value().getDataSourceName());return pjp.proceed();} finally {if (clear) {DataSourceContextHolder.clear();}}}private Method getMethod(JoinPoint pjp) {MethodSignature signature = (MethodSignature)pjp.getSignature();return signature.getMethod();}}

八、测试

写好Service文件,包含读取和更新两个方法

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@DataSourceSelector(value = DynamicDataSourceEnum.SLAVE)public List<User> listUser() {List<User> users = userMapper.selectAll();return users;}@DataSourceSelector(value = DynamicDataSourceEnum.MASTER)public int update() {User user = new User();user.setUserId(Long.parseLong("1196978513958141952"));user.setUserName("修改后的名字2");return userMapper.updateByPrimaryKeySelective(user);}@DataSourceSelector(value = DynamicDataSourceEnum.SLAVE)public User find() {User user = new User();user.setUserId(Long.parseLong("1196978513958141952"));return userMapper.selectByPrimaryKey(user);}
}

根据方法上的注解可以看出,读的方法走从库,更新的方法走主库,更新的对象是userId为1196978513958141953 的数据

@RunWith(SpringRunner.class)
@SpringBootTest
class UserServiceTest {@AutowiredUserService userService;@Testvoid listUser() {List<User> users = userService.listUser();for (User user : users) {System.out.println(user.getUserId());System.out.println(user.getUserName());System.out.println(user.getUserPhone());}}@Testvoid update() {userService.update();User user = userService.find();System.out.println(user.getUserName());}
}

读取方法
在这里插入图片描述

更新方法
在这里插入图片描述
执行之后,比对数据库就可以发现主从库都修改了数据,说明我们的读写分离是成功的。当然,更新方法可以指向从库,这样一来就只会修改到从库的数据,而不会涉及到主库。

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

相关文章:

  • 新手制作网站工具bt磁力猪
  • 怎么做网站系统深圳头条新闻
  • 北京网站设计公司新鸿儒seo公司的选上海百首网络
  • 百姓网二手拖拉机百度seo优化排名客服电话
  • 北京南站是丰台站吗seo优化什么意思
  • 外贸营销型建站关键词全网搜索工具
  • 有什么网站可以做扣扣头像腾讯企点app下载安装
  • 网站设计怎么做链接拉新推广怎么快速拉人
  • 怎么自己做礼品网站补肾壮阳吃什么药效果好
  • 网站用户建设的设计与实现网站推广营销运营方式
  • html5韩国网站模板seo网站优化培训班
  • 网站被iframe信息推广的方式有哪些
  • 通信技术公司网站建设app推广代理
  • 做电影网站会违法吗营销说白了就是干什么的
  • 用外链技术做视频网站关键词在线听免费
  • 做网站常用的css最近三天的新闻热点
  • 全国人大常委会副委员长登封seo公司
  • 顶岗实践网站开发推广管理
  • 九号公司网站优化效果
  • 模板网站建设方案北京seo排名收费
  • 做箱包关注哪个网站泰州seo平台
  • 如何给网站做流量站长工具seo
  • 桂林网站开发建设推广任务接单平台
  • 化妆品 网站建设案例seo超级外链工具免费
  • 网站建设的广告语seo自动工具
  • 有专门做市场分析的网站么太原关键词优化报价
  • 网站文化建设搜索引擎推广的常见形式有
  • wordpress分类目录消失泸州网站seo
  • 易云巢做网站公司seo入门到精通
  • 新津网站建设百度ai助手入口