Redis源码分析(一)redis.c //redis-server.c

Redis源码分析(一)redis.c //redis-server.c

入口函数 int main()

  4450 int main(int argc, char **argv) {
  4451     initServerConfig();
  4452     if (argc == 2) {
  4453         ResetServerSaveParams();
  4454         loadServerConfig(argv[1]);
  4455     } else if (argc > 2) {
  4456         fprintf(stderr,"Usage: ./redis-server [/path/to/redis.conf]\n");
  4457         exit(1);
  4458     } else {
  4459         redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'");
  4460     }
  4461     initServer();
  4462     if (server.daemonize) daemonize();
  4463     redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION);
  4464 #ifdef __linux__
  4465     linuxOvercommitMemoryWarning();
  4466 #endif
  4467     if (rdbLoad(server.dbfilename) == REDIS_OK)
  4468         redisLog(REDIS_NOTICE,"DB loaded from disk");
  4469     if (aeCreateFileEvent(server.el, server.fd, AE_READABLE,
  4470         acceptHandler, NULL, NULL) == AE_ERR) oom("creating file event");
  4471     redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
  4472     aeMain(server.el);
  4473     aeDeleteEventLoop(server.el);
  4474     return 0;
  4475 }     

初始化参数 initServerConfig()

   static void initServerConfig() {
      server.dbnum = REDIS_DEFAULT_DBNUM;//初始化redis的数据库个数16
      server.port = REDIS_SERVERPORT;//端口6379
      server.verbosity = REDIS_DEBUG;//默认这个为0
      // 这个是日志级别,有三种
      //#define REDIS_DEBUG 0                                                                                                                                                                          
      //#define REDIS_NOTICE 1 
      //#define REDIS_WARNING 2
      server.maxidletime = REDIS_MAXIDLETIME;//最大空闲时间60*5,也是客户端的超时时间
      server.saveparams = NULL;//持久化策略
      server.logfile = NULL; /* NULL = log on standard output, 也可以在后期脚本文件中将参数传入 */
      server.bindaddr = NULL;
      server.glueoutputbuf = 1;//在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启。
      server.daemonize = 0;设置redis是否以守护进程方式运行,默认为no。
      server.pidfile = "/var/run/redis.pid";
      server.dbfilename = "dump.rdb";
      server.requirepass = NULL;//设置redis连接的密码,设置之后客户端连接redis时需要先通过auth命令提供密码进行验证才能进行后续操作,默认没有密码。设置操作:requirepass mypass
      server.shareobjects = 0;
      server.sharingpoolsize = 1024;
      server.maxclients = 0;
      server.maxmemory = 0;
      ResetServerSaveParams();

      appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */
      appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */
      appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */
      /* Replication related */
      server.isslave = 0;
      server.masterhost = NULL;
      server.masterport = 6379;
      server.master = NULL;
      server.replstate = REDIS_REPL_NONE;
  }

初始化函数中的server变量包含

   223 /* Global server state structure */
   224 struct redisServer {
   225     int port; //端口号
   226     int fd; //文件描述符
   227     redisDb *db; // 一个数组,保存着服务器中的所有数据库
   228     dict *sharingpool; //存放数据的哈希表
   229     unsigned int sharingpoolsize;
   230     long long dirty; /* changes to DB from the last save */
   231     list *clients; //客户端链表
   232     list *slaves, *monitors;
   233     char neterr[ANET_ERR_LEN]; //网络错误信息存储,最多256个char
   234     aeEventLoop *el; //事件循环结构体 
   235     int cronloops;              /* number of times the cron function run */
   236     list *objfreelist;          /* A list of freed objects to avoid malloc() */
   237     time_t lastsave;            /* Unix time of last save succeeede */
   238     size_t usedmemory;             /* Used memory in megabytes */
   239     /* Fields used only for stats */
   240     time_t stat_starttime;         /* server start time */
   241     long long stat_numcommands;    /* number of processed commands */
   242     long long stat_numconnections; /* number of connections received */
   243     /* Configuration */
   244     int verbosity;
   245     int glueoutputbuf;
   246     int maxidletime; //最大空闲时间
   247     int dbnum; //数据库的数量
   248     int daemonize;
   249     char *pidfile;
   250     int bgsaveinprogress;
   251     pid_t bgsavechildpid;
   252     struct saveparam *saveparams; //持久化参数
   253     int saveparamslen;
   254     char *logfile; //日志文件路径
   255     char *bindaddr;
   256     char *dbfilename;
   257     char *requirepass;
   258     int shareobjects;
   259     /* Replication related */
   260     int isslave;
   261     char *masterhost;
   262     int masterport;
   263     redisClient *master;    /* client that is master for this slave */
   264     int replstate;
   265     unsigned int maxclients; 
   266     unsigned int maxmemory;
   267     /* Sort parameters - qsort_r() is only available under BSD so we
   268      * have to take this state global, in order to pass it to sortCompare() */
   269     int sort_desc;
   270     int sort_alpha;
   271     int sort_bypattern;
   272 };
   273 

