服务端定时器方案(红黑树,时间轮,最小堆)

一. 定时器在工作中的场景

  1. 面试
  2. 为项目添加,替换定时器
  3. 使用定时器

二. 定时器的触发方式

2.1 网络事件和定时事件在同一个线程处理

2.2.1 为什么可以协同处理呢?

		1. reactor是基于事件的网络模型
		2. IO的处理是异步的
		3. 事件的处理是异步的
		4. 定时任务的处理也是异步的

2.2.2 怎样协同处理

网络事件和定时事件在一个线程中处理的过程

  1. 先找到将来要处理的定时任务中的第一个要在多久后处理(设置为timeout)
  2. 将timeout设置为epoll_wait的最后一个参数
  3. epoll_wait在timeout这段时间内,如果没有要处理的IO事件,那么就会返回,然后此时就去处理定时任务
    在这里插入图片描述
    该场景的使用特征:
    1. 适用于定时任务比较少的场景
    2. 对于多线程,会引起事件处理不均衡(有的线程定时任务多,有的少)
    3. 单线程的话,如果定时任务太多,该方法会影响对网络事件的响应。

2.2 网络事件和定时事件在不同线程中处理

定时任务会在单独的线程中进行检测
通常用于大量定时任务的情况
怎么处理? 1. --》通常用usleep(time) 去触发定时器,time要小于最小时间精度
2. --》 通常采用时间轮,加锁粒度比较小
3 .–》时间轮只是负责检测,通常通过信号或插入执行队列让其他线程处理

三. 定时器的设计

3.1 接口设计

让用户使用定时器的接口,通常为下面几个。
在这里插入图片描述
其中find_nearest_timer()接口是针对于网络事件和定时事件在同一线程中的处理的专用接口,其他接口是都用。

add_timer(expire,cb);expire是多长时间后执行此定时事件,进而会回调cb

3.2 数据结构设计

	本质:按照定时任务的优先级进行组织。
	1.  按照触发时间顺序组织。红黑树(绝对有序,nginx),最小堆(相对有序,libevent,libev,go),跳表(未来会用),需要考虑相同时间触发的定时任务
	2.  按照执行顺序,时间轮

四. 常用的实现策略,红黑树和时间轮

4.1 基于红黑树(面试手撕)

在这里插入图片描述

时间轮

从时钟运行看时间的原理
在这里插入图片描述

实现
在这里插入图片描述
时间精度:1s
时间范围:12h

为什么要分成多个层级?

  1. 减少空间占用
  2. 只需要关注最近要触发的任务(最近1min)

未完待续。。。。。

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值