一.启动memcached
1.memcached启动选项:
-p TCP监听端口 (default: 11211)
-U UDP 监听端口 (default: 11211, 0 is off)
-s UNIX socket监听路径,不支持网络
-a UNIX socket访问掩码, 八进制 (default: 0700)
-l <ip_addr> 监听的服务器IP地址 (default: all addresses)
-d 启动一个守护进程
-r 最大限度利用核心文件限制
-u 运行memcached用户
-m 最大的内存使用 (default: 64 MB)
-M 内存耗尽返回错误
-c 最大并发连接 (default: 1024)
-k 锁定所有分页内存
-v 输出警告和错误信息
-vv 同时打印客户端请求和返回信息
-vvv 打印内部状态转换信息
-i 打印memcached 和 libevent 版本信息
-P 设置保存pid文件, only used with -d option
-f 块大小增长倍数 (default: 1.25)
-n key+value+flags最小分配空间(default: 48)
-L 如何有效,尝试使用大内存页。增加内存页大小可以减少失误的TLB数量,提高性能。
-D 指定key和IDs的分隔符 default is ":" (colon). 如果指定此选项,统计信息收集自动开启;
-t 使用的线程数量 (default: 4)
-R 每个事件的最大请求数 (default: 20)
-C 禁止使用 CAS
-b 设置积压队列数限制 (default: 1024)
-B 绑定协议 - one of ascii, binary, or auto (default)
-I 分配给每个slab页(default: 1mb, min: 1k, max: 128m)
2.启动
# ./memcached -d -m 500 -u root -l 192.168.50.10 -p 12000 -c 256 -P /tmp/memcached.pid -vvv
slab class 1: chunk size 96 perslab 10922
slab class 2: chunk size 120 perslab 8738
slab class 3: chunk size 152 perslab 6898
slab class 4: chunk size 192 perslab 5461
slab class 5: chunk size 240 perslab 4369
slab class 6: chunk size 304 perslab 3449
slab class 7: chunk size 384 perslab 2730
slab class 8: chunk size 480 perslab 2184
slab class 9: chunk size 600 perslab 1747
slab class 10: chunk size 752 perslab 1394
slab class 11: chunk size 944 perslab 1110
slab class 12: chunk size 1184 perslab 885
slab class 13: chunk size 1480 perslab 708
slab class 14: chunk size 1856 perslab 564
slab class 15: chunk size 2320 perslab 451
slab class 16: chunk size 2904 perslab 361
slab class 17: chunk size 3632 perslab 288
slab class 18: chunk size 4544 perslab 230
slab class 19: chunk size 5680 perslab 184
slab class 20: chunk size 7104 perslab 147
slab class 21: chunk size 8880 perslab 118
slab class 22: chunk size 11104 perslab 94
slab class 23: chunk size 13880 perslab 75
slab class 24: chunk size 17352 perslab 60
slab class 25: chunk size 21696 perslab 48
slab class 26: chunk size 27120 perslab 38
slab class 27: chunk size 33904 perslab 30
slab class 28: chunk size 42384 perslab 24
slab class 29: chunk size 52984 perslab 19
slab class 30: chunk size 66232 perslab 15
slab class 31: chunk size 82792 perslab 12
slab class 32: chunk size 103496 perslab 10
slab class 33: chunk size 129376 perslab 8
slab class 34: chunk size 161720 perslab 6
slab class 35: chunk size 202152 perslab 5
slab class 36: chunk size 252696 perslab 4
slab class 37: chunk size 315872 perslab 3
slab class 38: chunk size 394840 perslab 2
slab class 39: chunk size 493552 perslab 2
slab class 40: chunk size 616944 perslab 1
slab class 41: chunk size 771184 perslab 1
slab class 42: chunk size 1048576 perslab 1
使用12000端口,root用户,最大使用500M内存,253个并发连接,输出详细信息,以守护进程方式运行。
从输出信息可看出memcached分配内存的过程。
在入口main中 初始化阶段 while循环 接受处理这些参数:
int main (int argc, char **argv) {
.....若干变量声明....
if (!sanitycheck()) {
return EX_OSERR;
}
/* handle SIGINT */
signal(SIGINT, sig_handler);
/* init settings */
settings_init();
/* set stderr non-buffering (for running under, say, daemontools) */
setbuf(stderr, NULL);
/* process arguments */ /* arguments 后不跟值 arguments: 后跟值 */
while (-1 != (c = getopt(argc, argv,
"a:" /* access mask for unix socket */ /* UNIX socket访问掩码, 八进制 (default: 0700) */
"A" /* enable admin shutdown commannd */
"p:" /* TCP port number to listen on */ /* TCP监听端口 (default: 11211) */
"s:" /* unix socket path to listen on */ /* UNIX socket监听路径, 不支持网络 */
"U:" /* UDP port number to listen on */ /* UDP监听端口 (default: 11211, 0 is off) */
"m:" /* max memory to use for items in megabytes */ /* 最大的内存使用 (default: 64 MB) */
"M" /* return error on memory exhausted */ /* 内存耗尽返回错误 */
"c:" /* max simultaneous connections */ /* 最大并发连接 (default: 1024) */
"k" /* lock down all paged memory */ /* 锁定所有分页内存 */
"hi" /* help, licence info */
"r" /* maximize core file limit */ /* 最大限度利用核心文件限制 */
"v" /* verbose */ /* 输出警告和错误信息 */
"d" /* daemon mode */ /* 启动一个守护进程 */
"l:" /* interface to listen on */ /* <ip_addr> 监听的服务器IP地址 (default: all addresses) */
"u:" /* user identity to run as */ /* 运行memcached用户 */
"P:" /* save PID in file */ /* 设置保存pid文件, only used with -d option */
"f:" /* factor? */ /* 块大小增长倍数 (default: 1.25) */
"n:" /* minimum space allocated for key+value+flags */ /* key+value+flags最小分配空间(default: 48) */
"t:" /* threads */ /* 使用的线程数量 (default: 4) */
"D:" /* prefix delimiter? */ /* 指定key和IDs的分隔符 default is ":" (colon). 如果指定此选项,统计信息收集自动开启; */
"L" /* Large memory pages */ /* 如何有效,尝试使用大内存页。增加内存页大小可以减少失误的TLB数量,提高性能。 */
"R:" /* max requests per event */ /* 每个事件的最大请求数 (default: 20) */
"C" /* Disable use of CAS */ /* 禁止使用 CAS */
"b:" /* backlog queue limit */ /* 设置积压队列数限制 (default: 1024) */
"B:" /* Binding protocol */ /* 绑定协议 - one of ascii, binary, or auto (default) */
"I:" /* Max item size */ /* 分配给每个slab页(default: 1mb, min: 1k, max: 128m) */
"S" /* Sasl ON */
"F" /* Disable flush_all */
"o:" /* Extended generic options */
))) {
switch (c) {
case 'A':
/* enables "shutdown" command */
settings.shutdown_command = true;
break;
case 'a':
/* access for unix domain socket, as octal mask (like chmod)*/
settings.access= strtol(optarg,NULL,8);
break;
case 'U':
/* UDP port number to listen on */
settings.udpport = atoi(optarg);
udp_specified = true;
break;
case 'p':
/* TCP port number to listen on */
settings.port = atoi(optarg);
tcp_specified = true;
break;
case 's':
/* unix socket path to listen on */
settings.socketpath = optarg;
break;
case 'm':
/* max memory to use for items in megabytes */
settings.maxbytes = ((size_t)atoi(optarg)) * 1024 * 1024;
break;
case 'M':
/* return error on memory exhausted */
settings.evict_to_free = 0;
break;
case 'c':
/* max simultaneous connections */
settings.maxconns = atoi(optarg);
break;
case 'h':
/* help, licence info */
usage();
exit(EXIT_SUCCESS);
case 'i':
/* help, licence info */
usage_license();
exit(EXIT_SUCCESS);
case 'k':
/* lock down all paged memory */
lock_memory = true;
break;
case 'v':
/* verbose */
settings.verbose++;
break;
case 'l':
/* interface to listen on */
if (settings.inter != NULL) {
size_t len = strlen(settings.inter) + strlen(optarg) + 2;
char *p = malloc(len);
if (p == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
return 1;
}
snprintf(p, len, "%s,%s", settings.inter, optarg);
free(settings.inter);
settings.inter = p;
} else {
settings.inter= strdup(optarg);
}
break;
case 'd':
do_daemonize = true;
break;
case 'r':
maxcore = 1;
break;
case 'R':
settings.reqs_per_event = atoi(optarg);
if (settings.reqs_per_event == 0) {
fprintf(stderr, "Number of requests per event must be greater than 0\n");
return 1;
}
break;
case 'u':
/* user identity to run as */
username = optarg;
break;
case 'P':
pid_file = optarg;
break;
case 'f':
settings.factor = atof(optarg);
if (settings.factor <= 1.0) {
fprintf(stderr, "Factor must be greater than 1\n");
return 1;
}
break;
case 'n':
settings.chunk_size = atoi(optarg);
if (settings.chunk_size == 0) {
fprintf(stderr, "Chunk size must be greater than 0\n");
return 1;
}
break;
case 't':
settings.num_threads = atoi(optarg);
if (settings.num_threads <= 0) {
fprintf(stderr, "Number of threads must be greater than 0\n");
return 1;
}
/* There're other problems when you get above 64 threads.
* In the future we should portably detect # of cores for the
* default.
*/
if (settings.num_threads > 64) {
fprintf(stderr, "WARNING: Setting a high number of worker"
"threads is not recommended.\n"
" Set this value to the number of cores in"
" your machine or less.\n");
}
break;
case 'D':
if (! optarg || ! optarg[0]) {
fprintf(stderr, "No delimiter specified\n");
return 1;
}
settings.prefix_delimiter = optarg[0];
settings.detail_enabled = 1;
break;
case 'L' :
if (enable_large_pages() == 0) {
preallocate = true;
} else {
fprintf(stderr, "Cannot enable large pages on this system\n"
"(There is no Linux support as of this version)\n");
return 1;
}
break;
case 'C' :
settings.use_cas = false;
break;
case 'b' :
settings.backlog = atoi(optarg);
break;
case 'B':
protocol_specified = true;
if (strcmp(optarg, "auto") == 0) {
settings.binding_protocol = negotiating_prot;
} else if (strcmp(optarg, "binary") == 0) {
settings.binding_protocol = binary_prot;
} else if (strcmp(optarg, "ascii") == 0) {
settings.binding_protocol = ascii_prot;
} else {
fprintf(stderr, "Invalid value for binding protocol: %s\n"
" -- should be one of auto, binary, or ascii\n", optarg);
exit(EX_USAGE);
}
break;
case 'I':
buf = strdup(optarg);
unit = buf[strlen(buf)-1];
if (unit == 'k' || unit == 'm' ||
unit == 'K' || unit == 'M') {
buf[strlen(buf)-1] = '\0';
size_max = atoi(buf);
if (unit == 'k' || unit == 'K')
size_max *= 1024;
if (unit == 'm' || unit == 'M')
size_max *= 1024 * 1024;
settings.item_size_max = size_max;
} else {
settings.item_size_max = atoi(buf);
}
if (settings.item_size_max < 1024) {
fprintf(stderr, "Item max size cannot be less than 1024 bytes.\n");
return 1;
}
if (settings.item_size_max > 1024 * 1024 * 128) {
fprintf(stderr, "Cannot set item size limit higher than 128 mb.\n");
return 1;
}
if (settings.item_size_max > 1024 * 1024) {
fprintf(stderr, "WARNING: Setting item max size above 1MB is not"
" recommended!\n"
" Raising this limit increases the minimum memory requirements\n"
" and will decrease your memory efficiency.\n"
);
}
free(buf);
break;
case 'S': /* set Sasl authentication to true. Default is false */
#ifndef ENABLE_SASL
fprintf(stderr, "This server is not built with SASL support.\n");
exit(EX_USAGE);
#endif
settings.sasl = true;
break;
case 'F' :
settings.flush_enabled = false;
break;
case 'o': /* It's sub-opts time! */
subopts = optarg;
while (*subopts != '\0') {
switch (getsubopt(&subopts, subopts_tokens, &subopts_value)) {
case MAXCONNS_FAST:
settings.maxconns_fast = true;
break;
case HASHPOWER_INIT:
if (subopts_value == NULL) {
fprintf(stderr, "Missing numeric argument for hashpower\n");
return 1;
}
settings.hashpower_init = atoi(subopts_value);
if (settings.hashpower_init < 12) {
fprintf(stderr, "Initial hashtable multiplier of %d is too low\n",
settings.hashpower_init);
return 1;
} else if (settings.hashpower_init > 64) {
fprintf(stderr, "Initial hashtable multiplier of %d is too high\n"
"Choose a value based on \"STAT hash_power_level\" from a running instance\n",
settings.hashpower_init);
return 1;
}
break;
case SLAB_REASSIGN:
settings.slab_reassign = true;
break;
case SLAB_AUTOMOVE:
if (subopts_value == NULL) {
settings.slab_automove = 1;
break;
}
settings.slab_automove = atoi(subopts_value);
if (settings.slab_automove < 0 || settings.slab_automove > 2) {
fprintf(stderr, "slab_automove must be between 0 and 2\n");
return 1;
}
break;
case TAIL_REPAIR_TIME:
if (subopts_value == NULL) {
fprintf(stderr, "Missing numeric argument for tail_repair_time\n");
return 1;
}
settings.tail_repair_time = atoi(subopts_value);
if (settings.tail_repair_time < 10) {
fprintf(stderr, "Cannot set tail_repair_time to less than 10 seconds\n");
return 1;
}
break;
case HASH_ALGORITHM:
if (subopts_value == NULL) {
fprintf(stderr, "Missing hash_algorithm argument\n");
return 1;
};
if (strcmp(subopts_value, "jenkins") == 0) {
hash_type = JENKINS_HASH;
} else if (strcmp(subopts_value, "murmur3") == 0) {
hash_type = MURMUR3_HASH;
} else {
fprintf(stderr, "Unknown hash_algorithm option (jenkins, murmur3)\n");
return 1;
}
break;
case LRU_CRAWLER:
if (start_item_crawler_thread() != 0) {
fprintf(stderr, "Failed to enable LRU crawler thread\n");
return 1;
}
break;
case LRU_CRAWLER_SLEEP:
settings.lru_crawler_sleep = atoi(subopts_value);
if (settings.lru_crawler_sleep > 1000000 || settings.lru_crawler_sleep < 0) {
fprintf(stderr, "LRU crawler sleep must be between 0 and 1 second\n");
return 1;
}
break;
case LRU_CRAWLER_TOCRAWL:
if (!safe_strtoul(subopts_value, &tocrawl)) {
fprintf(stderr, "lru_crawler_tocrawl takes a numeric 32bit value\n");
return 1;
}
settings.lru_crawler_tocrawl = tocrawl;
break;
default:
printf("Illegal suboption \"%s\"\n", subopts_value);
return 1;
}
}
break;
default:
fprintf(stderr, "Illegal argument \"%c\"\n", c);
return 1;
}
}