几年前面试时,被问到这个问题。当时,根据市面上常见的几种解决方案进行了回答,比如定时轮询、利用Redis过期机制、RocketMQ延迟消息、被动检测等等。面试官不是很满意,他提了两点点要求:
- 实时性,要达到秒级以内
- 不能使用外部中间件,比如Redis、MQ等
是不是挺变态?当时没给出满足这两个条件的方案。后来在自研大数据调度平台时,在解决任务调度延迟问题时,突然想到了这个问题,恰好可以顺带解决。实际上解决起来很简单,利用定时轮询+延迟队列就可以解决问题。方案如下:
- 定时轮询:每隔M分钟从数据库中获取未来N分钟内超时的订单,需满足条件M<N。M、N的设定结合具体情况就好,根据数据库的承载能力以及N分钟内超时订单的数量。
- 延时队列:把查询到的订单放入到延迟队列中,一般采用JDK自带的DelayQueue即可。然后,用一个单独的线程不断的轮询延迟队列首节点,判断首节点订单是否超时。没超时就继续轮询,超时就放入处理队列,用一个单独的线程池去处理。
方案呢,想出来后,发现异常简单。实时性几乎可以达到毫秒级,什么中间件也没用。