定时器的实现方式
- 
数据结构出发
红黑树,最小堆,时间轮,跳表
![]()
4.分布式场景下:定时器设计
 
- 
应用场景出发
单线程,多线程,分布式场景
 
定时器定位;服务器是怎么驱动逻辑的?
网络事件、定时事件、信号事件
怎么实现定时器?
单线程环境下: 通常与网络事件协调处理;
多线程环境下: 单独的定时器进行处理定时事件;
源码:
- redis:单线程,通常与网络事件(搜epoll_wait)协调处理
 

有很多离散的定时事件,拿最近要触发的定时任务,作为epoll_wait网络事件阻塞的时长
取最近要触发的定时任务

- 
nginx:多进程,单线程---红黑树
![]()
![]()
![]()
![]()
红黑树是平衡二叉搜索树,返回树的最左边的叶子节点,就是最小值
 - 
skynet:多线程---时间轮/跳表
跳表是一个多层级链表,空间换时间,实现二分搜索
跳表通过加锁的方式,提供并发读写
![]()
时间轮(linux的定时器也是这个)
不需要维护整个数据结构,只要加到对应时间刻度的链表上(插入o(1))
并且对应的锁粒度也小,只要对某个时间刻度加锁,多线程性能高效
数组(时间轮)的大小必须大于 支持的最大的定时任务
但是又会出现空推进的问题
---所以要增加层级(拆分的思维)(秒层级,分层级,时层级)
![]()
分针移动一格:将此分针指向的任务链表进行重新映射到上一层级(上图是秒层级)
 
分布式场景:
1不能成为系统的风险点
2持久化 强一致性
3确保消费者正确消费 事务
必要性:
没有定时器,删除一个订单则要全表扫描,效率非常低。
如果有定时器就有订单id,可以直接删除,效率高

(分布式这里只是简单讲解)
https://www.bilibili.com/video/BV1uZ4y1r7Fy

(补充知识:
redis
内存 红黑树、跳表---红黑树锁的粒度太大了。要对整棵树加锁
磁盘 lsm tree、B+
)
(kv数据库:lsm-arrary、hashmap、跳表)
                    
                







                
            
        
浙公网安备 33010602011771号