延时队列实现方法列表

1、JDK提供的DelayQueue

一种支持延时获取元素的无界阻塞队列。

内部持有一个PriorityQueue,每个对象都被放入了这个队列,队列中的对象按照优先级进行了排序,队列头部是最先会超时的对象。

take方法会一直阻塞,直到队列头部的对象超时后才可以被取出。

2、Redis sorted set(ZSET)

实现思路大同小异。以过期时间的时间戳作为score。

生产者将消息内容作为member,时间戳作为score调用ZADD来生产消息;

消费者用ZRANGEBYSCORE命令获取N秒之前的数据进行轮询处理,使用min和max向前推N秒来卡延时的消息。

3、RabbitMQ

rabbitMQ中可以对Message设置 x-message-ttl(TTL = Time To Live)来控制消息的生存时间。超时以后消息变为dead letter(死信)。

同时,RabbitMQ的Queue可以配置x-dead-letter-exchange 和x-dead-letter-routing-key(可选)两个参数,如果队列内出现了dead letter,则按照这两个参数重新路由转发到指定的队列。

利用这样的特性,设置两个队列,A队列无消费者,生产者向该队列发送消息,消息设定TTL;同时设定A中出现死信以后将消息转发到B队列;B队列使用正常设定即可,所有消费者从B读取消息。

即可完成延时时间为TTL的延时队列。

4、Redis 过期回调

在Redis中开启监听key是否过期的事件,一旦key过期会触发一个callback事件。

有点类似MQ的队列事件监听。

5、Kafka

Kafka有专门用于实现延迟功能的定时器(SystemTimer)。底层使用的是时间轮(TimingWheel)模型(环形队列,下面挂接双向链表)。

操作效率非常高。JDK的DelayQueue插入和删除操作的平均时间复杂度为O(nlog(n)),而Kafka基于时间轮可以将插入和删除操作的时间复杂度都降为O(1)。

6、Netty等同样实现了时间轮的中间件

你可能感兴趣的:(请叫我攻城狮)