1.被动设置:在查询轮播图的时候检查是否过期并更新状态.
缺点:1.会产生额外的影响,比如:影响轮播图的未过期数量等.
2.影响用户体验,用户查询轮播图列表的时候,可能要处理大量的数据,影响显示的实时性。
3.但是这种方式依赖于用户的查询操作触发,这也就是说如果用户不进行查询轮播图的操作,该轮播图状态就永远不会被更新。
2.定时轮询:启动一个计划任务,定时查询数据,比较过期时间,检查是否过期,更新状态.
缺点:1、时效性差,会有一定的延迟,这个延迟时间最大就是每隔一定时间的大小,
如果你设置每分钟定时轮询一次,那么理论上订单取消时间的最大误差就有一分钟,当然也可能更大,
比如一分钟之内有大量数据,但是一分钟没处理完,那么下一分钟的就会顺延
2.效率低,如果数据量过大会严重影响数据库性能
3.不能够精准的去处理过期轮播图,轮询周期设置的越小,精准度越高,但是项目的压力越大,太多定时器在跑,项目运行起来比较笨重。
3延时队列:将过期的轮播图放入一个延时队列中,依次取出过期的轮播图来进行更新状态
实现:基于JDK的实现方法,将过期的轮播图放到一个有序的队列中,程序会自动依次取出过期的轮播图。
如果当前没有过期的轮播图,就会阻塞,直至有过期的轮播图。由于每次只处理过期的轮播图,并且处理的时间也很精准.
不存在定时调度方案的那两个弊端。
5.可以采用MQ,延时队列DelayQueue来实现。
mq提供的延时队列
优点:消息0丢失,可抗高并发
缺点:需要额外引入mq中间件,提高系统复杂性和mq高可用维护性
4.过期提醒:redis支持将一个过期的key(轮播图编号)通知给客户端,根据过期的轮播图编号进行相应的处理。
基于redis的过期提醒功能,处理过期的轮播图。
实现:修改个redis的配置,redis默认不开启过期提醒。
notify-keyspace-events改为notify-keyspace-events “Ex”
写一个类用来接收来自redis的过期提醒OrderExpirationListener,
继承一下KeyExpirationEventMessageListener抽象类。
重写onMessage()方法,在此方法中处理接收到的过期key.
缺点:
开启键通知会对redis有额外的开销
键通知暂时redis并不保证消息必达,redis客户端断开连接所有key丢失
消费速度不可自控,如果一瞬间QPS非常高,接收到的通知会非常密集,消费不过来,
如果用线程池消费,大部分的待消费任务会放入到阻塞队列 一旦服务宕机,阻塞队列消息全部丢失