1.redis客戶端與服務(wù)端
1.1 客戶端
1.1.1 客戶端種類
redis 客戶端主要分為三種,普通客戶端、發(fā)布訂閱客戶端、slave 客戶端。
普通客戶端我們不用多說,也是我們用的最多的客戶端。
redis 客戶端可以訂閱任意數(shù)量的頻道,如果你訂閱了某個(gè)服務(wù)器頻道,那么你的客戶端就也是一個(gè)發(fā)布訂閱客戶端,當(dāng)頻道中有新消息,服務(wù)器會向你推送。
當(dāng) redis 集群中部署了主從節(jié)點(diǎn)的時(shí)候,所有的從節(jié)點(diǎn)服務(wù)器又稱為 slave 客戶端,他們會向 master 定期拉取最新數(shù)據(jù)。
1.1.2 客戶端參數(shù)說明
直接來看redis中是如何定義client的
typedef struct client {
uint64_t id; /* Client incremental unique ID. */
connection *conn;
int resp; /* RESP protocol version. Can be 2 or 3. */
redisDb *db; /* Pointer to currently SELECTed DB. */
robj *name; /* As set by CLIENT SETNAME. */
sds querybuf; /* Buffer we use to accumulate client queries. */
size_t qb_pos; /* The position we have read in querybuf. */
sds pending_querybuf; /* If this client is flagged as master, this buffer
represents the yet not applied portion of the
replication stream that we are receiving from
the master. */
size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size. */
int argc; /* Num of arguments of current command. */
robj **argv; /* Arguments of current command. */
struct redisCommand *cmd, *lastcmd; /* Last command executed. */
user *user; /* User associated with this connection. If the
user is set to NULL the connection can do
anything (admin). */
int reqtype; /* Request protocol type: PROTO_REQ_* */
int multibulklen; /* Number of multi bulk arguments left to read. */
long bulklen; /* Length of bulk argument in multi bulk request. */
list *reply; /* List of reply objects to send to the client. */
unsigned long long reply_bytes; /* Tot bytes of objects in reply list. */
size_t sentlen; /* Amount of bytes already sent in the current
buffer or object being sent. */
time_t ctime; /* Client creation time. */
time_t lastinteraction; /* Time of the last interaction, used for timeout */
time_t obuf_soft_limit_reached_time;
uint64_t flags; /* Client flags: CLIENT_* macros. */
int authenticated; /* Needed when the default user requires auth. */
int replstate; /* Replication state if this is a slave. */
int repl_put_online_on_ack; /* Install slave write handler on first ACK. */
int repldbfd; /* Replication DB file descriptor. */
off_t repldboff; /* Replication DB file offset. */
off_t repldbsize; /* Replication DB file size. */
sds replpreamble; /* Replication DB preamble. */
long long read_reploff; /* Read replication offset if this is a master. */
long long reploff; /* Applied replication offset if this is a master. */
long long repl_ack_off; /* Replication ack offset, if this is a slave. */
long long repl_ack_time;/* Replication ack time, if this is a slave. */
long long psync_initial_offset; /* FULLRESYNC reply offset other slaves
copying this slave output buffer
should use. */
char replid[CONFIG_RUN_ID_SIZE+1]; /* Master replication ID (if master). */
int slave_listening_port; /* As configured with: SLAVECONF listening-port */
char slave_ip[NET_IP_STR_LEN]; /* Optionally given by REPLCONF ip-address */
int slave_capa; /* Slave capabilities: SLAVE_CAPA_* bitwise OR. */
multiState mstate; /* MULTI/EXEC state */
int btype; /* Type of blocking op if CLIENT_BLOCKED. */
blockingState bpop; /* blocking state */
long long woff; /* Last write global replication offset. */
list *watched_keys; /* Keys WATCHED for MULTI/EXEC CAS */
dict *pubsub_channels; /* channels a client is interested in (SUBSCRIBE) */
list *pubsub_patterns; /* patterns a client is interested in (SUBSCRIBE) */
sds peerid; /* Cached peer ID. */
listNode *client_list_node; /* list node in client list */
RedisModuleUserChangedFunc auth_callback; /* Module callback to execute
* when the authenticated user
* changes. */
void *auth_callback_privdata; /* Private data that is passed when the auth
* changed callback is executed. Opaque for
* Redis Core. */
void *auth_module; /* The module that owns the callback, which is used
* to disconnect the client if the module is
* unloaded for cleanup. Opaque for Redis Core.*/
/* If this client is in tracking mode and this field is non zero,
* invalidation messages for keys fetched by this client will be send to
* the specified client ID. */
uint64_t client_tracking_redirection;
rax *client_tracking_prefixes; /* A dictionary of prefixes we are already
subscribed to in BCAST mode, in the
context of client side caching. */
/* In clientsCronTrackClientsMemUsage() we track the memory usage of
* each client and add it to the sum of all the clients of a given type,
* however we need to remember what was the old contribution of each
* client, and in which categoty the client was, in order to remove it
* before adding it the new value. */
uint64_t client_cron_last_memory_usage;
int client_cron_last_memory_type;
/* Response buffer */
int bufpos;
char buf[PROTO_REPLY_CHUNK_BYTES];
} client;
authenticated:身份驗(yàn)證,為0時(shí)只能接受AUTH命令,為1時(shí)則正常使用
從終端執(zhí)行“client list”獲取到的值
127.0.0.1:6379> client list
id=308 addr=127.0.0.1:51338 fd=7 name= age=4752555 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
id:自增唯一id
addr:客戶端地址 + 端口
fd:套接字描述符(偽客戶端為-1,其他為正整數(shù))
name:客戶端的名字,默認(rèn)是空,可以用 “client setname“ 為客戶端命名
age:生命周期,以秒為單位
idle:空閑時(shí)長,以秒為單位
flags:客戶端的標(biāo)志值
db:指向客戶端正在使用的數(shù)據(jù)庫
sub:已訂閱頻道的數(shù)量
psub:已訂閱模式的數(shù)量
multi:在事務(wù)中被執(zhí)行的命令數(shù)量
qbuf:輸入緩沖區(qū)--已使用的緩沖區(qū)
qbuf-free:輸入緩沖區(qū)--空閑的緩沖區(qū)
obl:輸出緩沖區(qū)--固定緩沖區(qū)長度
oll:輸出緩沖區(qū)--動態(tài)緩沖區(qū)長度
omem:固定緩沖區(qū)和動態(tài)緩沖區(qū)總共占用了多少字節(jié)
events:文件描述符時(shí)間
cmd:最近一次執(zhí)行的命令
客戶端 flag 可以由以下部分組成:
- O:客戶端是 MONITOR 模式下的附屬節(jié)點(diǎn)(slave)
- S:客戶端是一般模式下(normal)的附屬節(jié)點(diǎn)
- M:客戶端是主節(jié)點(diǎn)(master)
- x:客戶端正在執(zhí)行事務(wù)
- b:客戶端正在等待阻塞事件
- i:客戶端正在等待 VM I/O 操作(已廢棄)
- d:一個(gè)受監(jiān)視(watched)的鍵已被修改, EXEC 命令將失敗
- c:在將回復(fù)完整地寫出之后,關(guān)閉鏈接
- u:客戶端未被阻塞(unblocked)
- A:盡可能快地關(guān)閉連接
- N:未設(shè)置任何 flag
文件描述符事件可以是:
- r:客戶端套接字(在事件 loop 中)是可讀的(readable)
- w:客戶端套接字(在事件 loop 中)是可寫的(writeable)
1.2 服務(wù)端
1.2.1 Redis服務(wù)啟動流程
概要
? Redis通過初始化全局服務(wù)器狀態(tài)變量并讀取可選的配置文件以覆蓋所有默認(rèn)值來啟動。它建立了一個(gè)全局命令表,該表將命令名稱與實(shí)現(xiàn)該命令的實(shí)際功能連接起來。它使用最佳可用的基礎(chǔ)系統(tǒng)庫創(chuàng)建事件循環(huán),以進(jìn)行事件/就緒通知,并為有新客戶端套接字連接接受時(shí)注冊處理程序函數(shù)。它還注冊了一個(gè)定期的(即基于時(shí)間的)事件處理程序來處理cron密鑰到期之類的類似任務(wù),需要在常規(guī)客戶端處理路徑之外解決。一旦客戶端已連接,便在事件循環(huán)中注冊了一個(gè)功能,以便在客戶端具有要讀取的數(shù)據(jù)(即查詢命令)時(shí)得到通知。解析客戶端的查詢,并調(diào)用命令處理程序以執(zhí)行命令并將響應(yīng)寫回到客戶端(事件通知循環(huán)也處理向客戶端的數(shù)據(jù)寫入)??蛻舳藢ο蟊恢刂茫?wù)器準(zhǔn)備處理更多查詢。
開始全局服務(wù)器狀態(tài)初始化
? 首先會調(diào)用initServerConfig()初始化一個(gè)變量server,其類型為struct redisServer,用作全局服務(wù)器狀態(tài)。
源碼如下:
struct redisServer {
/* General */
pid_t pid; /* Main process pid. */
char *configfile; /* Absolute config file path, or NULL */
char *executable; /* Absolute executable file path. */
char **exec_argv; /* Executable argv vector (copy). */
int dynamic_hz; /* Change hz value depending on # of clients. */
int config_hz; /* Configured HZ value. May be different than
the actual 'hz' field value if dynamic-hz
is enabled. */
int hz; /* serverCron() calls frequency in hertz */
redisDb *db;
dict *commands; /* Command table */
dict *orig_commands; /* Command table before command renaming. */
aeEventLoop *el;
_Atomic unsigned int lruclock; /* Clock for LRU eviction */
int shutdown_asap; /* SHUTDOWN needed ASAP */
int activerehashing; /* Incremental rehash in serverCron() */
int active_defrag_running; /* Active defragmentation running (holds current scan aggressiveness) */
char *pidfile; /* PID file path */
int arch_bits; /* 32 or 64 depending on sizeof(long) */
int cronloops; /* Number of times the cron function run */
char runid[CONFIG_RUN_ID_SIZE+1]; /* ID always different at every exec. */
int sentinel_mode; /* True if this instance is a Sentinel. */
size_t initial_memory_usage; /* Bytes used after initialization. */
int always_show_logo; /* Show logo even for non-stdout logging. */
/* Modules */
dict *moduleapi; /* Exported core APIs dictionary for modules. */
dict *sharedapi; /* Like moduleapi but containing the APIs that
modules share with each other. */
list *loadmodule_queue; /* List of modules to load at startup. */
int module_blocked_pipe[2]; /* Pipe used to awake the event loop if a
client blocked on a module command needs
to be processed. */
pid_t module_child_pid; /* PID of module child */
/* Networking */
int port; /* TCP listening port */
int tls_port; /* TLS listening port */
int tcp_backlog; /* TCP listen() backlog */
char *bindaddr[CONFIG_BINDADDR_MAX]; /* Addresses we should bind to */
int bindaddr_count; /* Number of addresses in server.bindaddr[] */
char *unixsocket; /* UNIX socket path */
mode_t unixsocketperm; /* UNIX socket permission */
int ipfd[CONFIG_BINDADDR_MAX]; /* TCP socket file descriptors */
int ipfd_count; /* Used slots in ipfd[] */
int tlsfd[CONFIG_BINDADDR_MAX]; /* TLS socket file descriptors */
int tlsfd_count; /* Used slots in tlsfd[] */
int sofd; /* Unix socket file descriptor */
int cfd[CONFIG_BINDADDR_MAX];/* Cluster bus listening socket */
int cfd_count; /* Used slots in cfd[] */
list *clients; /* List of active clients */
list *clients_to_close; /* Clients to close asynchronously */
list *clients_pending_write; /* There is to write or install handler. */
list *clients_pending_read; /* Client has pending read socket buffers. */
list *slaves, *monitors; /* List of slaves and MONITORs */
client *current_client; /* Current client executing the command. */
rax *clients_timeout_table; /* Radix tree for blocked clients timeouts. */
long fixed_time_expire; /* If > 0, expire keys against server.mstime. */
rax *clients_index; /* Active clients dictionary by client ID. */
int clients_paused; /* True if clients are currently paused */
mstime_t clients_pause_end_time; /* Time when we undo clients_paused */
char neterr[ANET_ERR_LEN]; /* Error buffer for anet.c */
dict *migrate_cached_sockets;/* MIGRATE cached sockets */
_Atomic uint64_t next_client_id; /* Next client unique ID. Incremental. */
int protected_mode; /* Don't accept external connections. */
int gopher_enabled; /* If true the server will reply to gopher
queries. Will still serve RESP2 queries. */
int io_threads_num; /* Number of IO threads to use. */
int io_threads_do_reads; /* Read and parse from IO threads? */
int io_threads_active; /* Is IO threads currently active? */
long long events_processed_while_blocked; /* processEventsWhileBlocked() */
/* RDB / AOF loading information */
int loading; /* We are loading data from disk if true */
off_t loading_total_bytes;
off_t loading_loaded_bytes;
time_t loading_start_time;
off_t loading_process_events_interval_bytes;
/* Fast pointers to often looked up command */
struct redisCommand *delCommand, *multiCommand, *lpushCommand,
*lpopCommand, *rpopCommand, *zpopminCommand,
*zpopmaxCommand, *sremCommand, *execCommand,
*expireCommand, *pexpireCommand, *xclaimCommand,
*xgroupCommand, *rpoplpushCommand;
/* 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 */
double stat_expired_stale_perc; /* Percentage of keys probably expired */
long long stat_expired_time_cap_reached_count; /* Early expire cylce stops.*/
long long stat_expire_cycle_time_used; /* Cumulative microseconds used. */
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 */
long long stat_active_defrag_hits; /* number of allocations moved */
long long stat_active_defrag_misses; /* number of allocations scanned but not moved */
long long stat_active_defrag_key_hits; /* number of keys with moved allocations */
long long stat_active_defrag_key_misses;/* number of keys scanned and not moved */
long long stat_active_defrag_scanned; /* number of dictEntries scanned */
size_t stat_peak_memory; /* Max used memory record */
long long stat_fork_time; /* Time needed to perform latest fork() */
double stat_fork_rate; /* Fork rate in GB/sec. */
long long stat_rejected_conn; /* Clients rejected because of maxclients */
long long stat_sync_full; /* Number of full resyncs with slaves. */
long long stat_sync_partial_ok; /* Number of accepted PSYNC requests. */
long long stat_sync_partial_err;/* Number of unaccepted PSYNC requests. */
list *slowlog; /* SLOWLOG list of commands */
long long slowlog_entry_id; /* SLOWLOG current entry ID */
long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */
unsigned long slowlog_max_len; /* SLOWLOG max number of items logged */
struct malloc_stats cron_malloc_stats; /* sampled in serverCron(). */
_Atomic long long stat_net_input_bytes; /* Bytes read from network. */
_Atomic long long stat_net_output_bytes; /* Bytes written to network. */
size_t stat_rdb_cow_bytes; /* Copy on write bytes during RDB saving. */
size_t stat_aof_cow_bytes; /* Copy on write bytes during AOF rewrite. */
size_t stat_module_cow_bytes; /* Copy on write bytes during module fork. */
uint64_t stat_clients_type_memory[CLIENT_TYPE_COUNT];/* Mem usage by type */
long long stat_unexpected_error_replies; /* Number of unexpected (aof-loading, replica to master, etc.) error replies */
long long stat_io_reads_processed; /* Number of read events processed by IO / Main threads */
long long stat_io_writes_processed; /* Number of write events processed by IO / Main threads */
_Atomic long long stat_total_reads_processed; /* Total number of read events processed */
_Atomic long long stat_total_writes_processed; /* Total number of write events processed */
/* The following two are used to track instantaneous metrics, like
* number of operations per second, network traffic. */
struct {
long long last_sample_time; /* Timestamp of last sample in ms */
long long last_sample_count;/* Count in last sample */
long long samples[STATS_METRIC_SAMPLES];
int idx;
} inst_metric[STATS_METRIC_COUNT];
/* Configuration */
int verbosity; /* Loglevel in redis.conf */
int maxidletime; /* Client timeout in seconds */
int tcpkeepalive; /* Set SO_KEEPALIVE if non-zero. */
int active_expire_enabled; /* Can be disabled for testing purposes. */
int active_expire_effort; /* From 1 (default) to 10, active effort. */
int active_defrag_enabled;
int jemalloc_bg_thread; /* Enable jemalloc background thread */
size_t active_defrag_ignore_bytes; /* minimum amount of fragmentation waste to start active defrag */
int active_defrag_threshold_lower; /* minimum percentage of fragmentation to start active defrag */
int active_defrag_threshold_upper; /* maximum percentage of fragmentation at which we use maximum effort */
int active_defrag_cycle_min; /* minimal effort for defrag in CPU percentage */
int active_defrag_cycle_max; /* maximal effort for defrag in CPU percentage */
unsigned long active_defrag_max_scan_fields; /* maximum number of fields of set/hash/zset/list to process from within the main dict scan */
_Atomic size_t client_max_querybuf_len; /* Limit for client query buffer length */
int dbnum; /* Total number of configured DBs */
int supervised; /* 1 if supervised, 0 otherwise. */
int supervised_mode; /* See SUPERVISED_* */
int daemonize; /* True if running as a daemon */
clientBufferLimitsConfig client_obuf_limits[CLIENT_TYPE_OBUF_COUNT];
/* AOF persistence */
int aof_enabled; /* AOF configuration */
int aof_state; /* AOF_(ON|OFF|WAIT_REWRITE) */
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. */
off_t aof_rewrite_base_size; /* AOF size on latest startup or rewrite. */
off_t aof_current_size; /* AOF current size. */
off_t aof_fsync_offset; /* AOF offset which is already synced to disk. */
int aof_flush_sleep; /* Micros to sleep before flush. (used by tests) */
int aof_rewrite_scheduled; /* Rewrite once BGSAVE terminates. */
pid_t aof_child_pid; /* PID if rewriting process */
list *aof_rewrite_buf_blocks; /* Hold changes during an AOF rewrite. */
sds aof_buf; /* AOF buffer, written before entering the event loop */
int aof_fd; /* File descriptor of currently selected AOF file */
int aof_selected_db; /* Currently selected DB in AOF */
time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */
time_t aof_last_fsync; /* UNIX time of last fsync() */
time_t aof_rewrite_time_last; /* Time used by last AOF rewrite run. */
time_t aof_rewrite_time_start; /* Current AOF rewrite start time. */
int aof_lastbgrewrite_status; /* C_OK or C_ERR */
unsigned long aof_delayed_fsync; /* delayed AOF fsync() counter */
int aof_rewrite_incremental_fsync;/* fsync incrementally while aof rewriting? */
int rdb_save_incremental_fsync; /* fsync incrementally while rdb saving? */
int aof_last_write_status; /* C_OK or C_ERR */
int aof_last_write_errno; /* Valid if aof_last_write_status is ERR */
int aof_load_truncated; /* Don't stop on unexpected AOF EOF. */
int aof_use_rdb_preamble; /* Use RDB preamble on AOF rewrites. */
/* AOF pipes used to communicate between parent and child during rewrite. */
int aof_pipe_write_data_to_child;
int aof_pipe_read_data_from_parent;
int aof_pipe_write_ack_to_parent;
int aof_pipe_read_ack_from_child;
int aof_pipe_write_ack_to_child;
int aof_pipe_read_ack_from_parent;
int aof_stop_sending_diff; /* If true stop sending accumulated diffs
to child process. */
sds aof_child_diff; /* AOF diff accumulator child side. */
/* RDB persistence */
long long dirty; /* Changes to DB from the last save */
long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */
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? */
int rdb_del_sync_files; /* Remove RDB files used only for SYNC if
the instance does not use persistence. */
time_t lastsave; /* Unix time of last successful save */
time_t lastbgsave_try; /* Unix time of last attempted bgsave */
time_t rdb_save_time_last; /* Time used by last RDB save run. */
time_t rdb_save_time_start; /* Current RDB save start time. */
int rdb_bgsave_scheduled; /* BGSAVE when possible if true. */
int rdb_child_type; /* Type of save by active child. */
int lastbgsave_status; /* C_OK or C_ERR */
int stop_writes_on_bgsave_err; /* Don't allow writes if can't BGSAVE */
int rdb_pipe_write; /* RDB pipes used to transfer the rdb */
int rdb_pipe_read; /* data to the parent process in diskless repl. */
connection **rdb_pipe_conns; /* Connections which are currently the */
int rdb_pipe_numconns; /* target of diskless rdb fork child. */
int rdb_pipe_numconns_writing; /* Number of rdb conns with pending writes. */
char *rdb_pipe_buff; /* In diskless replication, this buffer holds data */
int rdb_pipe_bufflen; /* that was read from the the rdb pipe. */
int rdb_key_save_delay; /* Delay in microseconds between keys while
* writing the RDB. (for testings). negative
* value means fractions of microsecons (on average). */
int key_load_delay; /* Delay in microseconds between keys while
* loading aof or rdb. (for testings). negative
* value means fractions of microsecons (on average). */
/* Pipe and data structures for child -> parent info sharing. */
int child_info_pipe[2]; /* Pipe used to write the child_info_data. */
struct {
int process_type; /* AOF or RDB child? */
size_t cow_size; /* Copy on write size. */
unsigned long long magic; /* Magic value to make sure data is valid. */
} child_info_data;
/* 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 */
int crashlog_enabled; /* Enable signal handler for crashlog.
* disable for clean core dumps. */
int memcheck_enabled; /* Enable memory check on crash. */
int use_exit_on_panic; /* Use exit() on panic and assert rather than
* abort(). useful for Valgrind. */
/* Replication (master) */
char replid[CONFIG_RUN_ID_SIZE+1]; /* My current replication ID. */
char replid2[CONFIG_RUN_ID_SIZE+1]; /* replid inherited from master*/
long long master_repl_offset; /* My current replication offset */
long long second_replid_offset; /* Accept offsets up to this for replid2. */
int slaveseldb; /* Last SELECTed DB in replication output */
int repl_ping_slave_period; /* Master pings the slave every N seconds */
char *repl_backlog; /* Replication backlog for partial syncs */
long long repl_backlog_size; /* Backlog circular buffer size */
long long repl_backlog_histlen; /* Backlog actual data length */
long long repl_backlog_idx; /* Backlog circular buffer current offset,
that is the next byte will'll write to.*/
long long repl_backlog_off; /* Replication "master offset" of first
byte in the replication backlog buffer.*/
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. */
int repl_diskless_sync; /* Master send RDB to slaves sockets directly. */
int repl_diskless_load; /* Slave parse RDB directly from the socket.
* see REPL_DISKLESS_LOAD_* enum */
int repl_diskless_sync_delay; /* Delay to start a diskless repl BGSAVE. */
/* Replication (slave) */
char *masteruser; /* AUTH with this user and masterauth with master */
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 */
client *master; /* Client that is master for this slave */
client *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 */
off_t repl_transfer_size; /* Size of RDB to read from master during sync. */
off_t repl_transfer_read; /* Amount of RDB read from master during sync. */
off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */
connection *repl_transfer_s; /* Slave -> Master SYNC connection */
int repl_transfer_fd; /* Slave -> Master SYNC temp file descriptor */
char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */
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? */
int repl_slave_ignore_maxmemory; /* If true slaves do not evict. */
time_t repl_down_since; /* Unix time at which link with master went down */
int repl_disable_tcp_nodelay; /* Disable TCP_NODELAY after SYNC? */
int slave_priority; /* Reported in INFO and used by Sentinel. */
int slave_announce_port; /* Give the master this listening port. */
char *slave_announce_ip; /* Give the master this ip address. */
/* The following two fields is where we store master PSYNC replid/offset
* while the PSYNC is in progress. At the end we'll copy the fields into
* the server->master client structure. */
char master_replid[CONFIG_RUN_ID_SIZE+1]; /* Master PSYNC runid. */
long long master_initial_offset; /* Master PSYNC offset. */
int repl_slave_lazy_flush; /* Lazy FLUSHALL before loading DB? */
/* Replication script cache. */
dict *repl_scriptcache_dict; /* SHA1 all slaves are aware of. */
list *repl_scriptcache_fifo; /* First in, first out LRU eviction. */
unsigned 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 */
unsigned 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 */
int lfu_log_factor; /* LFU logarithmic counter factor. */
int lfu_decay_time; /* LFU counter decay factor. */
long long proto_max_bulk_len; /* Protocol bulk length maximum size. */
int oom_score_adj_base; /* Base oom_score_adj value, as observed on startup */
int oom_score_adj_values[CONFIG_OOM_COUNT]; /* Linux oom_score_adj configuration */
int oom_score_adj; /* If true, oom_score_adj is managed */
/* Blocked clients */
unsigned int blocked_clients; /* # of clients executing a blocking cmd.*/
unsigned int blocked_clients_by_type[BLOCKED_NUM];
list *unblocked_clients; /* list of clients to unblock before next loop */
list *ready_keys; /* List of readyList structures for BLPOP & co */
/* Client side caching. */
unsigned int tracking_clients; /* # of clients with tracking enabled.*/
size_t tracking_table_max_keys; /* Max number of keys in tracking table. */
/* 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 set_max_intset_entries;
size_t zset_max_ziplist_entries;
size_t zset_max_ziplist_value;
size_t hll_sparse_max_bytes;
size_t stream_node_max_bytes;
long long stream_node_max_entries;
/* List parameters */
int list_max_ziplist_size;
int list_compress_depth;
/* time cache */
_Atomic time_t unixtime; /* Unix time sampled every cron cycle. */
time_t timezone; /* Cached timezone. As set by tzset(). */
int daylight_active; /* Currently in daylight saving time. */
mstime_t mstime; /* 'unixtime' in milliseconds. */
ustime_t ustime; /* 'unixtime' in microseconds. */
long long blocked_last_cron; /* Indicate the mstime of the last time we did cron jobs from a blocking operation */
/* Pubsub */
dict *pubsub_channels; /* Map channels to list of subscribed clients */
list *pubsub_patterns; /* A list of pubsub_patterns */
dict *pubsub_patterns_dict; /* A dict of pubsub_patterns */
int notify_keyspace_events; /* Events to propagate via Pub/Sub. This is an
xor of 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 */
int cluster_migration_barrier; /* Cluster replicas migration barrier. */
int cluster_slave_validity_factor; /* Slave max data age for failover. */
int cluster_require_full_coverage; /* If true, put the cluster down if
there is at least an uncovered slot.*/
int cluster_slave_no_failover; /* Prevent slave from starting a failover
if the master is in failure state. */
char *cluster_announce_ip; /* IP address to announce on cluster bus. */
int cluster_announce_port; /* base port to announce on cluster bus. */
int cluster_announce_bus_port; /* bus port to announce on cluster bus. */
int cluster_module_flags; /* Set of flags that Redis modules are able
to set in order to suppress certain
native Redis Cluster features. Check the
REDISMODULE_CLUSTER_FLAG_*. */
int cluster_allow_reads_when_down; /* Are reads allowed when the cluster
is down? */
int cluster_config_file_lock_fd; /* cluster config fd, will be flock */
/* Scripting */
lua_State *lua; /* The Lua interpreter. We use just one for all clients */
client *lua_client; /* The "fake client" to query Redis from Lua */
client *lua_caller; /* The client running EVAL right now, or NULL */
char* lua_cur_script; /* SHA1 of the script currently running, or NULL */
dict *lua_scripts; /* A dictionary of SHA1 -> Lua scripts */
unsigned long long lua_scripts_mem; /* Cached scripts' memory + oh */
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_replicate_commands; /* True if we are doing single commands repl. */
int lua_multi_emitted;/* True if we already proagated MULTI. */
int lua_repl; /* Script replication flags for redis.set_repl(). */
int lua_timedout; /* True if we reached the time limit for script
execution. */
int lua_kill; /* Kill the script if true. */
int lua_always_replicate_commands; /* Default replication type. */
int lua_oom; /* OOM detected when script start? */
/* Lazy free */
int lazyfree_lazy_eviction;
int lazyfree_lazy_expire;
int lazyfree_lazy_server_del;
int lazyfree_lazy_user_del;
/* Latency monitor */
long long latency_monitor_threshold;
dict *latency_events;
/* ACLs */
char *acl_filename; /* ACL Users file. NULL if not configured. */
unsigned long acllog_max_len; /* Maximum length of the ACL LOG list. */
sds requirepass; /* Remember the cleartext password set with the
old "requirepass" directive for backward
compatibility with Redis <= 5. */
/* Assert & bug reporting */
int watchdog_period; /* Software watchdog period in ms. 0 = off */
/* System hardware info */
size_t system_memory_size; /* Total memory in system as reported by OS */
/* TLS Configuration */
int tls_cluster;
int tls_replication;
int tls_auth_clients;
redisTLSContextConfig tls_ctx_config;
/* cpu affinity */
char *server_cpulist; /* cpu affinity list of redis server main/io thread. */
char *bio_cpulist; /* cpu affinity list of bio thread. */
char *aof_rewrite_cpulist; /* cpu affinity list of aof rewrite process. */
char *bgsave_cpulist; /* cpu affinity list of bgsave process. */
};
README.MD中有對類型進(jìn)行簡單解釋:
All the server configuration and in general all the shared state is
defined in a global structure called `server`, of type `struct redisServer`.
A few important fields in this structure are:
* `server.db` is an array of Redis databases, where data is stored.
* `server.commands` is the command table.
* `server.clients` is a linked list of clients connected to the server.
* `server.master` is a special client, the master, if the instance is a replica.
There are tons of other fields. Most fields are commented directly inside
the structure definition.
設(shè)置命令表
? 接下來要做的是對Redis命令表進(jìn)行排序。它們在redisCommandTable數(shù)組的全局變量中定義struct redisCommand。
? 只讀表按源代碼排序,以便按類別將命令分組,例如字符串命令,列表命令,設(shè)置命令等,以使程序員更容易掃描表中的類似命令。排序后的命令表由全局變量指向,用于通過 commandTable標(biāo)準(zhǔn)二進(jìn)制搜索(lookupCommand(),返回指向a的指針redisCommand)查找Redis命令。
加載配置文件
? 1.2.1.1 中會全局初始化一份配置,而這個(gè)動作是用Redis.conf文件中用戶配置的值覆蓋之前初始化出來的配置。Redis將加載配置文件并調(diào)用initServerConfig()覆蓋已經(jīng)設(shè)置的任何默認(rèn)值loadServerConfig()。此函數(shù)非常簡單,它遍歷配置文件中的每一行,并將與指令名稱匹配的值轉(zhuǎn)換為server結(jié)構(gòu)中匹配成員的適當(dāng)類型 。此時(shí),Redis將被守護(hù)并從控制終端分離(如果已配置)。
initServer()
? initServer()完成初始化由server開始的結(jié)構(gòu)的工作 initServerConfig()。首先,它設(shè)置了信號處理(SIGHUP并且 SIGPIPE信號被忽略了—有機(jī)會通過添加在接收到SIGHUP時(shí)以其他守護(hù)程序的方式重新加載其配置文件的功能來改進(jìn)Redis ),包括在服務(wù)器接收到時(shí)打印stacktrace a SIGSEGV(以及其他相關(guān)信號),請參閱segvHandler()。
? 創(chuàng)建了許多雙向鏈接列表(請參閱參考資料adlist.h)來跟蹤客戶端,從屬設(shè)備,監(jiān)視器(發(fā)送MONITOR命令的客戶端 )和無對象列表。
共享對象
? 很多人都知道 Redis內(nèi)部維護(hù)[0-9999]的整數(shù)對象池。創(chuàng)建大量的整數(shù)類型redisObject 存在內(nèi)存開銷,每個(gè)redisObject內(nèi)部結(jié)構(gòu)至少占16字節(jié),甚至超過了整數(shù)自身空間消耗。所以Redis內(nèi)存維護(hù)一個(gè)[0-9999]的整數(shù)對象池,用于節(jié)約內(nèi)存。 除了整數(shù)值對象,其他類型如list,hash,set,zset內(nèi)部元素也可以使用整數(shù)對象池。
? 除了整數(shù)對象池,還可以共享許多不同命令,響應(yīng)字符串和錯(cuò)誤消息所需要的通用Redis對象,而不必每次都分配它們,從而節(jié)省了內(nèi)存。例如:
shared.crlf = createObject(REDIS_STRING,sdsnew("\r\n"));
shared.ok = createObject(REDIS_STRING,sdsnew("+OK\r\n"));
shared.err = createObject(REDIS_STRING,sdsnew("-ERR\r\n"));
shared.emptybulk = createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));
事件循環(huán)
? initServer()會創(chuàng)建核心事件循環(huán),即調(diào)用aeCreateEventLoop()函數(shù)(參閱ae.c)。
? ae.h提供了一個(gè)獨(dú)立于平臺的包裝程序,用于設(shè)置I / O事件通知循環(huán),該循環(huán)程序epoll在Linuxkqueue上,BSD上使用,并在各自的首選不可用時(shí)返回select。Redis的事件循環(huán)輪詢新連接和I/O事件(從套接字讀取請求并向套接字寫入響應(yīng)),在新事件到達(dá)時(shí)觸發(fā)。這就是Redis如此快速響應(yīng)的原因,它可以同時(shí)為成千上萬的客戶端提供服務(wù),而不會阻塞單個(gè)請求的處理和響應(yīng)。
Databases
? initServer()初始化了一些redisDb對象,這些對象封裝了特定Redis數(shù)據(jù)庫的詳細(xì)信息,包括跟蹤即將到期的密鑰,正在阻止的密鑰(來自B{L,R}POP命令或I / O的密鑰)以及正在受檢查檢查的密鑰和設(shè)置。(默認(rèn)情況下,有16個(gè)獨(dú)立的數(shù)據(jù)庫,可以將它們視為Redis服務(wù)器中的名稱空間。)
TCP socket
? initServer()這是Redis偵聽連接的套接字(默認(rèn)情況下綁定到端口6379)的位置。另一個(gè)Redis本地包裝器anet.h定義anetTcpServer()了許多其他功能,這些功能簡化了設(shè)置新套接字,綁定和偵聽端口的通常復(fù)雜性。
serverCron
? initServer()進(jìn)一步為數(shù)據(jù)庫和pub / sub分配各種字典和列表,重置統(tǒng)計(jì)信息和各種標(biāo)志,并記下服務(wù)器啟動時(shí)間的UNIX時(shí)間戳。serverCron() 向事件循環(huán)注冊為時(shí)間事件,每100毫秒執(zhí)行一次該功能。(這并不完全,因?yàn)樽畛?serverCron()將其設(shè)置為在1毫秒內(nèi)運(yùn)行,以使該功能隨服務(wù)器啟動立即開始,但隨后將其設(shè)置為100毫秒執(zhí)行一次。)
? serverCron() 為Redis執(zhí)行許多定期任務(wù),包括詳細(xì)記錄數(shù)據(jù)庫大?。ㄊ褂玫逆I和內(nèi)存的數(shù)量)和已連接的客戶端,調(diào)整哈希表的大小,關(guān)閉空閑/超時(shí)的客戶端連接,執(zhí)行任何后臺保存或AOF重寫,如果已滿足所配置的保存條件(在這么多秒內(nèi)更改了很多鍵),則啟動后臺保存。
在事件循環(huán)中注冊連接處理器
? initServer()通過注冊套接字的描述符,并在acceptHandler()接受新連接時(shí)注冊要調(diào)用的函數(shù),從而將事件循環(huán)與服務(wù)器的TCP套接字掛鉤。
打開AOF
? initServer()會創(chuàng)建AOF文件,如果文件已存在,則直接打開。
備份主進(jìn)程id
? 如果服務(wù)器配置為守護(hù)進(jìn)程,則Redis現(xiàn)在將嘗試寫出一個(gè)pid文件(其路徑是可配置的,但默認(rèn)為 /var/run/redis.pid)。
? 此時(shí),服務(wù)器已啟動,Redis會將這個(gè)事實(shí)記錄到其日志文件中。
恢復(fù)AOF/RDB數(shù)據(jù)
? 如果存在AOF或數(shù)據(jù)庫轉(zhuǎn)儲文件(例如dump.rdb),則會將其加載,從而將服務(wù)器數(shù)據(jù)恢復(fù)到上一個(gè)會話。如果兩者都存在,則AOF優(yōu)先。
事件循環(huán)設(shè)置
? 最后,Redis在每次進(jìn)入事件循環(huán)時(shí)都會注冊一個(gè)要調(diào)用的函數(shù)beforeSleep()(因?yàn)樵撨^程實(shí)際上在等待通知事件的過程中進(jìn)入睡眠狀態(tài))。
進(jìn)入事件循環(huán)
? Redis通過調(diào)用aeMain()帶有參數(shù)的進(jìn)入主事件循環(huán)server.el(請記住,該成員包含指向的指針aeEventLoop)。如果每次循環(huán)都有任何時(shí)間或文件事件要處理,則將調(diào)用它們各自的處理程序函數(shù)。aeProcessEvents()封裝此邏輯-時(shí)間事件由定制邏輯來處理,而文件事件是由底層處理epoll或 kqueue或select I/O事件通知系統(tǒng)。
? 由于Redis需要響應(yīng)時(shí)間事件及文件I/O事件,因此它實(shí)現(xiàn)了自定義事件/輪詢循環(huán)aeMain()。通過檢查是否需要處理事件,并利用文件事件通知,事件循環(huán)可以有效地進(jìn)入睡眠狀態(tài),直到有工作要做為止,并且不會使CPU陷入緊張的while循環(huán)中。
處理新連接
? 當(dāng)有一個(gè)I/O事件與服務(wù)器正在偵聽的套接字的文件描述符相關(guān)聯(lián)時(shí)(即套接字具有等待讀取或?qū)懭氲臄?shù)據(jù)),Redis注冊為被調(diào)用。acceptHandler()創(chuàng)建一個(gè)客戶端對象-指向中redisClient定義的結(jié)構(gòu)的指針,表示新的客戶端連接。
? 調(diào)用createClient()以分配和初始化客戶端對象。默認(rèn)情況下,它選擇數(shù)據(jù)庫0(因?yàn)槊總€(gè)服務(wù)器必須至少有一個(gè)Redis db),并將acceptHandler()生成的客戶端文件描述符與客戶端對象相關(guān)聯(lián)。最后將客戶端附加到所跟蹤的客戶端的全局列表server.clients中。事件循環(huán)中注冊一個(gè)處理程序,該函數(shù)readQueryFromClient()用于何時(shí)從客戶端連接讀取數(shù)據(jù)。
從客戶端讀取命令
? 當(dāng)客戶端發(fā)出命令請求時(shí),由主事件循環(huán)調(diào)用。它會盡可能多地讀取命令(最多1024個(gè)字節(jié))到臨時(shí)緩沖區(qū),然后將其附加到特定于客戶端的緩沖區(qū)中,即:查詢緩沖區(qū)。這使Redis可以處理有效載荷大于1024字節(jié)的命令,或者由于I/O原因而被拆分為多個(gè)讀取事件的命令。然后調(diào)用processInputBuffer(),將客戶端對象作為參數(shù)傳遞。
? processInputBuffer()將來自客戶端的原始查詢解析為用于執(zhí)行Redis命令的參數(shù)。首先必須解決客戶機(jī)被B{L,R}POP 命令阻塞的可能性,并且在這種情況下盡早解救。然后,該函數(shù)將原始查詢緩沖區(qū)解析為參數(shù),創(chuàng)建每個(gè)的Redis字符串對象并將它們存儲在客戶端對象的數(shù)組中。該查詢采用Redis協(xié)議的形式,processInputBuffer()實(shí)際上是一個(gè)協(xié)議解析器,processCommand()來完全解析查詢。
? processCommand()從客戶端獲取命令的參數(shù)并執(zhí)行。在實(shí)際執(zhí)行命令之前,它會執(zhí)行許多檢查-如果任何檢查失敗,它將錯(cuò)誤消息附加到客戶端對象的答復(fù)列表中并返回給調(diào)用方processInputBuffer()。在特殊情況QUIT下處理了 命令后(為了安全地關(guān)閉客戶端),請將processCommand()設(shè)置在commandTable,這是在Redis的啟動周期中先前設(shè)置的。如果這是一個(gè)未知命令,或者客戶端錯(cuò)誤地認(rèn)為該命令是錯(cuò)誤的。雖然不常用,但是Redis可以配置為在接受命令之前要求密碼來認(rèn)證客戶端,這是Redis檢查客戶端是否經(jīng)過認(rèn)證的階段,否則將設(shè)置錯(cuò)誤。如果將Redis配置為使用最大內(nèi)存量,那么它會在此時(shí)嘗試釋放內(nèi)存(如果可能的話)(從空閑列表中釋放對象并刪除過期的密鑰),否則,如果服務(wù)器超出限制,它不會處理命令REDIS_CMD_DENYOOM標(biāo)志設(shè)置(主要是寫,像SET,INCR,RPUSH, ZADD等),再次出現(xiàn)錯(cuò)誤。Redis的最后一項(xiàng)檢查是,只有在訂閱了未解決的頻道時(shí),客戶端才能發(fā)出SUBSCRIBE或 UNSUBSCRIBE命令,否則,這是一個(gè)錯(cuò)誤。如果所有檢查均已通過,則將通過call()使用客戶端對象和命令對象作為參數(shù)調(diào)用來執(zhí)行命令。
執(zhí)行命令并響應(yīng)
? call(),struct redisCommandProc從對象的proc成員獲取類型為的函數(shù)的指針。
? 像SET和ZADD這樣的寫命令會使服務(wù)器“變臟”,換句話說,服務(wù)器被標(biāo)記為內(nèi)存中的頁面已更改。這對于自動保存過程非常重要,該過程可跟蹤在一定時(shí)期內(nèi)已更改了多少個(gè)Key寫入AOF。feedAppendOnlyFile()如果啟用了AOF的使用,該函數(shù)將調(diào)用 ,這會將命令緩沖區(qū)從客戶端寫到AOF,以便可以重播命令。(它將將相對密鑰有效期設(shè)置為絕對有效期的命令轉(zhuǎn)換為命令,但是否則,它基本上會復(fù)制從客戶端傳入的命令,請參見catAppendOnlyGenericCommand()。如果連接了任何從屬,call()則將命令發(fā)送給每個(gè)從屬以便從屬在本地執(zhí)行,可參閱replicationFeedSlaves()。同樣,如果連接了任何客戶端并發(fā)出了 MONITOR命令,Redis將發(fā)送該命令的表示形式,并帶有時(shí)間戳,請參見 replicationFeedMonitors()。
? 控制權(quán)返回給調(diào)用方,該調(diào)用方processCommand()將客戶端對象重置為后續(xù)命令。
? 如前所述,每個(gè)Redis命令過程本身負(fù)責(zé)設(shè)置要發(fā)送到客戶端的響應(yīng)。后readQueryFromClient()退出,并返回Redis的在以事件循環(huán)aeMain(),aeProcessEvents()將搭載在寫緩沖區(qū)中等待響應(yīng),并將其復(fù)制到客戶端連接的插座中。
? 客戶端和服務(wù)器都返回到可以分別發(fā)出和處理更多Redis命令的狀態(tài)。
1.3 INFO命令
通過給定可選的參數(shù) section ,可以讓命令只返回某一部分的信息:
-
server : 一般 Redis 服務(wù)器信息,包含以下域:
- redis_version : Redis 服務(wù)器版本
- redis_git_sha1 : Git SHA1
- redis_git_dirty : Git dirty flag
- os : Redis 服務(wù)器的宿主操作系統(tǒng)
- arch_bits : 架構(gòu)(32 或 64 位)
- multiplexing_api : Redis 所使用的事件處理機(jī)制
- gcc_version : 編譯 Redis 時(shí)所使用的 GCC 版本
- process_id : 服務(wù)器進(jìn)程的 PID
- run_id : Redis 服務(wù)器的隨機(jī)標(biāo)識符(用于 Sentinel 和集群)
- tcp_port : TCP/IP 監(jiān)聽端口
- uptime_in_seconds : 自 Redis 服務(wù)器啟動以來,經(jīng)過的秒數(shù)
- uptime_in_days : 自 Redis 服務(wù)器啟動以來,經(jīng)過的天數(shù)
- lru_clock : 以分鐘為單位進(jìn)行自增的時(shí)鐘,用于 LRU 管理
-
clients : 已連接客戶端信息,包含以下域:
- connected_clients : 已連接客戶端的數(shù)量(不包括通過從屬服務(wù)器連接的客戶端)
- client_longest_output_list : 當(dāng)前連接的客戶端當(dāng)中,最長的輸出列表
- client_longest_input_buf : 當(dāng)前連接的客戶端當(dāng)中,最大輸入緩存
- blocked_clients : 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客戶端的數(shù)量
-
memory : 內(nèi)存信息,包含以下域:
- used_memory : 由 Redis 分配器分配的內(nèi)存總量,以字節(jié)(byte)為單位
- used_memory_human : 以人類可讀的格式返回 Redis 分配的內(nèi)存總量
- used_memory_rss : 從操作系統(tǒng)的角度,返回 Redis 已分配的內(nèi)存總量(俗稱常駐集大?。_@個(gè)值和 top 、 ps 等命令的輸出一致。
- used_memory_peak : Redis 的內(nèi)存消耗峰值(以字節(jié)為單位)
- used_memory_peak_human : 以人類可讀的格式返回 Redis 的內(nèi)存消耗峰值
- used_memory_lua : Lua 引擎所使用的內(nèi)存大?。ㄒ宰止?jié)為單位)
- mem_fragmentation_ratio : used_memory_rss 和 used_memory 之間的比率
- mem_allocator : 在編譯時(shí)指定的, Redis 所使用的內(nèi)存分配器??梢允?libc 、 jemalloc 或者 tcmalloc 。
在理想情況下, used_memory_rss 的值應(yīng)該只比 used_memory 稍微高一點(diǎn)兒。
當(dāng) rss > used ,且兩者的值相差較大時(shí),表示存在(內(nèi)部或外部的)內(nèi)存碎片。
內(nèi)存碎片的比率可以通過 mem_fragmentation_ratio 的值看出。
當(dāng) used > rss 時(shí),表示 Redis 的部分內(nèi)存被操作系統(tǒng)換出到交換空間了,在這種情況下,操作可能會產(chǎn)生明顯的延遲。
當(dāng) Redis 釋放內(nèi)存時(shí),分配器可能會,也可能不會,將內(nèi)存返還給操作系統(tǒng)。
如果 Redis 釋放了內(nèi)存,卻沒有將內(nèi)存返還給操作系統(tǒng),那么 used_memory 的值可能和操作系統(tǒng)顯示的 Redis 內(nèi)存占用并不一致。
查看 used_memory_peak 的值可以驗(yàn)證這種情況是否發(fā)生。
persistence : RDB 和 AOF 的相關(guān)信息
stats : 一般統(tǒng)計(jì)信息
replication : 主/從復(fù)制信息
cpu : CPU 計(jì)算量統(tǒng)計(jì)信息
commandstats : Redis 命令統(tǒng)計(jì)信息
cluster : Redis 集群信息
keyspace : 數(shù)據(jù)庫相關(guān)的統(tǒng)計(jì)信息