server函数中的redisDb *db;结构体

   190 typedef struct redisDb {                                                                                                                                                                                                         
   191     dict *dict; //当前数据库的键空间
   192     dict *expires; //键的过期时间
   193     int id; //数据库ID标识
   194 } redisDb;
   195     

server函数中的dict结构体

结构体位于:dict.h

 67 //哈希表的定义                                                                                                  
 68 typedef struct dict {                                                                                           
 69     //指向实际的哈希表记录(用数组+开链的形式进行保存)                                                           
 70     dictEntry **table;                                                                                          
 71     //type中包含一系列哈希表需要用到的函数                                                                      
 72     dictType *type;                                                                                             
 73     //size表示哈希表的大小,为2的指数                                                                           
 74     unsigned long size;                                                                                         
 75     //sizemask=size-1,方便哈希值根据size取模                                                                    
 76     unsigned long sizemask;                                                                                     
 77     //used记录了哈希表中有多少记录                                                                              
 78     unsigned long used;                                                                                         
 79     void *privdata;                                                                                             
 80 } dict;                                                                                                         
 81 
 82 //对Hash表进行迭代遍历时使用的迭代器
 83 typedef struct dictIterator {                                                                                   
 84     dict *ht;                                                                                                   
 85     int index;                                                                                                  
 86     dictEntry *entry, *nextEntry;                                                                               
 87 } dictIterator;                                                                                                 
 88 

dict结构体中的dictEntry

 46 //实际存放数据的地方
 47 typedef struct dictEntry {
 48     void *key;
 49     void *val;
 50     struct dictEntry *next;
 51 } dictEntry;
 52 

dict结构体中的dictType

 53 //要作用于哈希表上的相关函数
 54 /*
 55  * dictType在哈希系统中包含了一系列可由应用程序定义的
 56  * 函数指针
 57  */
 58 typedef struct dictType {
 59     unsigned int (*hashFunction)(const void *key);//哈希函数
 60     void *(*keyDup)(void *privdata, const void *key);//key复制
 61     void *(*valDup)(void *privdata, const void *obj);//value复制
 62     int (*keyCompare)(void *privdata, const void *key1, const void *key2);//key比较
 63     void (*keyDestructor)(void *privdata, void *key);//key销毁
 64     void (*valDestructor)(void *privdata, void *obj);//value销毁
 65 } dictType;
 66 

server函数中的list结构体

adlist.h

 67 /*                                                                                                              
 68  * redis中的双向链表                                                                                            
 69  * head标识链表的头指针                                                                                         
 70  * tail标识链表的尾结点                                                                                         
 71  * dup/free/match是三个函数指针                                                                                 
 72  * dup用于复制链表,返回值也是一个函数指针                                                                      
 73  * free用于释放链表                                                                                             
 74  * match用于判断链表中是否存在*key的值                                                                          
 75  * len标识链表的长度                                                                                            
 76  * listIter链表的迭代器,通过此迭代器可以对链表进行遍历                                                         
 77  * 至于为什么要提供这种迭代器,可以查看设计模式相关的书箱                                                       
 78  */                                                                                                             
 79                                                                                                                 
 80 typedef struct list {                                                                                           
 81     listNode *head;//链表的头结点                                                                         
 82     listNode *tail;//链表的尾节点                                                                      
 83     void *(*dup)(void *ptr);//复制链表                                                                     
 84     void (*free)(void *ptr);//释放内存                                                                     
 85     int (*match)(void *ptr, void *key);//匹配                                                                         
 86     unsigned int len; //标识链表的长度,                                                                                         
 87     listIter iter;                                                                                              
 88 } list;                                                                                                         
 89                       

