博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Redis源码分析(一)redis.c //redis-server.c
阅读量:2491 次
发布时间:2019-05-11

本文共 19472 字,大约阅读时间需要 64 分钟。

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 //定时器的id103 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)

转载地址:http://mzorb.baihongyu.com/

你可能感兴趣的文章
Docker(一)使用阿里云容器镜像服务
查看>>
Docker(三) 构建镜像
查看>>
Spring 全家桶注解一览
查看>>
JDK1.8-Stream API使用
查看>>
cant connect to local MySQL server through socket /tmp/mysql.sock (2)
查看>>
vue中的状态管理 vuex store
查看>>
Maven之阿里云镜像仓库配置
查看>>
Maven:mirror和repository 区别
查看>>
微服务网关 Spring Cloud Gateway
查看>>
SpringCloud Feign的使用方式(一)
查看>>
SpringCloud Feign的使用方式(二)
查看>>
关于Vue-cli+ElementUI项目 打包时排除Vue和ElementUI
查看>>
Vue 路由懒加载根据根路由合并chunk块
查看>>
vue中 不更新视图 四种解决方法
查看>>
MySQL 查看执行计划
查看>>
OpenGL ES 3.0(四)图元、VBO、VAO
查看>>
OpenGL ES 3.0(五)纹理
查看>>
OpenGL ES 3.0(八)实现带水印的相机预览功能
查看>>
OpenGL ES 3.0(九)实现美颜相机功能
查看>>
FFmpeg 的介绍与使用
查看>>