业务开发算法 50 讲
黄清昊
Hashdata 数据库内核工程师,LeetCode 高赞答主,公众号微扰理论作者
23292 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
业务开发算法 50 讲
15
15
1.0x
00:00/00:00
登录|注册

32|时间轮:Kafka是如何实现定时任务的?

适用场景:大量定时任务
精度:可调整,影响成本
优势:减少锁竞争,降低取出任务时间复杂度
原理:类似桶排序,按时间分槽位,构成循环队列
应用:Kafka、Netty、ZooKeeper
适用场景:大数据量、需要稳定性和性能
轮询:定时查询ZSET中可执行任务
实现:任务ID(key), 详情(value), 执行时间(score)
原理:用ZSET维护按执行时间排列的任务
适用场景:单机、数据规模不大
线程模型:leader-follower
数据结构:堆
接口:offer(插入任务), take(取出任务)
原理:内存中维护有序结构,按执行时间排序
练习面试题目
考虑非并发场景
实现时间轮算法
时间轮:高效处理大量定时任务,适合分布式系统
Redis ZSET:适合大规模数据的延时任务
DelayedQueue:适合简单的单机延时任务
时间轮算法
Redis中的ZSET
JDK中的DelayedQueue
到时间后发送任务消息给执行主体
存储任务和期望执行时间
外卖订单超时提醒
云平台资源过期处理
电影票选座与付费
作用:延后消息处理时间
定义:在指定时间后才能被处理的消息队列
课后作业
总结
实现方式
延时队列的功能需求
常见业务场景
延时队列的概念
延时队列的实现与应用

该思维导图由 AI 生成,仅供参考

你好,我是微扰君。
今天我们来聊一聊日常开发中非常常见的技术需求:延时队列。
之前在学 Kafka 二分搜索的时候,我们已经学过了消息队列,它是一个用于传递消息的组件,大部分场景下,我们都希望消息尽快送达,并且消息之间要严格遵循先进先出的约束。但在有一些时候,我们也会希望消息不要立刻送达,而是在一段时间之后才会被接收方收到,也就是延后消息被处理的时间,像这样的场景就是“延时队列”。

常见业务场景

延时队列的应用非常多。我们回想一下有哪些业务场景,比如一个网上售卖电影票的平台,用户在买票的时候肯定要先选好位置,也就是说用户下单一张电影票有两个动作:选位置、付费。
我们不希望用户在付费的时候发现,自己选好的位置被别人买了,所以往往会在用户选定座位之后,就把这个位置锁定;但这个时候用户还没有付费,我们肯定不能让锁定一直持续下去,所以也会想要有一种定时机制,在用户超过一定时间没有付费时,在系统中自动取消这个订单,将对应的座位释放。
类似的场景还有许多,对应需要的定时周期跨度也很大。比如在云平台上如果用户资源过期,一般不会立刻清理所有数据,而会在超过一段时间之后再进行资源回收;再比如外卖平台上订单,如果快超过送餐时限了,就需要提醒外卖小哥加紧配送等等。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Kafka实现定时任务的方法及延时队列的常见业务场景和技术需求进行了介绍。文章首先对比了JDK中的DelayedQueue和Redis中的ZSET的实现方式,然后深入解释了时间轮算法的原理和优势。时间轮算法通过将任务按时间分成不同的槽,构成一个循环队列,以槽位时间跨度为周期固定地转动,实现了在某个精度下定时任务或者延时任务的需求。相比之前的实现,时间轮方案减少了任务插入和取出时的锁竞争,提升了效率。总体来说,文章介绍了延时队列的底层实现方式和应用场景,包括JDK中的DelayedQueue、Redis中ZSET以及时间轮算法,并对它们的利弊进行了分析。读者可以结合自身业务场景,选择适合的实现方式。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《业务开发算法 50 讲》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(4)

  • 最新
  • 精选
  • 对方正在输入。。。
    感觉优先队列也可以实现延时队列,只要优先队列按照调度时间优先就可以了吧

    作者回复: 最常见的延时队列实现方式之一就是基于优先队列的;主要是用来快速的找到最近的超时任务。

    2022-04-14
    1
  • peter
    请教老师几个问题: Q1:延时队列和定时任务的区别是什么? 延时队列可以看作是一种特殊的定时任务吗? Q2:时间轮算法: A JDK是否实现了时间轮? B SpringBoot应用是否可以直接利用时间轮?比如引入一个包就可以用。 Q3:时间轮的图中,槽位“3”的队列是双向箭头,槽位“4”对应的队列用了单向箭头,为什么? Q4:ZSET部分,redis是<K:V>对,是两个值,怎么处理id:value:score三个值的情况呢? Q5:ZSET只存储任务ID,不存储具体任务,即redis中并没有具体任务信息。消费端需要维护 “任务id --- 具体任务”映射关系,根据ID找到具体任务执行,是这样吗?
    2022-03-08
    2
  • 陈斌
    第三种实现方式,时间轮,是一个巧妙又高效的设计。牺牲了一定精度,但通过在内存中以循环队列的方式维护任务,降低了任务并行插入的锁竞争,也减少了取出任务的时间复杂度,特别适用于大量定时任务存在的场景,也因此成为 Kafka 实现延时队列的一种常用方式。 1、 特别适用于大量定时任务存在的场景 这个怎么理解,时间轮的设计不也是把元素放在内存中的吗,怎么就特别适合大量定时任务存在的场景,OOM了怎么办? 2、老师能简单的介绍一下 怎么基于时间轮的设计实现 一个基于Kafka的延时队列?消费Kafka的数据放入时间轮中,延时触发任务?
    2022-11-17归属地:广东
    1
  • 陈斌
    JDK 中的 DelayedQueue 可以更好地利用系统内置的定时机制,避免轮询的成本,不过因为单机本身的限制,不能很好的扩展来支持海量的数据场景。 1、JDK的DelayedQueue 不支持海量的数据场景:是因为 DelayedQueue 是无界队列,数据量太多会造成OOM吗? 2、为了提高效率,DelayedQueue 底层还采用了一种 leader-follower 的线程模型,也非常常用,你可以理解成任务的执行会有多个线程进行。 这句话中的任务执行 指的是队列中的元素出队列 的这个操作 吗,leader-follower线程模型 就是 一个线程去读取队列的队首元素是否到期,如果到期这个线程不负责将该元素出队,而是提交任务让其他线程去负责元素的出队操作? 3、 DelayedQueue 是线程安全队列,那么在频繁写入的场景,队列中的元素是获取不到读锁的,也会导致 take 方法阻塞,导致任务被延迟执行。例如极端场景:延迟队列一直在增加数据(队列元素的写锁一直被占有),尽管队列已经有满足条件的元素可以出队了,但是take方法一直会被阻塞,这么理解对吗?
    2022-11-17归属地:广东
收起评论
显示
设置
留言
4
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部