listNode结构体

 40 /*                                                                                                              
 41  * redis中最基本的结构用以标识链表中的结点                                                                      
 42  * *prev标识上一个节点                                                                                          
 43  * *next标识下一个节点                                                                                          
 44  * *value标识节点的值                                                                                           
 45  */                                                                                                             
 46                                                                                                          
 47 typedef struct listNode {                                                                                       
 48     struct listNode *prev;                                                                                      
 49     struct listNode *next;                                                                                      
 50     void *value;                                                                                                
 51 } listNode;                                                                                                     
 52   

迭代器

 53 /*                                                                                                              
 54  * 迭代器用于链表的遍历                                                                                         
 55  * next将要遍历的下一个元素                                                                                     
 56  * direction遍历链表的方向                                                                                      
 57  * 方向由下面的两个宏进行标识                                                                                   
 58  * AL_START_HEAD表示向前                                                                                        
 59  * AL_START_TAIL表示向后                                                                                        
 60  */                                                                                                             
 61                                                                                                                 
 62 typedef struct listIter {                                                                                       
 63     listNode *next;                                                                                             
 64     int direction;                                                                                              
 65 } listIter;                                                                                                     
 66  

server函数中的aeEventLoop *el结构体

ae.h

112 
113 /* State of an event based program */
114 /**
115  * 事件循环结构体
116  */
117 typedef struct aeEventLoop {
118     //用于标识下一个定时器
119     long long timeEventNextId;
120     //文件事件
121     aeFileEvent *fileEventHead;
122     //定时器事件
123     aeTimeEvent *timeEventHead;
124     //stop用于停止事件轮询
125     int stop;
126 } aeEventLoop;
127 

aeEventLoopd的aeFileEvent和aeTimeEvent

 78 typedef struct aeFileEvent {
 79     int fd;
 80     /**
 81      * AE_READABLE|AE_WRITEABLE_AE_EXCEPTION中的一个
 82      * 表示要监听的事件类型
 83      */
 84     int mask; /* one of AE_(READABLE|WRITABLE|EXCEPTION) */
 85     //文件事件相应的处理函数
 86     aeFileProc *fileProc;
 87     aeEventFinalizerProc *finalizerProc;
 88     void *clientData;
 89     //下一个文件事件
 90     struct aeFileEvent *next;
 91 } aeFileEvent;
 92 
 93 /* Time event structure */
 94 /**
 95  * redis自已定义的定时器事件
 96  * 其实现是一个链表,其中的每一个结点是一个Timer
 97  * when_sec与when_ms指定了定时器发生的时间
 98  * timeProc为响应函数
 99  * finalizerProc为删除定时器的析构函数
100  */
101 typedef struct aeTimeEvent {
102     //定时器的id
103     long long id; /* time event identifier. */
104     long when_sec; /* seconds */
105     long when_ms; /* milliseconds */
106     aeTimeProc *timeProc;
107     aeEventFinalizerProc *finalizerProc;
108     //定义了该定时器有的数据情况
109     void *clientData;
110     struct aeTimeEvent *next;
111 } aeTimeEvent;

