请选择 进入手机版 | 继续访问电脑版

Redis中国用户组(CRUG)论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: 活动 交友 discuz
查看: 975|回复: 0

Redis源码分析(三十三)--- redis-cli客户端命令行接口的实现2

[复制链接]
  • TA的每日心情
    开心
    2017-8-30 15:46
  • 签到天数: 94 天

    [LV.6]常住居民II

    371

    主题

    481

    帖子

    3831

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    3831

    最佳新人活跃会员宣传达人突出贡献优秀版主荣誉管理论坛元老

    发表于 2016-4-18 09:19:06 | 显示全部楼层 |阅读模式

    今天学习完了命令行客户端的后续内容,整体感觉就是围绕着2个东西转,config和mode。为什么我会这么说呢,请继续往下看,客户端中的配置结构体和之前我们所学习的配置结构体,不是指的同一个概念,cli中的结构体除了基本的ip,Port端口号,还有就是各种mode的配置了。

    1. /* Redis配置结构体 */  
    2. static struct config {  
    3.     char *hostip;  
    4.     int hostport;  
    5.     char *hostsocket;  
    6.     long repeat;  
    7.     long interval;  
    8.     int dbnum;  
    9.     int interactive;  
    10.     int shutdown;  
    11.     int monitor_mode;  
    12.     int pubsub_mode;  
    13.     int latency_mode;  
    14.     int latency_history;  
    15.     int cluster_mode;  
    16.     int cluster_reissue_command;  
    17.     int slave_mode;  
    18.     int pipe_mode;  
    19.     int pipe_timeout;  
    20.     int getrdb_mode;  
    21.     int stat_mode;  
    22.     int scan_mode;  
    23.     int intrinsic_latency_mode;  
    24.     int intrinsic_latency_duration;  
    25.     char *pattern;  
    26.     char *rdb_filename;  
    27.     int bigkeys;  
    28.     int stdinarg; /* get last arg from stdin. (-x option) */  
    29.     char *auth;  
    30.     int output; /* output mode, see OUTPUT_* defines */  
    31.     sds mb_delim;  
    32.     char prompt[128];  
    33.     char *eval;  
    34.     int last_cmd_type;  
    35. } config;  
    复制代码

    里面少说也有10个mode模式了吧。我们先倒过来,看看cli的主程序运行的流程,也就是main函数的执行步骤:
    1. /*main函数主程序操作*/  
    2. int main(int argc, char **argv) {  
    3.     int firstarg;  
    4.       
    5.     //首先初始化客户端配置操作  
    6.     config.hostip = sdsnew("127.0.0.1");  
    7.     config.hostport = 6379;  
    8.     config.hostsocket = NULL;  
    9.     config.repeat = 1;  
    10.     config.interval = 0;  
    11.     config.dbnum = 0;  
    12.     config.interactive = 0;  
    13.     config.shutdown = 0;  
    14.     config.monitor_mode = 0;  
    15.     config.pubsub_mode = 0;  
    16.     config.latency_mode = 0;  
    17.     config.latency_history = 0;  
    18.     config.cluster_mode = 0;  
    19.     config.slave_mode = 0;  
    20.     config.getrdb_mode = 0;  
    21.     config.stat_mode = 0;  
    22.     config.scan_mode = 0;  
    23.     config.intrinsic_latency_mode = 0;  
    24.     config.pattern = NULL;  
    25.     config.rdb_filename = NULL;  
    26.     config.pipe_mode = 0;  
    27.     config.pipe_timeout = REDIS_CLI_DEFAULT_PIPE_TIMEOUT;  
    28.     config.bigkeys = 0;  
    29.     config.stdinarg = 0;  
    30.     config.auth = NULL;  
    31.     config.eval = NULL;  
    32.     config.last_cmd_type = -1;  
    33.   
    34.     if (!isatty(fileno(stdout)) && (getenv("FAKETTY") == NULL))  
    35.         config.output = OUTPUT_RAW;  
    36.     else  
    37.         config.output = OUTPUT_STANDARD;  
    38.     config.mb_delim = sdsnew("\n");  
    39.     cliInitHelp();  
    40.       
    41.     //根据用户输入的参数,配置config  
    42.     firstarg = parseOptions(argc,argv);  
    43.     argc -= firstarg;  
    44.     argv += firstarg;  
    45.   
    46.     //配置设置完毕,根据配置中的模式设置,调用相应的mode方法  
    47.     /* Latency mode */  
    48.     if (config.latency_mode) {  
    49.         if (cliConnect(0) == REDIS_ERR) exit(1);  
    50.         latencyMode();  
    51.     }  
    52.   
    53.     /* Slave mode */  
    54.     if (config.slave_mode) {  
    55.         if (cliConnect(0) == REDIS_ERR) exit(1);  
    56.         slaveMode();  
    57.     }  
    58.     ....  
    复制代码

    后面的代码与此相同,所以就省略了,步骤简单来说,就是设置配置,根据配置启动相应的模式,下面说说,里面的主要几种模式

    1.statMode:

    1. /* statMode主要输出一些读取数据统计的一些信息 */  
    2. static void statMode(void) {  
    3.     redisReply *reply;  
    4.     long aux, requests = 0;  
    5.     int i = 0;  
    6.   
    7.     while(1) {  
    8.         char buf[64];  
    9.         int j;  
    10.   
    11.         reply = reconnectingInfo();  
    12.         if (reply->type == REDIS_REPLY_ERROR) {  
    13.             printf("ERROR: %s\n", reply->str);  
    14.             exit(1);  
    15.         }  
    16.   
    17.         if ((i++ % 20) == 0) {  
    18.             printf(  
    19. "------- data ------ --------------------- load -------------------- - child -\n"  
    20. "keys       mem      clients blocked requests            connections          \n");  
    21.         }  
    22.   
    23.         /* Keys */  
    24.         aux = 0;  
    25.         for (j = 0; j < 20; j++) {  
    26.             long k;  
    27.   
    28.             sprintf(buf,"db%d:keys",j);  
    29.             k = getLongInfoField(reply->str,buf);  
    30.             if (k == LONG_MIN) continue;  
    31.             aux += k;  
    32.         }  
    33.         sprintf(buf,"%ld",aux);  
    34.         printf("%-11s",buf);  
    35.   
    36.         /* Used memory */  
    37.         aux = getLongInfoField(reply->str,"used_memory");  
    38.         bytesToHuman(buf,aux);  
    39.         printf("%-8s",buf);  
    40.   
    41.         /* Clients */  
    42.         aux = getLongInfoField(reply->str,"connected_clients");  
    43.         sprintf(buf,"%ld",aux);  
    44.         printf(" %-8s",buf);  
    45.   
    46.         /* Blocked (BLPOPPING) Clients */  
    47.         aux = getLongInfoField(reply->str,"blocked_clients");  
    48.         sprintf(buf,"%ld",aux);  
    49.         printf("%-8s",buf);  
    50.         ....  
    复制代码

    客户端当前的数据统计信息。

    2.latencyMode中会用到的测试硬件计算性能的方法:

    1. /* This is just some computation the compiler can't optimize out.
    2. * Should run in less than 100-200 microseconds even using very
    3. * slow hardware. Runs in less than 10 microseconds in modern HW. */  
    4. /* 普通的计算操作,测试硬件计算的速度快慢 */  
    5. unsigned long compute_something_fast(void) {  
    6.     unsigned char s[256], i, j, t;  
    7.     int count = 1000, k;  
    8.     unsigned long output = 0;  
    9.   
    10.     for (k = 0; k < 256; k++) s[k] = k;  
    11.   
    12.     i = 0;  
    13.     j = 0;  
    14.     while(count--) {  
    15.         i++;  
    16.         j = j + s[i];  
    17.         t = s[i];  
    18.         s[i] = s[j];  
    19.         s[j] = t;  
    20.         output += s[(s[i]+s[j])&255];  
    21.     }  
    22.     return output;  
    23. }  
    复制代码

    帮助命令的输出文档是由下面的函数输出的:
    1. /* 帮助命令的输出文档 */  
    2. static void usage(void) {  
    3.     sds version = cliVersion();  
    4.     fprintf(stderr,  
    5. "redis-cli %s\n"  
    6. "\n"  
    7. "Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n"  
    8. "  -h <hostname>      Server hostname (default: 127.0.0.1).\n"  
    9. "  -p <port>          Server port (default: 6379).\n"  
    10. "  -s <socket>        Server socket (overrides hostname and port).\n"  
    11. "  -a <password>      Password to use when connecting to the server.\n"  
    12. "  -r <repeat>        Execute specified command N times.\n"  
    13. "  -i <interval>      When -r is used, waits <interval> seconds per command.\n"  
    14. "                     It is possible to specify sub-second times like -i 0.1.\n"  
    15. "  -n <db>            Database number.\n"  
    16. "  -x                 Read last argument from STDIN.\n"  
    17. "  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \\n).\n"  
    18. "  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).\n"  
    19. "  --raw              Use raw formatting for replies (default when STDOUT is\n"  
    20. "                     not a tty).\n"  
    21. "  --no-raw           Force formatted output even when STDOUT is not a tty.\n"  
    22. "  --csv              Output in CSV format.\n"  
    23. "  --latency          Enter a special mode continuously sampling latency.\n"  
    24. "  --latency-history  Like --latency but tracking latency changes over time.\n"  
    25. "                     Default time interval is 15 sec. Change it using -i.\n"  
    26. "  --slave            Simulate a slave showing commands received from the master.\n"  
    27. "  --rdb <filename>   Transfer an RDB dump from remote server to local file.\n"  
    28. "  --pipe             Transfer raw Redis protocol from stdin to server.\n"  
    29. "  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.\n"  
    30. "                     no reply is received within <n> seconds.\n"  
    31. "                     Default timeout: %d. Use 0 to wait forever.\n"  
    32. "  --bigkeys          Sample Redis keys looking for big keys.\n"  
    33. "  --scan             List all keys using the SCAN command.\n"  
    34. "  --pattern <pat>    Useful with --scan to specify a SCAN pattern.\n"  
    35. "  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.\n"  
    36. "                     The test will run for the specified amount of seconds.\n"  
    37. "  --eval <file>      Send an EVAL command using the Lua script at <file>.\n"  
    38. "  --help             Output this help and exit.\n"  
    39. "  --version          Output version and exit.\n"  
    40. "\n"  
    41. "Examples:\n"  
    42. "  cat /etc/passwd | redis-cli -x set mypasswd\n"  
    43. "  redis-cli get mypasswd\n"  
    44. "  redis-cli -r 100 lpush mylist x\n"  
    45. "  redis-cli -r 100 -i 1 info | grep used_memory_human:\n"  
    46. "  redis-cli --eval myscript.lua key1 key2 , arg1 arg2 arg3\n"  
    47. "  redis-cli --scan --pattern '*:12345*'\n"  
    48. "\n"  
    49. "  (Note: when using --eval the comma separates KEYS[] from ARGV[] items)\n"  
    50. "\n"  
    51. "When no command is given, redis-cli starts in interactive mode.\n"  
    52. "Type \"help\" in interactive mode for information on available commands.\n"  
    53. "\n",  
    54.         version, REDIS_CLI_DEFAULT_PIPE_TIMEOUT);  
    55.     sdsfree(version);  
    56.     exit(1);  
    57. }  
    复制代码

    在命令里面,会由于2个概念,1个叫一般性的Command命令还有一个是CommandGroup命令组的概念,举个例子,比如list,set等经常会用到的一些命令,后面可以接好多种参数的命令,属性命令组命令,一般CONFIG GET,这种功能非常单一的命令我们就叫他为普通的命令,Dump,Exist啊等等这些命令都是普通的命令,CommandGroup的命令不是很多就下面这么几个:
    1. /* 所有的命令组 */  
    2. static char *commandGroups[] = {  
    3.     "generic",  
    4.     "string",  
    5.     "list",  
    6.     "set",  
    7.     "sorted_set",  
    8.     "hash",  
    9.     "pubsub",  
    10.     "transactions",  
    11.     "connection",  
    12.     "server",  
    13.     "scripting",  
    14.     "hyperloglog"  
    15. };  
    复制代码

    也是最最常用的命令,在redis的系统中。

    转自:http://blog.csdn.net/androidlushangderen/article/details/40889141
    上一篇:Redis源码分析(三十二)--- redis-cli客户端命令行接口的实现1
    下一篇:Redis源码分析(三十四)--- redis.h服务端的实现分析(1)
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    阿里云
    阿里云

    Archiver|手机版|小黑屋|Redis中国用户组 ( 京ICP备15003959号

    GMT+8, 2017-11-21 18:04 , Processed in 0.115876 second(s), 35 queries .

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表