// 取出键的过期时间 mstime_t when = getExpire(db,key); mstime_t now;
// 没有过期时间 if (when < 0) return 0; /* No expire for this key */
/* Don't expire anything while loading. It will be done later. */ // 如果服务器正在进行载入,那么不进行任何过期检查 if (server.loading) return 0;
/* If we are in the context of a Lua script, we claim that time is * blocked to when the Lua script started. This way a key can expire * only the first time it is accessed and not in the middle of the * script execution, making propagation to slaves / AOF consistent. * See issue #1525 on Github for more information. */ now = server.lua_caller ? server.lua_time_start : mstime();
/* If we are running in the context of a slave, return ASAP: * the slave key expiration is controlled by the master that will * send us synthesized DEL operations for expired keys. * * Still we try to return the right information to the caller, * that is, 0 if we think the key should be still valid, 1 if * we think the key is expired at this time. */ // 当服务器运行在 replication 模式时 // 附属节点并不主动删除 key // 它只返回一个逻辑上正确的返回值 // 真正的删除操作要等待主节点发来删除命令时才执行 // 从而保证数据的同步 if (server.masterhost != NULL) return now > when;
// 运行到这里,表示键带有过期时间,并且服务器为主节点
/* Return when this key has not expired */ // 如果未过期,返回 0 if (now <= when) return 0;
/* The API provided to the rest of the Redis core is a simple function: * * notifyKeyspaceEvent(char *event, robj *key, int dbid); * * 'event' is a C string representing the event name. * * event 参数是一个字符串表示的事件名 * * 'key' is a Redis object representing the key name. * * key 参数是一个 Redis 对象表示的键名 * * 'dbid' is the database ID where the key lives. * * dbid 参数为键所在的数据库 */ void notifyKeyspaceEvent(int type, char *event, robj *key, int dbid) { sds chan; robj *chanobj, *eventobj; int len = -1; char buf[24];
/* If notifications for this class of events are off, return ASAP. */ // 如果服务器配置为不发送 type 类型的通知,那么直接返回 if (!(server.notify_keyspace_events & type)) return;
/* Fast pointers to often looked up command */ // 常用命令的快捷连接 struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand, *rpopCommand;
/* Fields used only for stats */
// 服务器启动时间 time_t stat_starttime; /* Server start time */
// 已处理命令的数量 long long stat_numcommands; /* Number of processed commands */
// 服务器接到的连接请求数量 long long stat_numconnections; /* Number of connections received */
// 已过期的键数量 long long stat_expiredkeys; /* Number of expired keys */
// 因为回收内存而被释放的过期键的数量 long long stat_evictedkeys; /* Number of evicted keys (maxmemory) */
// 成功查找键的次数 long long stat_keyspace_hits; /* Number of successful lookups of keys */
// 查找键失败的次数 long long stat_keyspace_misses; /* Number of failed lookups of keys */
// 已使用内存峰值 size_t stat_peak_memory; /* Max used memory record */
// 最后一次执行 fork() 时消耗的时间 long long stat_fork_time; /* Time needed to perform latest fork() */
// 服务器因为客户端数量过多而拒绝客户端连接的次数 long long stat_rejected_conn; /* Clients rejected because of maxclients */
// 执行 full sync 的次数 long long stat_sync_full; /* Number of full resyncs with slaves. */
// PSYNC 成功执行的次数 long long stat_sync_partial_ok; /* Number of accepted PSYNC requests. */
// PSYNC 执行失败的次数 long long stat_sync_partial_err;/* Number of unaccepted PSYNC requests. */
/* slowlog */
// 保存了所有慢查询日志的链表 list *slowlog; /* SLOWLOG list of commands */
// 下一条慢查询日志的 ID long long slowlog_entry_id; /* SLOWLOG current entry ID */
// 服务器配置 slowlog-log-slower-than 选项的值 long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */
// 服务器配置 slowlog-max-len 选项的值 unsigned long slowlog_max_len; /* SLOWLOG max number of items logged */ size_t resident_set_size; /* RSS sampled in serverCron(). */ /* The following two are used to track instantaneous "load" in terms * of operations per second. */ // 最后一次进行抽样的时间 long long ops_sec_last_sample_time; /* Timestamp of last sample (in ms) */ // 最后一次抽样时,服务器已执行命令的数量 long long ops_sec_last_sample_ops; /* numcommands in last sample */ // 抽样结果 long long ops_sec_samples[REDIS_OPS_SEC_SAMPLES]; // 数组索引,用于保存抽样结果,并在需要时回绕到 0 int ops_sec_idx;
/* Configuration */
// 日志可见性 int verbosity; /* Loglevel in redis.conf */
// 客户端最大空转时间 int maxidletime; /* Client timeout in seconds */
// 是否开启 SO_KEEPALIVE 选项 int tcpkeepalive; /* Set SO_KEEPALIVE if non-zero. */ int active_expire_enabled; /* Can be disabled for testing purposes. */ size_t client_max_querybuf_len; /* Limit for client query buffer length */ int dbnum; /* Total number of configured DBs */ int daemonize; /* True if running as a daemon */ // 客户端输出缓冲区大小限制 // 数组的元素有 REDIS_CLIENT_LIMIT_NUM_CLASSES 个 // 每个代表一类客户端:普通、从服务器、pubsub,诸如此类 clientBufferLimitsConfig client_obuf_limits[REDIS_CLIENT_LIMIT_NUM_CLASSES];
/* AOF persistence */
// AOF 状态(开启/关闭/可写) int aof_state; /* REDIS_AOF_(ON|OFF|WAIT_REWRITE) */
// 所使用的 fsync 策略(每个写入/每秒/从不) int aof_fsync; /* Kind of fsync() policy */ char *aof_filename; /* Name of the AOF file */ int aof_no_fsync_on_rewrite; /* Don't fsync if a rewrite is in prog. */ int aof_rewrite_perc; /* Rewrite AOF if % growth is > M and... */ off_t aof_rewrite_min_size; /* the AOF file is at least N bytes. */
// 最后一次执行 BGREWRITEAOF 时, AOF 文件的大小 off_t aof_rewrite_base_size; /* AOF size on latest startup or rewrite. */
// AOF 文件的当前字节大小 off_t aof_current_size; /* AOF current size. */ int aof_rewrite_scheduled; /* Rewrite once BGSAVE terminates. */
// 负责进行 AOF 重写的子进程 ID pid_t aof_child_pid; /* PID if rewriting process */
// AOF 重写缓存链表,链接着多个缓存块 list *aof_rewrite_buf_blocks; /* Hold changes during an AOF rewrite. */
// AOF 缓冲区 sds aof_buf; /* AOF buffer, written before entering the event loop */
// AOF 文件的描述符 int aof_fd; /* File descriptor of currently selected AOF file */
// AOF 的当前目标数据库 int aof_selected_db; /* Currently selected DB in AOF */
// 推迟 write 操作的时间 time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */
// 最后一直执行 fsync 的时间 time_t aof_last_fsync; /* UNIX time of last fsync() */ time_t aof_rewrite_time_last; /* Time used by last AOF rewrite run. */
// 指示是否需要每写入一定量的数据,就主动执行一次 fsync() int aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */ int aof_last_write_status; /* REDIS_OK or REDIS_ERR */ int aof_last_write_errno; /* Valid if aof_last_write_status is ERR */ /* RDB persistence */
// 自从上次 SAVE 执行以来,数据库被修改的次数 long long dirty; /* Changes to DB from the last save */
// BGSAVE 执行前的数据库被修改次数 long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */
// 负责执行 BGSAVE 的子进程的 ID // 没在执行 BGSAVE 时,设为 -1 pid_t rdb_child_pid; /* PID of RDB saving child */ struct saveparam *saveparams; /* Save points array for RDB */ int saveparamslen; /* Number of saving points */ char *rdb_filename; /* Name of RDB file */ int rdb_compression; /* Use compression in RDB? */ int rdb_checksum; /* Use RDB checksum? */
// 最后一次完成 SAVE 的时间 time_t lastsave; /* Unix time of last successful save */
// 最后一次尝试执行 BGSAVE 的时间 time_t lastbgsave_try; /* Unix time of last attempted bgsave */
// 最近一次 BGSAVE 执行耗费的时间 time_t rdb_save_time_last; /* Time used by last RDB save run. */
// 数据库最近一次开始执行 BGSAVE 的时间 time_t rdb_save_time_start; /* Current RDB save start time. */
// 最后一次执行 SAVE 的状态 int lastbgsave_status; /* REDIS_OK or REDIS_ERR */ int stop_writes_on_bgsave_err; /* Don't allow writes if can't BGSAVE */
/* Propagation of commands in AOF / replication */ redisOpArray also_propagate; /* Additional command to propagate. */
/* Logging */ char *logfile; /* Path of log file */ int syslog_enabled; /* Is syslog enabled? */ char *syslog_ident; /* Syslog ident */ int syslog_facility; /* Syslog facility */
/* Replication (master) */ int slaveseldb; /* Last SELECTed DB in replication output */ // 全局复制偏移量(一个累计值) long long master_repl_offset; /* Global replication offset */ // 主服务器发送 PING 的频率 int repl_ping_slave_period; /* Master pings the slave every N seconds */
// backlog 本身 char *repl_backlog; /* Replication backlog for partial syncs */ // backlog 的长度 long long repl_backlog_size; /* Backlog circular buffer size */ // backlog 中数据的长度 long long repl_backlog_histlen; /* Backlog actual data length */ // backlog 的当前索引 long long repl_backlog_idx; /* Backlog circular buffer current offset */ // backlog 中可以被还原的第一个字节的偏移量 long long repl_backlog_off; /* Replication offset of first byte in the backlog buffer. */ // backlog 的过期时间 time_t repl_backlog_time_limit; /* Time without slaves after the backlog gets released. */
// 距离上一次有从服务器的时间 time_t repl_no_slaves_since; /* We have no slaves since that time. Only valid if server.slaves len is 0. */
// 是否开启最小数量从服务器写入功能 int repl_min_slaves_to_write; /* Min number of slaves to write. */ // 定义最小数量从服务器的最大延迟值 int repl_min_slaves_max_lag; /* Max lag of <count> slaves to write. */ // 延迟良好的从服务器的数量 int repl_good_slaves_count; /* Number of slaves with lag <= max_lag. */
/* Replication (slave) */ // 主服务器的验证密码 char *masterauth; /* AUTH with this password with master */ // 主服务器的地址 char *masterhost; /* Hostname of master */ // 主服务器的端口 int masterport; /* Port of master */ // 超时时间 int repl_timeout; /* Timeout after N seconds of master idle */ // 主服务器所对应的客户端 redisClient *master; /* Client that is master for this slave */ // 被缓存的主服务器,PSYNC 时使用 redisClient *cached_master; /* Cached master to be reused for PSYNC. */ int repl_syncio_timeout; /* Timeout for synchronous I/O calls */ // 复制的状态(服务器是从服务器时使用) int repl_state; /* Replication status if the instance is a slave */ // RDB 文件的大小 off_t repl_transfer_size; /* Size of RDB to read from master during sync. */ // 已读 RDB 文件内容的字节数 off_t repl_transfer_read; /* Amount of RDB read from master during sync. */ // 最近一次执行 fsync 时的偏移量 // 用于 sync_file_range 函数 off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */ // 主服务器的套接字 int repl_transfer_s; /* Slave -> Master SYNC socket */ // 保存 RDB 文件的临时文件的描述符 int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */ // 保存 RDB 文件的临时文件名字 char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */ // 最近一次读入 RDB 内容的时间 time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */ int repl_serve_stale_data; /* Serve stale data when link is down? */ // 是否只读从服务器? int repl_slave_ro; /* Slave is read only? */ // 连接断开的时长 time_t repl_down_since; /* Unix time at which link with master went down */ // 是否要在 SYNC 之后关闭 NODELAY ? int repl_disable_tcp_nodelay; /* Disable TCP_NODELAY after SYNC? */ // 从服务器优先级 int slave_priority; /* Reported in INFO and used by Sentinel. */ // 本服务器(从服务器)当前主服务器的 RUN ID char repl_master_runid[REDIS_RUN_ID_SIZE+1]; /* Master run id for PSYNC. */ // 初始化偏移量 long long repl_master_initial_offset; /* Master PSYNC offset. */
/* Replication script cache. */ // 复制脚本缓存 // 字典 dict *repl_scriptcache_dict; /* SHA1 all slaves are aware of. */ // FIFO 队列 list *repl_scriptcache_fifo; /* First in, first out LRU eviction. */ // 缓存的大小 int repl_scriptcache_size; /* Max number of elements. */
/* Synchronous replication. */ list *clients_waiting_acks; /* Clients waiting in WAIT command. */ int get_ack_from_slaves; /* If true we send REPLCONF GETACK. */ /* Limits */ int maxclients; /* Max number of simultaneous clients */ unsigned long long maxmemory; /* Max number of memory bytes to use */ int maxmemory_policy; /* Policy for key eviction */ int maxmemory_samples; /* Pricision of random sampling */
/* Blocked clients */ unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */ list *unblocked_clients; /* list of clients to unblock before next loop */ list *ready_keys; /* List of readyList structures for BLPOP & co */
/* Sort parameters - qsort_r() is only available under BSD so we * have to take this state global, in order to pass it to sortCompare() */ int sort_desc; int sort_alpha; int sort_bypattern; int sort_store;
/* Zip structure config, see redis.conf for more information */ size_t hash_max_ziplist_entries; size_t hash_max_ziplist_value; size_t list_max_ziplist_entries; size_t list_max_ziplist_value; size_t set_max_intset_entries; size_t zset_max_ziplist_entries; size_t zset_max_ziplist_value; size_t hll_sparse_max_bytes; time_t unixtime; /* Unix time sampled every cron cycle. */ long long mstime; /* Like 'unixtime' but with milliseconds resolution. */
/* Pubsub */ // 字典,键为频道,值为链表 // 链表中保存了所有订阅某个频道的客户端 // 新客户端总是被添加到链表的表尾 dict *pubsub_channels; /* Map channels to list of subscribed clients */
// 这个链表记录了客户端订阅的所有模式的名字 list *pubsub_patterns; /* A list of pubsub_patterns */
int notify_keyspace_events; /* Events to propagate via Pub/Sub. This is an xor of REDIS_NOTIFY... flags. */
/* Cluster */
int cluster_enabled; /* Is cluster enabled? */ mstime_t cluster_node_timeout; /* Cluster node timeout. */ char *cluster_configfile; /* Cluster auto-generated config file name. */ struct clusterState *cluster; /* State of the cluster */
// Lua 环境 lua_State *lua; /* The Lua interpreter. We use just one for all clients */ // 复制执行 Lua 脚本中的 Redis 命令的伪客户端 redisClient *lua_client; /* The "fake client" to query Redis from Lua */
// 当前正在执行 EVAL 命令的客户端,如果没有就是 NULL redisClient *lua_caller; /* The client running EVAL right now, or NULL */
// 一个字典,值为 Lua 脚本,键为脚本的 SHA1 校验和 dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */ // Lua 脚本的执行时限 mstime_t lua_time_limit; /* Script timeout in milliseconds */ // 脚本开始执行的时间 mstime_t lua_time_start; /* Start time of script, milliseconds time */
// 脚本是否执行过写命令 int lua_write_dirty; /* True if a write command was called during the execution of the current script. */
// 脚本是否执行过带有随机性质的命令 int lua_random_dirty; /* True if a random command was called during the execution of the current script. */
// 脚本是否超时 int lua_timedout; /* True if we reached the time limit for script execution. */
// 是否要杀死脚本 int lua_kill; /* Kill the script if true. */
/* Assert & bug reporting */
char *assert_failed; char *assert_file; int assert_line; int bug_report_start; /* True if bug report header was already logged. */ int watchdog_period; /* Software watchdog period in ms. 0 = off */ };