常数定义部分

  /* Error codes */
  #define REDIS_OK                0
  #define REDIS_ERR               -1
  
  /* Static server configuration */
  #define REDIS_SERVERPORT        6379    /* TCP port */
  #define REDIS_MAXIDLETIME       (60*5)  /* default client timeout */
  #define REDIS_IOBUF_LEN         1024
  #define REDIS_LOADBUF_LEN       1024
  #define REDIS_STATIC_ARGS       4
  #define REDIS_DEFAULT_DBNUM     16
  #define REDIS_CONFIGLINE_MAX    1024
  #define REDIS_OBJFREELIST_MAX   1000000 /* Max number of objects to cache */
  #define REDIS_MAX_SYNC_TIME     60      /* Slave can't take more to sync */
  #define REDIS_EXPIRELOOKUPS_PER_CRON    100 /* try to expire 100 keys/second */
  #define REDIS_MAX_WRITE_PER_EVENT (1024*64)
  #define REDIS_REQUEST_MAX_SIZE  (1024*1024*256) /* max bytes in inline command */
  
  /* Hash table parameters */
  #define REDIS_HT_MINFILL        10      /* Minimal hash table fill 10% */
  
  /* Command flags */
  #define REDIS_CMD_BULK          1       /* Bulk write command */
  #define REDIS_CMD_INLINE        2       /* Inline command */
  /* REDIS_CMD_DENYOOM reserves a longer comment: all the commands marked with
     this flags will return an error when the 'maxmemory' option is set in the
     config file and the server is using more than maxmemory bytes of memory.
     In short this commands are denied on low memory conditions. */
  #define REDIS_CMD_DENYOOM       4
  
  /* Object types */
  #define REDIS_STRING 0
  #define REDIS_LIST 1
  #define REDIS_SET 2
  #define REDIS_HASH 3
  
  /* Object types only used for dumping to disk */
  #define REDIS_EXPIRETIME 253
  #define REDIS_SELECTDB 254
  #define REDIS_EOF 255
  
  
  /* Defines related to the dump file format. To store 32 bits lengths for short
   * keys requires a lot of space, so we check the most significant 2 bits of
   * the first byte to interpreter the length:
   *
   * 00|000000 => if the two MSB are 00 the len is the 6 bits of this byte
   * 01|000000 00000000 =>  01, the len is 14 byes, 6 bits + 8 bits of next byte
   * 10|000000 [32 bit integer] => if it's 01, a full 32 bit len will follow
   * 11|000000 this means: specially encoded object will follow. The six bits
   *           number specify the kind of object that follows.
   *           See the REDIS_RDB_ENC_* defines.
   *
   * Lenghts up to 63 are stored using a single byte, most DB keys, and may
   * values, will fit inside. */
  #define REDIS_RDB_6BITLEN 0
  #define REDIS_RDB_14BITLEN 1
  #define REDIS_RDB_32BITLEN 2
  #define REDIS_RDB_ENCVAL 3
  #define REDIS_RDB_LENERR UINT_MAX

  /* When a length of a string object stored on disk has the first two bits
   * set, the remaining two bits specify a special encoding for the object
   * accordingly to the following defines: */
  #define REDIS_RDB_ENC_INT8 0        /* 8 bit signed integer */
  #define REDIS_RDB_ENC_INT16 1       /* 16 bit signed integer */
  #define REDIS_RDB_ENC_INT32 2       /* 32 bit signed integer */
  #define REDIS_RDB_ENC_LZF 3         /* string compressed with FASTLZ */
  
  /* Client flags */
  #define REDIS_CLOSE 1       /* This client connection should be closed ASAP */
  #define REDIS_SLAVE 2       /* This client is a slave server */
  #define REDIS_MASTER 4      /* This client is a master server */
  #define REDIS_MONITOR 8      /* This client is a slave monitor, see MONITOR */
  
  /* Slave replication state - slave side */
  #define REDIS_REPL_NONE 0   /* No active replication */
  #define REDIS_REPL_CONNECT 1    /* Must connect to master */
  #define REDIS_REPL_CONNECTED 2  /* Connected to master */
  
  /* Slave replication state - from the point of view of master
   * Note that in SEND_BULK and ONLINE state the slave receives new updates
   * in its output queue. In the WAIT_BGSAVE state instead the server is waiting
   * to start the next background saving in order to send updates to it. */
  #define REDIS_REPL_WAIT_BGSAVE_START 3 /* master waits bgsave to start feeding it */
  #define REDIS_REPL_WAIT_BGSAVE_END 4 /* master waits bgsave to start bulk DB transmission */
  #define REDIS_REPL_SEND_BULK 5 /* master is sending the bulk DB */
  #define REDIS_REPL_ONLINE 6 /* bulk DB already transmitted, receive updates */
    
  /* List related stuff */
  #define REDIS_HEAD 0
  #define REDIS_TAIL 1
  
  /* Sort operations */
  #define REDIS_SORT_GET 0
  #define REDIS_SORT_DEL 1
  #define REDIS_SORT_INCR 2
  #define REDIS_SORT_DECR 3
  #define REDIS_SORT_ASC 4
  #define REDIS_SORT_DESC 5
  #define REDIS_SORTKEY_MAX 1024
  
  /* Log levels */
  #define REDIS_DEBUG 0
  #define REDIS_NOTICE 1
  #define REDIS_WARNING 2
  
  /* Anti-warning macro... */
  #define REDIS_NOTUSED(V) ((void) V)
  

发布了257 篇原创文章 · 获赞 223 · 访问量 32万+

猜你喜欢

转载自blog.csdn.net/csdn_kou/article/details/103048931