思维导图:定时器设计

Posted 鱼竿钓鱼干

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了思维导图:定时器设计相关的知识,希望对你有一定的参考价值。

思维导图:定时器设计

Linux 服务器经典定时器设计,根据网上的各种资料简单整理了个思维导图

单个思维导图估计也就个人看看,如果各位有兴趣可以从以下几个问题入手

  • 为啥要有专门的定时器模块
  • 定时器有啥用
  • 怎么定时
  • 关于定时器的设计与几种方案的讨论
  • 和其他模块的结合

下面是 Xmind 生成的 markdown 大纲,方便各位基于我的导图去修改

大纲

为什么需要

  • 定时事件应用
    • 心跳检测
    • 技能冷却
    • 武器冷却
    • 倒计时
    • 检测连接
  • 高效地组织并管理定时事件:把每个定时事件封装成定时器

Linux 定时机制

  • alarm/setitimer:设置超时时间,等待并捕获 SIGALARM 信号
  • 套接字超时选项
  • 多路复用超时参数 select/poll/epoll:看是否返回 0
  • timer_create:本质也是借助信号
  • timerfd_create:通过判断文件描述符来判,可以配合 IO 多路复用

和 IO 协程调度模块的结合(sylar)

  • 用 epoll_wait 来做的超时等待,毫秒级
  • IO协程调度器的idle协程会在调度器空闲时阻塞在epoll_wait上,等待IO事件发生。加入定时器功能后,epoll_wait的超时时间改用当前定时器的最小超时时间来代替。epoll_wait返回后,根据当前的绝对时间把已超时的所有定时器收集起来,执行它们的回调函数。
  • 由于epoll_wait的返回并不一定是超时引起的,也有可能是IO事件唤醒的。要再判断一下定时器有没有超时,用绝对时间就可以轻松判断啦

定时器设计与实现

成员

  • 超时时间
    • 相对时间:注册的时候一般是超时时间
    • 绝对时间:排序和确认超时的时候一般绝对时间
      • gettimeofday 获取绝对时间,依赖系统时间
      • 可能存在校时问题导致定时机制失效
        • 用小的超时步长 + 多次超时才触发 + 检测系统时间有没有往回调
        • 直接换个时间源如 clock_gettime(CLOCK_MONOTONIC_RAW) 获取系统单调时间
  • 任务回调函数

接口设计

  • 初始化
  • 添加定时器
  • 删除定时器
  • 找到最近要发生的定时任务
  • 更新检测定时器
  • 清除定时器

数据结构设计

  • 考虑:支持动态修改并维护有序,高效找到最近要发生的定时任务
  • 几种方案
    • 依赖一个固定周期触发的 tick 信号
      • 升序链表
        • 时间复杂度:添加 O(N),找最小,删除O(1)
          • tick 信号的周期对定时器性能影响比较大:周期小,精度高,CPU 负担高;周期大,精度低,CPU 负担小
          • 定时器数量比较多的时候,插入开销大
      • 时间轮:哈希思想,将定时器散列到不同的有序链表上
        • 每个链表的定时器数量的不会太常,这样插入效率也不会太拉跨;N 越大散列越均匀,插入效率越高。如果 N = 1 那就退化成升序链表了
        • 几种实现
          • 最简单的不带取模的直接一个槽为对应一个时间(纯哈希表)
            • 增删改查都O(1)
            • 可能要很多槽为,空间爆炸
          • 带取模的
            • 特征:同一条链表上每个定时器前后节点定时时间差 N * si 的整数倍(不一定是差 1 个 N);ts = (cs + (ti / si) %N
            • 先 O(1) 找到对应槽为,按有序链表操作
          • 多级时间轮(优雅)
            • 根据定时任务出发的紧急程度,分布到不同层级的时间轮中
            • 均衡了时间(简单的单时间轮差不了多少)和空间
    • 直接把超时时间当作 tick 周期
      • 基本思路:每次都取出所有定时器中超时时间最小的超时值作为一个tick,这样,一旦tick触发,超时时间最小的定时器必然到期。处理完已超时的定时器后,再从剩余的定时器中找出超时时间最小的一个,并将这个最小时间作为下一个tick,如此反复,就可以实现较为精确的定时。根据绝对时间去排序
      • 具体实现
        • 最小堆:增删O(log2N),删除O(n) 因为查找要O(n)可以配合 hash map 来辅助快速索引,查最小O(1)直接根节点
        • 红黑树:都 O(log2N),查最小就是查红黑树的最左节点
        • 其他:跳表

参考资料

《Linux高性能服务器编程》第 11 章
sylar 服务器 定时器模块

以上是关于思维导图:定时器设计的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 中的事件流和事件处理程序(读书笔记思维导图)

设计模式:思维导图

设计模式思维导图总览

协程栈设计 思维导图

协程栈设计 思维导图

面向对象 思维导图