《Redis源码学习笔记》事件库

来源:互联网 发布:时代巨轮知乎 编辑:程序博客网 时间:2024/06/03 19:15

转载自:http://diaocow.iteye.com/blog/1935093


Redis没有使用第三方事件库来处理socket(譬如Libevent),而是自己实现了一个非常精巧的事件库(加上注释不到600行代码),这使得我们可以更加专注于Redis本身代码的阅读,而不必陷于三方库的学习和使用(我自己就是因为该原因选择学习Redis而不是memcache);同时阅读Redis自带的事件库也可以让我们一窥类似Libevent这样的事件库内部实现机制; 

Redis事件库中的所有函数几乎都是以ae开头(原因不得而知),其中最重要的就是aeEventLoop对象,它充当着“事件处理器”角色: 

 
其中“文件事件”是一个数组,存放当前Redis所有连接的客户端描述符,而“时间事件”则是一个链表,用来存放计划任务; 

事件处理器循环流程: 


整个执行流程的伪代码: 

Python代码  收藏代码
  1. def aeMain(aeEventLoop):  
  2.     # 开始事件循环  
  3.     while (not aeEventLoop.stop):  
  4.         aeProcessEvents(aeEventLoop, AE_ALL_EVENTS)  
  5.   
  6. def aeProcessEvents(aeEventLoop, flags):  
  7.     # 是否需要处理时间事件  
  8.     if flags & AE_TIME_EVENTS:  
  9.         # 获取最近一个即将到达的时间事件  
  10.         arrived_time = aeEventLoop.timeEvents.getNearestArrivedTime()  
  11.         if (arrived_time < now_time):  
  12.             # 若最近一个时间事件的arrived_time小于当前时间(说明需要立即执行),则设置文件事件为非阻塞  
  13.             tvp.sec = 0   
  14.             tvp.usec = 0   
  15.         else:  
  16.             # 否则取两者的时间间隔,作为文件事件的最大阻塞时间  
  17.             tvp.sec = arrived_time.sec - now_time.sec  
  18.             tvp.usec = arrived_time.usec - now_time.usec   
  19.     else  
  20.         # 文件事件是否阻塞  
  21.         if flags & AE_DONT_WAIT:  
  22.             tvp.sec = 0   
  23.             tvp.usec = 0   
  24.         else :  
  25.             tvp = null   
  26.   
  27.     # 处理文件事件(IO多路复用)  
  28.     # 若此时没有描述符就绪,tvp的值决定阻塞行为(立即返回?阻塞一段时间?一直阻塞下去?)  
  29.     aeEventLoop.fileEvents.poll(tvp)  
  30.   
  31.     # 处理达到的时间事件  
  32.     if (flags & AE_TIME_EVENTS):   
  33.         aeEventLoop.timeEvents.processArrived()                                                                                                                         

更详细细节,请看:ae.h  ae.c 

总结: 
1. 了解文件事件和时间事件的概念; 
2. 了解Redis事件库运行流程;

0 0
原创粉丝点击