• Redis源码研究--启动过程


    ---------------------6月23日---------------------------

    Redis启动入口即main函数在redis.c文件,伪代码如下:

     1 int main(int argc, char **argv) {
     2     initServerConfig();
     3     
     4     if (argc >= 2) {
     5          loadServerConfig(configfile,options);
     6     } else {
     7         redisLog(REDIS_WARNING, "Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/%s.conf", argv[0], server.sentinel_mode ? "sentinel" : "redis");
     8     }
     9     
    10     initServer();
    11     redisAsciiArt();
    12 
    13     if (!server.sentinel_mode) {
    14         /* Things not needed when running in Sentinel mode. */
    15         redisLog(REDIS_WARNING,"Server started, Redis version "  REDIS_VERSION);
    16         loadDataFromDisk();
    17       
    18         if (server.ipfd > 0)
    19             redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
    20        
    21     }
    22 
    23     aeSetBeforeSleepProc(server.el,beforeSleep);
    24     aeMain(server.el);
    25     aeDeleteEventLoop(server.el);
    26     return 0;
    27 }

     第2行,初始化默认的server 结构,简单看了下,有近200来个字段,记录了和服务器相关的所有数据

     第4行,如果启动方式为“redis-server my.conf”,程序会加载该配置文件

     第6行,否则的话,打印一个warning,控制台上显示的是#号

     第10行,初始化server,这个动真格的了,为一些变量分配了内存,进行了初始化。createSharedObjects对一些经常用到的如“ ”进行共享,让它们常驻内存

     第11行,用Ascii码把redis的图标画出来了

     第15行,Redis启动完成

     第16行,从磁盘上加载保存的数据库数据

    剩下的利用了ae事件库,还没看。

    ---------------6月24日---------------------

    今天只看半个小时,有点忙。

    redisServer这个数据结构里面有太多东西了,今天是看不完了,能啃一点是一点。先看redisObject

    1 typedef struct redisObject {
    2     unsigned type:4;
    3     unsigned notused:2;     /* Not used */
    4     unsigned encoding:4;
    5     unsigned lru:22;        /* lru time (relative to server.lruclock) */
    6     int refcount;
    7     void *ptr;
    8 } robj;

    用到了位段或者说位域,type占4位,可以表示16种type。我们只定义了五种数据类型

    /* Object types */
    #define REDIS_STRING 0
    #define REDIS_LIST 1
    #define REDIS_SET 2
    #define REDIS_ZSET 3
    #define REDIS_HASH 4

     encoding当然定义了编码方式

    /* Objects encoding. Some kind of objects like Strings and Hashes can be
     * internally represented in multiple ways. The 'encoding' field of the object
     * is set to one of this fields for this object. */
    #define REDIS_ENCODING_RAW 0     /* Raw representation */
    #define REDIS_ENCODING_INT 1     /* Encoded as integer */
    #define REDIS_ENCODING_HT 2      /* Encoded as hash table */
    #define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
    #define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
    #define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
    #define REDIS_ENCODING_INTSET 6  /* Encoded as intset */
    #define REDIS_ENCODING_SKIPLIST 7  /* Encoded as skiplist */

    下图展示了 redisObject 、Redis 所有数据类型、以及 Redis 所有编码方式(底层实现)三者之间的关系 ,

    图片转自之前提到过的《Redis设计与实现》,以后就不提了。

    refCount,引用计数,让人联想到java虚拟机垃圾回收,没错,就是这么理解的。当有对象用到该robj时,refCount加1,初始时为1,当refCount为0时,可以销毁。

    ---------------------6月25日------------------------------

    今天看了Redis的数据库结构redisDB,也不是很复杂啊,虽然我不懂。

    先上代码

    1 typedef struct redisDb {
    2     dict *dict;                 /* The keyspace for this DB */
    3     dict *expires;              /* Timeout of keys with a timeout set */
    4     dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */
    5     dict *ready_keys;           /* Blocked keys that received a PUSH */
    6     dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */
    7     int id;
    8 } redisDb;

    dict存键值对,expires键的过期时间,id数据库号,

    #define REDIS_DEFAULT_DBNUM     16

    select 0,使用0号数据库,redisServer.db[0]。

    -----------------------6月26日----------------------------

    看了数据库的键空间操作,增、查、删、改,以及过期操作。

    过期键删除有3种策略,

    1. 定时删除:在设置键的过期时间时,创建一个定时事件,当过期时间到达时,由事件处理器自动执行键的删除操作。
    2. 惰性删除:放任键过期不管,但是在每次从 dict 字典中取出键值时,要检查键是否过期,如果过期的话,就删除它,并返回空;如果没过期,就返回键值。
    3. 定期删除:每隔一段时间,对 expires 字典进行检查,删除里面的过期键。

    -------------------------6月27日---------------------------

    Redis提供了两种持久化方法,RDB和AOF

     ------------------------6月28日----------------------------

    1 typedef struct zskiplist {
    2     struct zskiplistNode *header, *tail;
    3     unsigned long length;
    4     int level;
    5 } zskiplist;

    redis.h里还有个zskiplist,跳表,网易公开课里有专门介绍跳表的。

  • 相关阅读:
    【项目】 技术选型 平台和语言
    WCF 常见逻辑和代码 1.错误处理和配置
    一个挺有意思的Javascript小问题
    【设计原则和建议】 方法返回值
    一次HTTP请求中的缓存
    【设计原则和建议】 方法
    【设计原则和建议】 字段
    Express全系列教程之(一):Express的安装 和第一个程序
    js switch语句祥解[范围判断]
    修改notepad++ zencodeing 插件的配置路径
  • 原文地址:https://www.cnblogs.com/feiyunruyue/p/3151010.html
Copyright © 2020-2023  润新知