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

公司注册地址与实际经营地址不符长春seo服务

公司注册地址与实际经营地址不符,长春seo服务,室内设计网站源码下载,广州seo优化排名推广前端每隔15秒就发起一次请求#xff0c;将播放记录写入数据库。 但问题是#xff0c;提交播放记录的业务太复杂了#xff0c;其中涉及到大量的数据库操作#xff1a; 如何进行优化 单机并发能力 变同步为异步 合并写请求 提高单机并发#xff1a;优化SQL#xff0c;尽…前端每隔15秒就发起一次请求将播放记录写入数据库。 但问题是提交播放记录的业务太复杂了其中涉及到大量的数据库操作 如何进行优化 单机并发能力 变同步为异步 合并写请求 提高单机并发优化SQL尽量走索引避免双重for循环添加缓存 提高单机并发能力 变同步为异步 合并写请求 合并写请求方案其实是参考高并发读的优化思路当读数据库并发较高时我们可以把数据缓存到Redis这样就无需访问数据库大大减少数据库压力减少响应时间。 既然读数据可以建立缓存那么写数据可以不可以也缓存到Redis呢 答案是肯定的合并写请求就是指当写数据库并发较高时不再直接写到数据库。而是先将数据缓存到Redis然后定期将缓存中的数据批量写入数据库。 提交学习记录业务优化 记录是否已经存在放入缓存中因为每次提交都会去数据库查询更新学习记录时间放入缓存中 对提交学习记录进行改造每隔15秒进行一次提交对数据库压力太大考虑到只有最后一次提交才有效所以我们对存在数据库操作的地方进行优化 而播放进度信息不管更新多少次下一次续播肯定是从最后的一次播放进度开始续播。也就是说我们只需要记住最后一次即可。因此可以采用合并写方案来降低数据库写的次数和频率而异步写做不到。 如何设计缓存字段 用户学习视频的过程中可能会在多个视频之间来回跳转这就会导致频繁的创建缓存、缓存过期影响到最终的业务性能。该如何解决呢 使用hash key解决 实际操作中可以直接把实体类转化为JSON 当做value存入 但是存在一定问题 但问题来了我们怎么知道哪一次提交是最后一次提交呢 只要用户一直在提交记录Redis中的播放进度就会一直变化。如果Redis中的播放进度不变肯定是停止了播放是最后一次提交。 因此我们只要能判断Redis中的播放进度是否变化即可。怎么判断呢 核心思想 每当前端提交播放记录时我们可以设置一个延迟任务并保存这次提交的进度。等待20秒后因为前端每15秒提交一次20秒就是等待下一次提交检查Redis中的缓存的进度与任务中的进度是否一致。把数据缓存到redis中同时设置一个20秒的延迟任务20秒后执行这个任务执行这个任务的时候再一次跟redis中的时间比对如果一样则更新数据库否则跳过 不一致说明持续在提交无需处理 一致说明是最后一次提交暂停了或者离开播放了提交延迟任务更新学习记录、更新课表最近学习小节和时间到数据库中 延迟任务方案 DelayQueue的用法  package com.tianji.learning.utils;import lombok.Data;import java.time.Duration; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit;Data public class DelayTaskD implements Delayed {private D data;private long deadlineNanos;public DelayTask(D data, Duration delayTime) {this.data data;this.deadlineNanos System.nanoTime() delayTime.toNanos();}Overridepublic long getDelay(TimeUnit unit) {return unit.convert(Math.max(0, deadlineNanos - System.nanoTime()), TimeUnit.NANOSECONDS);}Overridepublic int compareTo(Delayed o) {long l getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);if(l 0){return 1;}else if(l 0){return -1;}else {return 0;}} } 接下来就可以创建延迟任务交给延迟队列保存 package com.tianji.learning.utils;import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test;import java.time.Duration; import java.util.concurrent.DelayQueue;Slf4j class DelayTaskTest {Testvoid testDelayQueue() throws InterruptedException {// 1.初始化延迟队列DelayQueueDelayTaskString queue new DelayQueue();// 2.向队列中添加延迟执行的任务log.info(开始初始化延迟任务。。。。);queue.add(new DelayTask(延迟任务3, Duration.ofSeconds(3)));queue.add(new DelayTask(延迟任务1, Duration.ofSeconds(1)));queue.add(new DelayTask(延迟任务2, Duration.ofSeconds(2)));// TODO 3.尝试执行任务} } 执行任务 package com.tianji.learning.utils;import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test;import java.time.Duration; import java.util.concurrent.DelayQueue;Slf4j class DelayTaskTest {Testvoid testDelayQueue() throws InterruptedException {// 1.初始化延迟队列DelayQueueDelayTaskString queue new DelayQueue();// 2.向队列中添加延迟执行的任务log.info(开始初始化延迟任务。。。。);queue.add(new DelayTask(延迟任务3, Duration.ofSeconds(3)));queue.add(new DelayTask(延迟任务1, Duration.ofSeconds(1)));queue.add(new DelayTask(延迟任务2, Duration.ofSeconds(2)));// 3.尝试执行任务while (true) {DelayTaskString task queue.take();log.info(开始执行延迟任务{}, task.getData());}} } 开始改造 封装的工具类 延迟队列里面放的就是这一个个DelayTaskT Data public class DelayTaskD implements Delayed {private D data;private long deadlineNanos;public DelayTask(D data, Duration delayTime) {this.data data;this.deadlineNanos System.nanoTime() delayTime.toNanos();}Overridepublic long getDelay(TimeUnit unit) {return unit.convert(Math.max(0, deadlineNanos - System.nanoTime()), TimeUnit.NANOSECONDS);}Overridepublic int compareTo(Delayed o) {long l getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);if(l 0){return 1;}else if(l 0){return -1;}else {return 0;}} } 需要开启另一个线程来执行任务 Slf4j RequiredArgsConstructor Component public class LearningRecordDelayTaskHandler {private final StringRedisTemplate redisTemplate;private final DelayQueueDelayTaskRecordTaskData queue new DelayQueue();private final static String RECORD_KEY_TEMPLATE learning:record:{};private final LearningRecordMapper recordMapper;private final ILearningLessonService lessonService;private static volatile boolean begin true;// 项目启动后 当前类实例化 属性输入之后 方法就会运行 一般用来做初始化工作PostConstructpublic void init(){CompletableFuture.runAsync(this::handleDelayTask);log.debug(开启 新线程执行handleDelayTask方法);// 开启 新线程执行handleDelayTask方法}PreDestroy // 当前类是实例 销毁之前该方法执行public void destroy(){log.debug(关闭学习记录处理的延迟任务);begin false;}private void handleDelayTask(){while (begin){try {// 1.尝试获取任务 take是阻塞方法DelayTaskRecordTaskData task queue.take();log.debug(获取到要处理的播放记录任务);RecordTaskData data task.getData();// 2.读取Redis缓存LearningRecord record readRecordCache(data.getLessonId(), data.getSectionId());log.debug(获取到要处理的播放记录任务任务数据{} 缓存中的数据{},data,record);if (record null) {continue;}// 3.比较数据if(!Objects.equals(data.getMoment(), record.getMoment())){// 4.如果不一致播放进度在变化无需持久化continue;}// 5.如果一致证明用户离开了视频需要持久化// 5.1.更新学习记录record.setFinished(null);recordMapper.updateById(record);// 5.2.更新课表LearningLesson lesson new LearningLesson();lesson.setId(data.getLessonId());lesson.setLatestSectionId(data.getSectionId());lesson.setLatestLearnTime(LocalDateTime.now());lessonService.updateById(lesson);log.debug(准备持久化学习记录信息);} catch (Exception e) {log.error(处理播放记录任务发生异常, e);}}}public void addLearningRecordTask(LearningRecord record){// 1.添加数据到Redis缓存writeRecordCache(record);// 2.提交延迟任务到延迟队列 DelayQueuequeue.add(new DelayTask(new RecordTaskData(record), Duration.ofSeconds(20)));}public void writeRecordCache(LearningRecord record) {log.debug(更新学习记录的缓存数据);try {// 1.数据转换String json JsonUtils.toJsonStr(new RecordCacheData(record));// 2.写入RedisString key StringUtils.format(RECORD_KEY_TEMPLATE, record.getLessonId());redisTemplate.opsForHash().put(key, record.getSectionId().toString(), json);// 3.添加缓存过期时间redisTemplate.expire(key, Duration.ofMinutes(1));} catch (Exception e) {log.error(更新学习记录缓存异常, e);}}public LearningRecord readRecordCache(Long lessonId, Long sectionId){try {// 1.读取Redis数据String key StringUtils.format(RECORD_KEY_TEMPLATE, lessonId);Object cacheData redisTemplate.opsForHash().get(key, sectionId.toString());if (cacheData null) {return null;}// 2.数据检查和转换return JsonUtils.toBean(cacheData.toString(), LearningRecord.class);} catch (Exception e) {log.error(缓存读取异常, e);return null;}}public void cleanRecordCache(Long lessonId, Long sectionId){// 删除数据String key StringUtils.format(RECORD_KEY_TEMPLATE, lessonId);redisTemplate.opsForHash().delete(key, sectionId.toString());}// 缓存实体类DataNoArgsConstructorprivate static class RecordCacheData{private Long id;private Integer moment;private Boolean finished;public RecordCacheData(LearningRecord record) {this.id record.getId();this.moment record.getMoment();this.finished record.getFinished();}}// 任务实体类DataNoArgsConstructorprivate static class RecordTaskData{private Long lessonId;private Long sectionId;private Integer moment;public RecordTaskData(LearningRecord record) {this.lessonId record.getLessonId();this.sectionId record.getSectionId();this.moment record.getMoment();}} }使用线程池来处理任务 目前我们的延迟任务执行还是单线程模式大家将其改造为线程池模式 拉取方法 还是使用哪个开辟的线程去拉取但是拉取完之后的执行让线程池里面的来执行 面试题
http://www.hkea.cn/news/14496404/

