Memcached原理
安装/运行
参数
memcached -h
memcached 1.4.25
-p <num> TCP端口,默认为11211,可以不设置
-U <num> UDP端口,默认为11211,0为关闭
-s <file> UNIX socket
-a <mask> access mask for UNIX socket, in octal (default: 0700)
-l <addr> 监听的 IP 地址,本机可以不设置此参数
-d 以守护程序(daemon)方式运行
-u 指定用户,如果当前为 root ,需要使用此参数指定用户
-m <num> 最大内存使用,单位MB。默认64MB
-M 禁止LRU策略,内存耗尽时返回错误,而不是删除项
-c <num> 最大同时连接数,默认是1024
-v verbose (print errors/warnings while in event loop)
-vv very verbose (also print client commands/reponses)
-vvv extremely verbose (also print internal state transitions)
-h 帮助信息
-i print memcached and libevent license
-P <file> 保存PID到指定文件
-f <factor> 增长因子,默认1.25
-n <bytes> 初始chunk=key+suffix+value+32结构体,默认48字节
-L 启用大内存页,可以降低内存浪费,改进性能
-t <num> 线程数,默认4。由于memcached采用NIO,所以更多线程没有太多作用
-R 每个event连接最大并发数,默认20
-C 禁用CAS命令(可以禁止版本计数,减少开销)
-b Set the backlog queue limit (default: 1024)
-B Binding protocol-one of ascii, binary or auto (default)
-I 调整分配slab页的大小,默认1M,最小1k到128M
启动方式
> /usr/local/memcached/bin/memcached -d -l 192.168.21.213 -p 11214 -u root -m 14000 -c 65535 -P /var/run/memcached-11214.pid
查看参数
先远程连接
> telnet 192.168.21.213 11212
Trying 192.168.21.213...
Connected to 192.168.21.213.
Escape character is '^]'.
stats setting
stats setting
STAT maxbytes 14680064000
STAT maxconns 65535
STAT tcpport 11211
STAT udpport 11211
STAT inter 192.168.21.213
STAT verbosity 0
STAT oldest 0
STAT evictions on
STAT domain_socket NULL
STAT umask 700
STAT growth_factor 1.25
STAT chunk_size 48
STAT num_threads 4
STAT num_threads_per_udp 4
STAT stat_key_prefix :
STAT detail_enabled no
STAT reqs_per_event 20
STAT cas_enabled yes
STAT tcp_backlog 1024
STAT binding_protocol auto-negotiate
STAT auth_enabled_sasl no
STAT item_size_max 1048576
STAT maxconns_fast no
STAT hashpower_init 0
STAT slab_reassign no
STAT slab_automove 0
STAT lru_crawler no
STAT lru_crawler_sleep 100
STAT lru_crawler_tocrawl 0
STAT tail_repair_time 0
STAT flush_enabled yes
STAT hash_algorithm jenkins
STAT lru_maintainer_thread no
STAT hot_lru_pct 32
STAT warm_lru_pct 32
STAT expirezero_does_not_evict no
END
理解memcached的内存存储机制
Memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。
Slab Allocator的基本原理是按照预先规定的大小,将分配的内存以page为单位,默认情况下一个page是1M,可以通过**-I参数**在启动时指定,分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合),如果需要申请内存时,memcached会划分出一个新的page并分配给需要的slab区域。page一旦被分配在重启前不会被回收或者重新分配,以解决内存碎片问题。
Page
分配给Slab的内存空间,默认是1MB。分配给Slab之后根据slab的大小切分成chunk。
Chunk
用于缓存记录的内存空间。
Slab Class
特定大小的chunk的组。
Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责一定范围内的数据存储。memcached根据收到的数据的大小,选择最适合数据大小的slab。memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk,然后将数据缓存于其中。
如图所示,每个slab只存储大于其上一个slab的size并小于或者等于自己最大size的数据。例如:100字节大小的字符串会被存到slab2(88-112)中,每个slab负责的空间是不等的,memcached默认情况下下一个slab的最大值为前一个的1.25倍,这个可以通过修改**-f参数**来修改增长比例。
Slab Allocator解决了当初的内存碎片问题,但新的机制也给memcached带来了新的问题。chunk是memcached实际存放缓存数据的地方,这个大小就是管理它的slab的最大存放大小。每个slab中的chunk大小是一样的,如上图所示slab1的chunk大小是88字节,slab2是112字节。由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。这里需要注意的是**chunk中不仅仅存放缓存对象的value,*而且保存了缓存对象的key,expire time, flag等详细信息。所以当set 1字节的item,需要远远大于1字节的空间存放。***
memcached在启动时指定 Growth Factor因子(通过-f选项), 就可以在某种程度上控制slab之间的差异。默认值为1.25。
slab的内存分配具体过程如下:
Memcached在启动时通过**-m参数**指定最大使用内存,但是这个不会一启动就占用完,而是逐步分配给各slab的。如果一个新的数据要被存放,首先选择一个合适的slab,然后查看该slab是否还有空闲的chunk,如果有则直接存放进去;如果没有则要进行申请,slab申请内存时以page为单位,无论大小为多少,都会有1M大小的page被分配给该slab(该page不会被回收或者重新分配,永远都属于该slab)。申请到page后,slab会将这个page的内存按chunk的大小进行切分,这样就变成了一个chunk的数组,再从这个chunk数组中选择一个用于存储数据。若没有空闲的page的时候,则会对改slab进行LRU,而不是对整个memcache进行LRU。
以上大致讲解了memcache的内存分配策略,下面来说明如何查看memcache的使用状况。
memcache状态和性能查看
命中率: stats命令
stats
STAT pid 26951
STAT uptime 9511337
STAT time 1586857744
STAT version 1.4.25
STAT libevent 2.0.21-stable
STAT pointer_size 64
STAT rusage_user 509603.291815
STAT rusage_system 994059.822978
STAT curr_connections 1685
STAT total_connections 353900
STAT connection_structures 3533
STAT reserved_fds 20
STAT cmd_get 44324121744
STAT cmd_set 4848030796
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 30099867188
STAT get_misses 14224254556
STAT delete_misses 9383198915
STAT delete_hits 3269
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 8094188476441
STAT bytes_written 51979086878431
STAT limit_maxbytes 14680064000
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT time_in_listen_disabled_us 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 24
STAT hash_bytes 134217728
STAT hash_is_expanding 0
STAT malloc_fails 0
STAT bytes 2927304884
STAT curr_items 13994142
STAT total_items 553063500
STAT expired_unfetched 2140005017
STAT evicted_unfetched 362000809
STAT evictions 451606766
STAT reclaimed 3388195726
STAT crawler_reclaimed 0
STAT crawler_items_checked 0
STAT lrutail_reflocked 11421
END
按照下面的图来解读分析
get_hits表示读取cache命中的次数,get_misses是读取失败的次数,即尝试读取不存在的缓存数据。即:
命中率=get_hits / (get_hits + get_misses)
命中率越高说明cache起到的缓存作用越大。但是在实际使用中,这个命中率不是有效数据的命中率,有些时候get操作可能只是检查一个key存在不存在,这个时候miss也是正确的,这个命中率是从memcached启动开始所有的请求的综合值,不能反映一个时间段内的情况,所以要排查memcached的性能问题,还需要更详细的数值。但是高的命中率还是能够反映出memcached良好的使用情况,突然下跌的命中率能够反映大量cache丢失的发生
各slab的items: Stats items命令
stats items
STAT items:1:number 9989523
STAT items:1:age 18000
STAT items:1:evicted 136697779
STAT items:1:evicted_nonzero 136697779
STAT items:1:evicted_time 0
STAT items:1:outofmemory 0
STAT items:1:tailrepairs 0
STAT items:1:reclaimed 2130217738
STAT items:1:expired_unfetched 1216182931
STAT items:1:evicted_unfetched 112241076
STAT items:1:crawler_reclaimed 0
STAT items:1:crawler_items_checked 0
STAT items:1:lrutail_reflocked 0
...
END
主要参数说明:
参数 | 描述 |
---|---|
outofmemory | slab class为新item分配空间失败的次数。这意味着你运行时带上了-M或者移除操作失败 |
number | 存放的数据总数 |
age | 存放的数据中存放时间最久的数据已经存在的时间,以秒为单位 |
evicted | 不得不从LRU中移除未过期item的次数 |
evicted_time | 自最后一次清除过期item起所经历的秒数,即最后被移除缓存的时间,0表示当前就有被移除,用这个来判断数据被移除的最近时间 |
evicted_nonzero | 没有设置过期时间(默认30天),但不得不从LRU中称除该未过期的item的次数 |
因为memcached的内存分配策略导致一旦memcached的总内存达到了设置的最大内存,表示所有的slab能够使用的page都已经固定,这时如果还有数据放入,将导致memcached使用LRU策略剔除数据。而LRU策略不是针对所有的slabs,而是只针对新数据应该被放入的slab,例如有一个新的数据要被放入slab 3,则LRU只对slab 3进行,通过stats items就可以观察到这些剔除的情况。
注意evicted_time:并不是发生了LRU就代表memcached负载过载了,因为有些时候在使用cache时会设置过期时间为0,这样缓存将被存放30天,如果内存满了还持续放入数据,而这些为过期的数据很久没有被使用,则可能被剔除。把evicted_time换算成标准时间看下是否已经达到了你可以接受的时间,例如:你认为数据被缓存了2天是你可以接受的,而最后被剔除的数据已经存放了3天以上,则可以认为这个slab的压力其实可以接受的;但是如果最后被剔除的数据只被缓存了20秒,不用考虑,这个slab已经负载过重了。
通过上面的说明可以看到当前的memcache的slab1的状态:
items有305816个,有效时间最久的是21529秒,通过LRU移除未过期的items有95336839个,通过LRU移除没有设置过期时间的未过期items有95312220个,当前就有被清除的items,启动时没有带-M参数。
各slabs的情况:stats slabs命令
从Stats items中如果发现有异常的slab,则可以通过stats slabs查看下该slab是不是内存分配的确有问题。
stats slabs
STAT 1:chunk_size 96
STAT 1:chunks_per_page 10922
STAT 1:total_pages 955
STAT 1:total_chunks 10430510
STAT 1:used_chunks 10019872
STAT 1:free_chunks 410638
STAT 1:free_chunks_end 0
STAT 1:mem_requested 863781455
STAT 1:get_hits 5698670344
STAT 1:cmd_set 2950430272
STAT 1:delete_hits 717
STAT 1:incr_hits 0
STAT 1:decr_hits 0
STAT 1:cas_hits 0
STAT 1:cas_badval 0
STAT 1:touch_hits 0
...
STAT active_slabs 28
STAT total_malloced 14682094688
END
主要参数说明:
参数 | 说明 |
---|---|
chunk_size | 当前slab每个chunk的大小 |
chunk_per_page | 每个page能够存放的chunk数 |
total_pages | 分配给当前slab的page总数,默认1个page大小1M,可以计算出该slab的大小 |
total_chunks | 当前slab最多能够存放的chunk数,应该等于chunck_per_page * total_page |
used_chunks | 已经被占用的chunks总数 |
free_chunks | 过期数据空出的chunk但还没有被使用的chunk数 |
free_chunks_end | 新分配的但是还没有被使用的chunk数 |
active_slabs | 活动的slab总数 |
total_malloced | 实际已经分配的总内存数,单位为byte,这个数值决定了memcached实际还能申请多少内存,如果这个值已经达到设定的上限(和stats settings中的maxbytes对比),则不会有新的page被分配。 |
这里需要注意:total_pages 这个是当前slab总共分配大的page总数,如果没有修改page的默认大小的情况下,这个数值就是当前slab能够缓存的数据的总大小(单位为M)。如果这个slab的剔除非常严重,一定要注意这个slab的page数是不是太少了。还有一个公式:
total_chunks = used_chunks + free_chunks + free_chunks_end
对象数量的统计:stats sizes
stats sizes
STAT 96 10029147
STAT 128 1423089
STAT 160 4146
STAT 192 1
STAT 224 1797
STAT 256 26754
STAT 288 163706
STAT 320 692487
STAT 352 83758
STAT 384 45550
STAT 416 56749
STAT 448 98446
STAT 480 112503
STAT 512 123638
STAT 544 322699
STAT 576 90973
STAT 608 97044
STAT 640 67397
STAT 672 64047
STAT 704 55648
STAT 736 37663
STAT 768 23013
STAT 800 13655
STAT 832 9818
STAT 864 8001
STAT 896 6978
STAT 928 6141
STAT 960 4638
STAT 992 4167
STAT 1024 4011
STAT 1056 6036
STAT 1088 5666
STAT 1120 4661
STAT 1152 5583
STAT 1184 5247
STAT 1216 5519
STAT 1248 5355
STAT 1280 5109
STAT 1312 7868
STAT 1344 4104
STAT 1376 13607
STAT 1408 5307
STAT 1440 11392
STAT 1472 7625
STAT 1504 4450
STAT 1536 4196
STAT 1568 13253
STAT 1600 3994
STAT 1632 62997
STAT 1664 15758
STAT 1696 23941
STAT 1728 5472
STAT 1760 8531
STAT 1792 6321
STAT 1824 38917
STAT 1856 10603
STAT 1888 3523
STAT 1920 3539
STAT 1952 5632
STAT 1984 5567
STAT 2016 7874
STAT 2048 4178
STAT 2080 6418
STAT 2112 5474
STAT 2144 3850
STAT 2176 3253
STAT 2208 1796
STAT 2240 5741
STAT 2272 6965
STAT 2304 1257
STAT 2336 1186
STAT 2368 815
STAT 2400 847
STAT 2432 327
STAT 2464 464
STAT 2496 987
STAT 2528 1056
STAT 2560 1033
STAT 2592 1181
STAT 2624 383
STAT 2656 294
STAT 2688 10554
STAT 2720 15836
STAT 2752 819
STAT 2784 378
STAT 2816 486
STAT 2848 300
STAT 2880 273
STAT 2912 234
STAT 2944 18
STAT 2976 54
STAT 3008 52
STAT 3040 113
STAT 3072 65
STAT 3104 8952
STAT 3136 36
STAT 3168 42
STAT 3200 12
STAT 3232 70
STAT 3264 163
STAT 3296 7
STAT 3328 27
STAT 3360 31
STAT 3392 69
STAT 3424 929
STAT 3456 138
STAT 3488 322
STAT 3520 135
STAT 3552 11
STAT 3584 566
STAT 3616 167
STAT 3648 712
STAT 3680 2711
STAT 3712 650
STAT 3744 171
STAT 3776 378
STAT 3808 396
STAT 3840 93
STAT 3872 103
STAT 3904 3795
STAT 3936 221
STAT 3968 171
STAT 4000 1618
STAT 4032 3554
STAT 4064 158
STAT 4096 21
STAT 4128 183
STAT 4160 606
STAT 4192 194
STAT 4224 643
STAT 4256 76
STAT 4288 128
STAT 4320 89
STAT 4352 178
STAT 4384 335
STAT 4416 238
STAT 4448 15
STAT 4480 267
STAT 4512 681
STAT 4544 20
STAT 4576 4
STAT 4608 3099
STAT 4640 49
STAT 4672 18
STAT 4704 36
STAT 4736 14
STAT 4768 26
STAT 4800 120
STAT 4832 163
STAT 4864 26
STAT 4896 16
STAT 4928 23
STAT 4960 190
STAT 4992 21
STAT 5024 46
STAT 5056 149
STAT 5088 30
STAT 5120 48
STAT 5152 9
STAT 5184 15
STAT 5216 8
STAT 5248 16
STAT 5280 79
STAT 5312 9
STAT 5344 38
STAT 5376 73
STAT 5408 121
STAT 5440 52
STAT 5472 135
STAT 5504 122
STAT 5536 25
STAT 5568 93
STAT 5600 10
STAT 5632 21
STAT 5664 52
STAT 5696 147
STAT 5728 49
STAT 5760 17
STAT 5792 13
STAT 5824 109
STAT 5856 94
STAT 5888 46
STAT 5920 40
STAT 5952 438
STAT 5984 87
STAT 6016 60
STAT 6048 66
STAT 6080 5
STAT 6112 28
STAT 6144 24
STAT 6176 2
STAT 6208 46
STAT 6240 5
STAT 6272 5
STAT 6304 10
STAT 6336 8
STAT 6368 9
STAT 6400 168
STAT 6432 1986
STAT 6464 2
STAT 6528 1
STAT 6560 1
STAT 6592 2
STAT 6624 2
STAT 6688 2
STAT 6720 516
STAT 6752 3
STAT 6848 1
STAT 6880 54
STAT 6912 5
STAT 7072 2
STAT 7104 112
STAT 7136 1
STAT 7168 1
STAT 7264 2
STAT 7392 1
STAT 7456 1
STAT 7488 107
STAT 7520 22
STAT 7552 6
STAT 7584 1
STAT 7680 7
STAT 7712 14
STAT 7904 362
STAT 7936 34
STAT 7968 13
STAT 8064 2
STAT 8096 1
STAT 8128 3
STAT 8160 3
STAT 8192 4
STAT 8224 6
STAT 8256 10
STAT 8288 3
STAT 8320 561
STAT 8352 301
STAT 8384 30
STAT 8416 6
STAT 8448 1
STAT 8480 4
STAT 8512 14
STAT 8544 8
STAT 8576 6
STAT 8608 9
STAT 8640 2
STAT 8672 2
STAT 8704 1
STAT 8736 1
STAT 8768 3
STAT 8800 4
STAT 8832 2
STAT 8864 1
STAT 8896 1
STAT 8928 1
STAT 9088 1
STAT 9568 2
STAT 10176 6
STAT 10240 213
STAT 10272 53
STAT 10304 3
STAT 10336 1
STAT 10368 5
STAT 10496 3
STAT 10528 1
STAT 10560 1
STAT 10592 1
STAT 11264 1200
STAT 12992 2
STAT 13056 1
STAT 14592 4
STAT 15904 4
STAT 16160 213
STAT 16192 2
STAT 17152 8
STAT 17184 1566
STAT 18144 1
STAT 18176 2
STAT 24896 1
STAT 24928 8
STAT 24960 6
STAT 24992 1
STAT 25216 1
STAT 25312 1
STAT 25568 1
STAT 25952 4
STAT 25984 15
STAT 27264 52
STAT 27296 51
STAT 27328 2
STAT 27360 6
STAT 27424 9
STAT 27456 18
STAT 27488 2
STAT 27520 9
STAT 27552 5
STAT 27584 6
STAT 27616 5
STAT 27648 2
STAT 27680 3
STAT 27712 3
STAT 27744 3
STAT 29504 145
STAT 29536 26
STAT 29568 9
STAT 29600 11
STAT 29632 1
STAT 29664 9
STAT 29696 16
STAT 29728 3
STAT 29760 8
STAT 29792 10
STAT 29824 7
STAT 29856 2
STAT 29888 2
STAT 29920 7
STAT 29952 5
STAT 29984 1
STAT 30016 2
STAT 30048 2
STAT 30080 1
STAT 30144 1
STAT 33792 1
STAT 33856 2
STAT 33888 1
STAT 33920 2
STAT 35456 7
STAT 35488 2
STAT 35520 1
STAT 35584 1
STAT 35712 3
STAT 35744 1
STAT 36064 1
STAT 36480 5
END
注意:该命令会锁定服务,暂停处理请求。该命令展示了固定chunk大小中的items的数量。也可以看出slab1(96byte)中有多少个chunks。