暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Java项目笔记之Redis预热和持久化、游记首页

java学途 2021-06-21
856
不点蓝字,我们哪来故事?



Redis操作流程:

  1. 预热——初始化:以前在操作Redis中的数据之前,需要判断数据是否存在,存在获取,不存在创建一个(即准备数据)。实际中尽量避免,即操作之前就先将数据准备好;

  2. 缓存的逻辑操作:对缓存中的数据做CRUD等操作;

  3. 缓存数据的持久化:缓存中的数据被操作之后,数据库中的数据要不要和Redis被写的数据保持同步;读操作不会改变,不需要持久化;


初始化(预热):

凡是用到Redis的都要思考上面的三个步骤

思考:使用Redis都要想清楚的问题:

  1. 需要初始化什么数据

  • 需要频繁改动的数据(DML)[ 此处需要将统计相关的vo数据初始化到Redis中 ]

  • 不需要频繁改动的数据(DQL)

  1. 在哪一个项目执行初始化逻辑?(mgrsite、website-api)

    • website-api :接口对外暴露,安全性不可保证;website-api后续拓展可能做集群操作,那样就会导致多次执行了初始化操作;

    • 数据初始化数据数据管理范畴,你应该使用mgrsite来管理;

  2. 在JavaWeb中的哪一个组件中实现初始化逻辑?(filter、servlet、intercept、controller、listener)

    • javaweb监听器:监听web(Tomcat)容器的启动,功能简单;

    • spring容器的监听器:监听的是spring容器的启动,功能强大,操作简单;

    • 监听器可以实现一次初始化,后续只有不启动项目,就不会再初始化;

    • 在项目启动后,就应该将数据都准备好,让用户访问更加顺畅,监听器的上帝视角可以完美实现;

    • 初始化逻辑的特点:一次初始化即可;filter和intercept属于拦截过滤范畴,每次都拦截初始化,这样不符合;servlet、controller发起请求的方式初始化,不安全,可以通过代码逻辑控制,这样不适合;最优的选择:listener,容器启动一次,我就初始化,不关闭容器就不会再执行初始化操作;

    • 初始化选择listener

    • 选谁的监听器



Spring 中的5种标准的事件

1.上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。

2.上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。

3.上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。

4.上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。

5.请求处理事件(RequestHandledEvent):在Web应用中,当一个http请求(request)结束触发该事件。


初始化设计

当容器准备好之后马上执行,使用上下文更新事件(ContextRefreshedEvent)

自定义Redis数据初始化监听器:


需要初始化的数据:点赞数、回复数、收藏数、分享数、评论数


上面的代码不完善,逻辑不严谨。还需要:

思考:如果要初始化的数据在Redis中已经存在了,是否需要再初始化一次?

如果vo在Redis中已经存在了,初始化的时候必须跳过;

原因:Redis中存了写的操作,还没有持久化到mongodb中,此时如果再初始化,name数据vo就会被覆盖了,原来的写操作修改了的数据就会丢失。所以,已经存在的数据必须跳过而不是覆盖;


如何实现:

在初始化操作的时候,判断vo是否已经存在,存在就跳过;

如果key存在,说明vo已经存在了;


注意

之前的if判断创没创建的逻辑不能删,因为,如果数据量很大的时候,不是所有的数据都拿来初始化存起来,只初始化活跃的数据(即初始化还要条件筛选),此时if逻辑就起到排除漏网之鱼的作用了;



持久化

问题
  1. 为什么要持久化?

    缓存数据发生变动,如果不进行初始化,DML操作都白做了嘛,所以要持久化到数据库中保存;

  2. 需要持久化什么数据?

    缓存中有用的数据(被改变并且要保存防止丢失),此处需要初始化的数据:a、vo数据;b、用户攻略收藏数据 [ 拓展 ]

  3. 在哪一个项目执行持久化逻辑(mgrsite、website-api)?

    原则上两个都不用,真实项目开发中会额外开发一个项目:定时任务项目,统一执行有定时要求的逻辑;此处选择用mgrsite,因持久化是数据管理范畴,api后续开发会拓展使用集群,若在website-api上定时任务就可能会重复执行了。

  4. 在javaweb的哪一个组件实现持久化逻辑(filter、servlet、intercept、controller、listener)?

    • 持久化特点:多次执行,人工干预请求进行持久化,程序周期性执行(定时器);

    • 此时上面的组件都不合适了,servlet。controller勉强可以,但是我们不希望人工干预执行,不可靠;

    • 持久化逻辑的最佳实践:使用定时器周期性执行(每隔一天执行一次);


SpringBoot定时任务处理:
  • Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。

  • ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。

  • Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

  • Quartz [ 拓展 ]:这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。


实现定时任务处理:
  • @Component

  • @Scheduled(cron = "0/5 * * * * *")


在主配置类上使用@EnableScheduling
注解开启对定时任务的支持



执行时间的配置cron表达式

cron:通过表达式来配置任务执行时间

一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素。按顺序依次为:

字段允许值允许的特殊字符
0~59, - *
0~59, - *
小时0~23, - *
日期1~31, - * ? L W C
月份1~12或者JAN~DEC, - *
星期1~7或者SUN~SAT, - * ? L C #
年(可选)留空,1970~2099, - *

例子:对比着来,实在不行在线生成http://cron.qqe2.com/

测试一把:


定时持久化任务逻辑实现

1.获取所有的攻略vo数据(用前缀批量获取到指定前缀的key集合);

2.更新vo对应的攻略,改动攻略中的统计字段;


从Redis中获得所有攻略的vo:


将vo的list中的vo对象保存到mongodb中:

数据库中没有vo表,怎么更新vo,new 一个攻略对象把vo的属性封装进去,更新攻略表;


为什么不能用vo直接update,而是用攻略?


测试:改为20s

测试成功之后将它的注解注释掉。


面试细节:定时任务的时间间隔,没有标准,根据Redis中的数据量来决定,如果数据量较大,时间周期会短一点(经验值)。一般都是一天/半天,凌晨服务器压力小的时候执行持久化同步;



拓展
  1. 游记数据统计

  2. 用户收藏持久化

    • 传统方式:设计一个中间表保存用户id和攻略id

    • mongodb:在user表中增加一个攻略数组字段favors;或者设置一张表,usid  favors字段




网站首页:

首页,网站默认页面, 是数据整合页面

banner, 指需要在前端网站首页/显示的攻略文章或游记,后续配合爆款营销而设计模块。(可以很复杂,自己了解banner),与钱有关的业务都不简单;

banner推荐:

首页封面类似banner的组件,使用推荐游记前4篇进行列表


需求:设计一个banner表展示


设计banner表之后,做banner的CRUD操作,基本的数据结构;


后端数据的维护mgrsite
banner添加编辑

关键点:二级联动

页面代码:


后台实现:


测试:

添加更新:


测试



website

banner中显示的是游记,需要在首页中将游记的文章查出来

index/index.js


controller

但是我们要取前五个:

可以使用query方法来实现,或者直接使用Pageable


测试


攻略的推荐:

前台代码:

攻略推荐一个:

游记热门排序:



java学途

只分享有用的Java技术资料 

扫描二维码关注公众号

 


笔记|学习资料|面试笔试题|经验分享 

如有任何需求或问题欢迎骚扰。微信号:JL2020aini

或扫描下方二维码添加小编微信

 




小伙砸,欢迎再看分享给其他小伙伴!共同进步!


文章转载自java学途,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论