相关文章:

  • 网站开发从入门到实战生产型或服务型企业网站有哪些
  • 爱玖货源站网站解析设置
  • 上海网站建设价位如何设定网站关键词
  • 物流公司网站建设模板旅游网站建设翻译
  • 大型网站建设翻译英文营销案例100例小故事
  • 网站建设与管理任务分工高端网站价格
  • 网站安全建设总结报告网站建设加盟合作
  • 高端网站设计费用免费制作论坛网站模板
  • 什么网站可以免费做视频的软件下载网站彩票怎么做
  • 做分类信息网站如何郴州新网交友
  • 专业做网站设计公司价格百度云盘下载
  • 网站的维护和更新电子商务网站建设的核心
  • 网站开发案列三门峡企业网站建设公司
  • 济宁亿峰科技做网站一年多少费用网络营销课程论文
  • 网站建设难点和重点开发公司网签的流程
  • 店面门头在线设计网站个人门户网站备案
  • 主机屋网站空间的IPwordpress 禁用可视化
  • 微信网站开发视频站长工具排名分析
  • 彩票网站 模块黄页网如何注册
  • 摄影行业网站wordpress 两边
  • 淘客网站佣金建设在哪做网站建设
  • dedecms精仿学校网站模板宜家在线设计
  • 哪些网站可以做招生信息如何制作企业网站的版式
  • 梅州网站建设梅州网站建设在线建站
  • 横岗网站建设公司全屏式网站
  • 互联在线app开发网站wordpress主题 qux
  • 福州鼓楼区建设局网站越秀重点场所
  • 网站链接推广怎么赚钱界面好看的网站
  • 网站开发过程的数据交互全国物流平台货找车
  • 网站内容分析深圳手机建站模板