Kafka 时间轮 & 延时队列的实现

Kafka时间轮算法在延时队列中的应用
文章探讨了时间轮算法在Kafka服务端用于高效执行定时任务的原理,同时分析了如何利用DelayQueue解决‘空推进’问题。还提到了在实现延迟队列时,通过设置max.poll.interval.ms避免服务中断后无法恢复的问题,并讨论了自动rebalance的策略。

本文为学习摘录文,感谢原创作者的讲解。

1 时间轮详解

安全验证 - 知乎

深入理解Kafka服务端之高效的时间轮算法在定时任务中的应用 - 墨天轮

https://www.cnblogs.com/keepal/p/16341754.html

2 配合DelayQueue解决“空推进”问题

安全验证 - 知乎

Kafka解惑之时间轮(TimingWheel)

3 延时队列实现方案

安全验证 - 知乎

<<基于kafka实现延迟队列>> 文中使用了resume和pause的方法来实现延迟消息的等待,但是容易出现服务down掉后,一直pause状态无法恢复的问题。自己处理需要做很多工作。

还是使用简单的设置一个较长的

max.poll.interval.ms

的时间,让Kakfa在timeout后可以自动rebanance。

 

延迟任务队列的实现方案 - 黄瓜与土豆的个人空间 - OSCHINA - 中文开源技术交流社区

好的,我来为您介绍一下基于时间轮实现延时队列Java代码实现: ```java import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; public class DelayQueue&lt;T&gt; { private final ConcurrentHashMap&lt;Long, ConcurrentLinkedQueue&lt;T&gt;&gt; wheel; private final ExecutorService executor; private final AtomicInteger currentTick; private final int tickDuration; private final int wheelSize; public DelayQueue(int tickDuration, int wheelSize) { this.wheel = new ConcurrentHashMap&lt;&gt;(); this.executor = Executors.newSingleThreadExecutor(); this.currentTick = new AtomicInteger(0); this.tickDuration = tickDuration; this.wheelSize = wheelSize; start(); } private void start() { executor.submit(() -&gt; { while (!Thread.currentThread().isInterrupted()) { int current = currentTick.get(); ConcurrentLinkedQueue&lt;T&gt; queue = wheel.remove(current); if (queue != null) { for (T item : queue) { System.out.println(&quot;Processing item: &quot; + item); // 这里处理延时的任务 } } currentTick.incrementAndGet(); try { Thread.sleep(tickDuration); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }); } public void add(T item, long delay) { long expirationTime = System.currentTimeMillis() + delay; long key = expirationTime / tickDuration; wheel.computeIfAbsent(key, k -&gt; new ConcurrentLinkedQueue&lt;&gt;()).offer(item); } public void shutdown() { executor.shutdownNow(); } } ``` 这段代码实现了一个基于时间轮算法的延时队列。主要特点如下: 1. 使用ConcurrentHashMap作为时间轮的核心数据结构。 2. 使用单个线程的ExecutorService来驱动时间轮的转动。 3. 使用AtomicInteger来记录当前的时间轮刻度。 4. 可以设置时间轮的刻度持续时间和总刻度数量。 使用示例: ```java public class Main { public static void main(String[] args) throws InterruptedException { DelayQueue&lt;String&gt; delayQueue = new DelayQueue&lt;&gt;(1000, 60); delayQueue.add(&quot;Task1&quot;, 2000); delayQueue.add(&quot;Task2&quot;, 5000); Thread.sleep(7000); delayQueue.shutdown(); } } ``` 在这个示例中,我们创建了一个时间轮刻度为1000毫秒,总刻度为60的时间轮延时队列。然后我们添加了两个任务,分别在2秒和5秒后执行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值