標籤:nosql資料庫 記憶體資料庫 redis 結構
今天學習完了命令列用戶端的後續內容,整體感覺就是圍繞著2個東西轉,config和mode。為什麼我會這麼說呢,請繼續往下看,用戶端中的配置結構體和之前我們所學習的配置結構體,不是指的同一個概念,cli中的結構體除了基本的ip,Port連接埠號碼,還有就是各種mode的配置了。
/* Redis配置結構體 */static struct config { char *hostip; int hostport; char *hostsocket; long repeat; long interval; int dbnum; int interactive; int shutdown; int monitor_mode; int pubsub_mode; int latency_mode; int latency_history; int cluster_mode; int cluster_reissue_command; int slave_mode; int pipe_mode; int pipe_timeout; int getrdb_mode; int stat_mode; int scan_mode; int intrinsic_latency_mode; int intrinsic_latency_duration; char *pattern; char *rdb_filename; int bigkeys; int stdinarg; /* get last arg from stdin. (-x option) */ char *auth; int output; /* output mode, see OUTPUT_* defines */ sds mb_delim; char prompt[128]; char *eval; int last_cmd_type;} config;
裡面少說也有10個mode模式了吧。我們先倒過來,看看cli的主程式啟動並執行流程,也就是main函數的執行步驟:
/*main函數主程式操作*/int main(int argc, char **argv) { int firstarg;//首先初始化用戶端配置操作 config.hostip = sdsnew("127.0.0.1"); config.hostport = 6379; config.hostsocket = NULL; config.repeat = 1; config.interval = 0; config.dbnum = 0; config.interactive = 0; config.shutdown = 0; config.monitor_mode = 0; config.pubsub_mode = 0; config.latency_mode = 0; config.latency_history = 0; config.cluster_mode = 0; config.slave_mode = 0; config.getrdb_mode = 0; config.stat_mode = 0; config.scan_mode = 0; config.intrinsic_latency_mode = 0; config.pattern = NULL; config.rdb_filename = NULL; config.pipe_mode = 0; config.pipe_timeout = REDIS_CLI_DEFAULT_PIPE_TIMEOUT; config.bigkeys = 0; config.stdinarg = 0; config.auth = NULL; config.eval = NULL; config.last_cmd_type = -1; if (!isatty(fileno(stdout)) && (getenv("FAKETTY") == NULL)) config.output = OUTPUT_RAW; else config.output = OUTPUT_STANDARD; config.mb_delim = sdsnew("\n"); cliInitHelp();//根據使用者輸入的參數,配置config firstarg = parseOptions(argc,argv); argc -= firstarg; argv += firstarg;//配置設定完畢,根據配置中的模式設定,調用相應的mode方法 /* Latency mode */ if (config.latency_mode) { if (cliConnect(0) == REDIS_ERR) exit(1); latencyMode(); } /* Slave mode */ if (config.slave_mode) { if (cliConnect(0) == REDIS_ERR) exit(1); slaveMode(); }....
後面的代碼與此相同,所以就省略了,步驟簡單來說,就是設定配置,根據配置啟動相應的模式,下面說說,裡面的主要幾種模式
1.statMode:
/* statMode主要輸出一些讀取資料統計的一些資訊 */static void statMode(void) { redisReply *reply; long aux, requests = 0; int i = 0; while(1) { char buf[64]; int j; reply = reconnectingInfo(); if (reply->type == REDIS_REPLY_ERROR) { printf("ERROR: %s\n", reply->str); exit(1); } if ((i++ % 20) == 0) { printf("------- data ------ --------------------- load -------------------- - child -\n""keys mem clients blocked requests connections \n"); } /* Keys */ aux = 0; for (j = 0; j < 20; j++) { long k; sprintf(buf,"db%d:keys",j); k = getLongInfoField(reply->str,buf); if (k == LONG_MIN) continue; aux += k; } sprintf(buf,"%ld",aux); printf("%-11s",buf); /* Used memory */ aux = getLongInfoField(reply->str,"used_memory"); bytesToHuman(buf,aux); printf("%-8s",buf); /* Clients */ aux = getLongInfoField(reply->str,"connected_clients"); sprintf(buf,"%ld",aux); printf(" %-8s",buf); /* Blocked (BLPOPPING) Clients */ aux = getLongInfoField(reply->str,"blocked_clients"); sprintf(buf,"%ld",aux); printf("%-8s",buf);....
用戶端當前的資料統計資訊。
2.latencyMode中會用到的測試硬體計算效能的方法:
/* This is just some computation the compiler can't optimize out. * Should run in less than 100-200 microseconds even using very * slow hardware. Runs in less than 10 microseconds in modern HW. *//* 普通的計算操作,測試硬體計算的速度快慢 */unsigned long compute_something_fast(void) { unsigned char s[256], i, j, t; int count = 1000, k; unsigned long output = 0; for (k = 0; k < 256; k++) s[k] = k; i = 0; j = 0; while(count--) { i++; j = j + s[i]; t = s[i]; s[i] = s[j]; s[j] = t; output += s[(s[i]+s[j])&255]; } return output;}
協助命令的輸出文檔是由下面的函數輸出的:
/* 協助命令的輸出文檔 */static void usage(void) { sds version = cliVersion(); fprintf(stderr,"redis-cli %s\n""\n""Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n"" -h <hostname> Server hostname (default: 127.0.0.1).\n"" -p <port> Server port (default: 6379).\n"" -s <socket> Server socket (overrides hostname and port).\n"" -a <password> Password to use when connecting to the server.\n"" -r <repeat> Execute specified command N times.\n"" -i <interval> When -r is used, waits <interval> seconds per command.\n"" It is possible to specify sub-second times like -i 0.1.\n"" -n <db> Database number.\n"" -x Read last argument from STDIN.\n"" -d <delimiter> Multi-bulk delimiter in for raw formatting (default: \\n).\n"" -c Enable cluster mode (follow -ASK and -MOVED redirections).\n"" --raw Use raw formatting for replies (default when STDOUT is\n"" not a tty).\n"" --no-raw Force formatted output even when STDOUT is not a tty.\n"" --csv Output in CSV format.\n"" --latency Enter a special mode continuously sampling latency.\n"" --latency-history Like --latency but tracking latency changes over time.\n"" Default time interval is 15 sec. Change it using -i.\n"" --slave Simulate a slave showing commands received from the master.\n"" --rdb <filename> Transfer an RDB dump from remote server to local file.\n"" --pipe Transfer raw Redis protocol from stdin to server.\n"" --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.\n"" no reply is received within <n> seconds.\n"" Default timeout: %d. Use 0 to wait forever.\n"" --bigkeys Sample Redis keys looking for big keys.\n"" --scan List all keys using the SCAN command.\n"" --pattern <pat> Useful with --scan to specify a SCAN pattern.\n"" --intrinsic-latency <sec> Run a test to measure intrinsic system latency.\n"" The test will run for the specified amount of seconds.\n"" --eval <file> Send an EVAL command using the Lua script at <file>.\n"" --help Output this help and exit.\n"" --version Output version and exit.\n""\n""Examples:\n"" cat /etc/passwd | redis-cli -x set mypasswd\n"" redis-cli get mypasswd\n"" redis-cli -r 100 lpush mylist x\n"" redis-cli -r 100 -i 1 info | grep used_memory_human:\n"" redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3\n"" redis-cli --scan --pattern '*:12345*'\n""\n"" (Note: when using --eval the comma separates KEYS[] from ARGV[] items)\n""\n""When no command is given, redis-cli starts in interactive mode.\n""Type \"help\" in interactive mode for information on available commands.\n""\n", version, REDIS_CLI_DEFAULT_PIPE_TIMEOUT); sdsfree(version); exit(1);}
在命令裡面,會由於2個概念,1個叫一般性的Command命令還有一個是CommandGroup命令組的概念,舉個例子,比如list,set等經常會用到的一些命令,後面可以接好多種參數的命令,屬性命令組命令,一般CONFIG GET,這種功能非常單一的命令我們就叫他為普通的命令,Dump,Exist啊等等這些命令都是普通的命令,CommandGroup的命令不是很多就下面這麼幾個:
/* 所有的命令組 */static char *commandGroups[] = { "generic", "string", "list", "set", "sorted_set", "hash", "pubsub", "transactions", "connection", "server", "scripting", "hyperloglog"};
也是最最常用的命令,在redis的系統中。
Redis源碼分析(三十三)--- redis-cli.c用戶端命令列介面的實現(2)