Redis 网络部分代码-Redis Server端

参考http://pauladamsmith.com/articles/redis-under-the-hood.html#event-loop-setup

http://www.yiihsia.com/tag/redis/

Redis Server端

  • initServerConfig()首先初始化配置信息
  1. 这个函数里面会设置server的相关信息如:port、dbnum、Command table等
  2. 先创建Command命令的字典server.commands = dictCreate(&commandTableDictType,NULL)
  3. populateCommandTable()就是将常用的命令加入Command字典
  • loadServerConfig根据命令行参数设置server的配置文件;并且导入配置文件;根据配置文件设置server的port等信息

redis.c 的main函数里面的initServer会执行如下操作

  • 如果需要配置文件里面配置了后台运行程序,那么就fork一个子进程;然后父进程exit;让子进程运行程序
  • initServer
  1. 忽略SIGPIPE写端关闭信号 和SIGHUP终端退出信号
  2. 生成client 、slaves 以及monitors等的list
  3. 创建 sharedObjectsStruct 其中包括robj *crlf, *ok, *err,
  4. aeCreateEventLoop创建aeEventLoop *eventLoop,主要是做一些初始化工作并create一个epollfd
    1. 这个函数里面会调用aeApiCreate来真正的create一个epoll的描述符state->epfd=epoll_create(1024)
  5. 当port为合法的时候就会去调用anetTcpServer;这个函数会anetCreateSocket用于监听客户端请求的socketfd;然后anetListen会bind 还会listen开始监听客户端请求
    1. anetCreateSocket(err,AF_INET)这个函数里会创建一个socket然后会设置socket的相关属性:如设置setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));这样如果一个服务断掉之后不用等待很久就可以立即使用这个端口
  6. 接下来会dictCreate创建dict(此处略去一万字)
  7. aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL)如果有超时时间发生会去调用serverCron这个回调函数
    1. aeCreateTimeEvent里面会设置超时时间;将其添加到timeEventHead里面并作为list的head;并设置这个event的回调函数是serverCron
    2. 接下来应该看的就是serverCron干了些什么
      1. 打印非空db的一些信息,log功能
      2. 如果当前没有后台运行dump数据保存到文件的进程,则可以根据内存使用情况重新调整hashTables大小
      3. 日志输出一些client的连接信息
      4. 检测idle的client 连接,关闭idle连接
      5. 判断是否有正在进行dump数据到文件的后台进程;如果有判断是否已经结束,进行结束后的一些工作(这个跟replication有关,后续详细说明);没有则判断是否需要启动新的进程dump数据到文件
      6. 处理expired的key
      7. vmSwapOut功能,如果启动了vm选项,则判断是否超过vmMaxMemory,如果超过进行value的swap
      8. 判断如果server是slave,则连接master,发送sync命令,和master同步数据
  8. aeCreateFileEvent他的回调函数是acceptTcpHandler;aeCreateFileEvent这里面主要是将要监听的sockfd添加到epoll的事件队列里面epoll_ctl(state->epfd,op,fd,&ee)
    1. acceptTcpHandler至于他的回调函数要干的事情就是anetTcpAccept接受连接;将与客户端已经建立连接的cfd加入到epoll事件队列并调用它的回调函数
      1. acceptCommonHandler这个函数就是将与客户端已经建立连接的cfd加入到epoll事件队列 他会调用createClient:他会设置cfd为非阻塞并且为TcpNoDela然后aeCreateFileEvent将cfd加入到epoll事件队列里面;aeCreateFileEvent的回调函数是readQueryFromClient;处理客户端的Query
        1. createClient(fd)设置fd的属性并且调用aeCreateFileEvent(server.el,fd,AE_READABLE, readQueryFromClient, c) 将fd加入到epoll队列里面;设置Client的若干属性;将该Client加入.server.client的尾部;他的回调函数是readQueryFromClient
          1. readQueryFromClient的作用是读入客户端输入的数据,并调用processInputBuffer解析并处理用户的请求
  9. 如果vm是可用的那么执行 vmInit()(此处略去一万字)
  • aeSetBeforeSleepProc(server.el,beforeSleep):当 Redis进入事件驱动的main循环之前即获取准备就绪事件之前需要完成的工作:这个他会去试着为没有被阻塞的客户处理他们等待在buffer中的命令;并且会调用flushAppendOnlyFile 写AOF缓冲区在硬盘上
  1. 如果vm是可用的那将已经IO准备就绪的进行swap
  2. 执行非阻塞Client命令
  3. 写AOF到disk上
  • aeMain(server.el)在每次进行aeProcessEvent之前都需要调用beforeSleep:
  1. aeProcessEvent获得准备就绪的事件;并且调用它的回调函数.检查超时事件(线性扫描超市队列)并执行超时事件的回调函数
  • aeDeleteEventLoop(server.el)
posted @ 2011-04-07 20:25  洛离  阅读(806)  评论(0)    收藏  举报