到这里memcached的初步使用我们已经没问题了,但是了解一些它内部的机制还是十分必要的,这直接涉及到你能否把memcached给真正“用好”。

Memcached的守护进程机制使用的是Unix下的daemon,Socket则使用了非阻塞(non-blocked)高性能的NIO,事件处理上大家都已经知道了,是基于libevent,支持异步的事件处理。

最主要的是要知道它的内存管理机制,使用如下命令启动memcached:

  1. liyd@ubuntu:~$ memcached -d -m256 -p11211 -u liyd

这里我们分配了256M的内存给memcached,那么memcached又是怎么样来分配内存的呢?先看下图:

Memcached在分配内存时是以Page为单位的,默认情况下一个Page是1M,内部是一个个chunk,当chunk的大小等于Page大小时也就是Memcached所能存储的最大数据大小了,可以在启动时通过-l来指定它,最大可以支持128M。

Memcached并不是将所有大小的数据都存放在一起的,而是将内存空间划分为一个个的slab,每个slab只负责一定范围内的数据。上图中,slab1只负责96bytes的数据,slab2负责120bytes的数据。

在存储数据时,如果这个item对应的slab还没有创建则申请一个page的内存,将这个page按照所在slab中chunk的大小进行分割,然后将item存入。

如果已经创建存在了,判断对应的slab是否用完,没用完直接存储。

如果对应的slab已经用完了,看内存是否用完,没用完会申请一个新的page进行分割存储,用完了则直接进行LRU。

那么我们怎么样来查看各个slab的状况及里面的chunk大小呢?

在前面的启动参数中我们发现有-v –vv -vvv三个选项,一般我们用的最多的是-vv:

  1. liyd@ubuntu:~$ memcached -d -m256 -p11211 -u liyd -vv
  2. liyd@ubuntu:~$ slab class 1: chunk size 96 perslab 10922
  3. slab class 2: chunk size 120 perslab 8738
  4. slab class 3: chunk size 152 perslab 6898
  5. slab class 4: chunk size 192 perslab 5461
  6. slab class 5: chunk size 240 perslab 4369
  7. slab class 6: chunk size 304 perslab 3449
  8. slab class 7: chunk size 384 perslab 2730
  9. slab class 8: chunk size 480 perslab 2184
  10. slab class 9: chunk size 600 perslab 1747
  11. slab class 10: chunk size 752 perslab 1394
  12. slab class 11: chunk size 944 perslab 1110
  13. slab class 12: chunk size 1184 perslab 885
  14. slab class 13: chunk size 1480 perslab 708
  15. slab class 14: chunk size 1856 perslab 564
  16. slab class 15: chunk size 2320 perslab 451
  17. slab class 16: chunk size 2904 perslab 361
  18. slab class 17: chunk size 3632 perslab 288
  19. slab class 18: chunk size 4544 perslab 230
  20. slab class 19: chunk size 5680 perslab 184
  21. slab class 20: chunk size 7104 perslab 147
  22. slab class 21: chunk size 8880 perslab 118
  23. slab class 22: chunk size 11104 perslab 94
  24. slab class 23: chunk size 13880 perslab 75
  25. slab class 24: chunk size 17352 perslab 60
  26. slab class 25: chunk size 21696 perslab 48
  27. slab class 26: chunk size 27120 perslab 38
  28. slab class 27: chunk size 33904 perslab 30
  29. slab class 28: chunk size 42384 perslab 24
  30. slab class 29: chunk size 52984 perslab 19
  31. slab class 30: chunk size 66232 perslab 15
  32. slab class 31: chunk size 82792 perslab 12
  33. slab class 32: chunk size 103496 perslab 10
  34. slab class 33: chunk size 129376 perslab 8
  35. slab class 34: chunk size 161720 perslab 6
  36. slab class 35: chunk size 202152 perslab 5
  37. slab class 36: chunk size 252696 perslab 4
  38. slab class 37: chunk size 315872 perslab 3
  39. slab class 38: chunk size 394840 perslab 2
  40. slab class 39: chunk size 493552 perslab 2
  41. slab class 40: chunk size 616944 perslab 1
  42. slab class 41: chunk size 771184 perslab 1
  43. slab class 42: chunk size 1048576 perslab 1
  44. <26 server listening (auto-negotiate)
  45. <27 send buffer was 212992, now 268435456
  46. <28 send buffer was 212992, now 268435456
  47. <27 server listening (udp)
  48. <28 server listening (udp)
  49. <27 server listening (udp)
  50. <28 server listening (udp)
  51. <27 server listening (udp)
  52. <28 server listening (udp)
  53. <27 server listening (udp)
  54. <28 server listening (udp)

我们看到,一共有42个slab,第一个slab中chunk大小为96bytes,第二个为120bytes,第三个为152bytes,每个slab中chunk的大小都不一样,这个chunk就是memcached具体存储数据的地方。

Memcached通过指定的成长因子(-f指定,默认1.25倍)来决定每个slab中chunk增长的范围,第一个slab的大小可以通过-n来设定。

当数据进来时Memcached会选择一个大于等于最接近的slab来进行存储。例如当item大小为95时将存储到chunk为96bytes的slab1,item大小为97时则会存储到chunk大小为120的slab2.

这样分配的好处是速度快,避免大量重复的初始化和清理操作,有效的避免了内存碎片的问题,但内存利用率上会有所浪费。

另外Memcached是懒检测机制,当存储在内存中的对象过期甚至是flush_all时,它并不会做检查或删除操作,只有在get时才检查数据对象是否应该删除。

删除数据时,Memcached同样是懒删除机制,只在对应的数据对象上做删除标识并不回收内存,在下次分配时直接覆盖使用。

了解了Memcached的内存分配机制,如何进行调优是不是自然而然的就明白了?

应该尽量的根据实际情况来设定slab的chunk的初始大小和增长因子,尽量减少内存的浪费。在某些情况下数据的长度都会集中在一个区域,如session。甚至会有定长的情况,如数据统计等。

还有一个重要调优的地方就是提高缓存命中率了,这个没有固定的方法,还得具体场景做具体业务分析,需要注意的就是,Memcached中LRU的操作是基于slab而非全局,分析时最好考虑这一点,这也就是有时候内存还没用完但数据却被回收了的原因。

我们也可以借助类似memcached-tool这类对memcache的状态性能分析工具来更直观的查看memcache内部的状态,但是功能上也比较有限,就不细讲了,主要就是以下几个命令:

  1. #memcached-tool
  2. #Usage: memcached-tool <host[:port]> [mode]
  3. memcached-tool 127.0.0.1:11211 display # shows slabs
  4. memcached-tool 127.0.0.1:11211 # same. (default is display)
  5. memcached-tool 127.0.0.1:11211 stats # shows general stats
  6. memcached-tool 127.0.0.1:11211 dump # dumps keys and value

现在我们再回过头去看Memcached的stats命令,是不是就很有用了?这里贴上常用的一些参数说明。

stats统计项:

  1. pid Memcached进程ID
  2. uptime Memcached运行时间,单位:秒
  3. time Memcached当前的UNIX时间
  4. version Memcached的版本号
  5. rusage_user 该进程累计的用户时间,单位:秒
  6. rusage_system 该进程累计的系统时间,单位:秒
  7. curr_connections 当前连接数量
  8. total_connections Memcached运行以来接受的连接总数
  9. connection_structures Memcached分配的连接结构的数量
  10. cmd_get 查询请求总数
  11. get_hits 查询成功获取数据的总次数
  12. get_misses 查询成功未获取到数据的总次数
  13. cmd_set 存储(添加/更新)请求总数
  14. bytes Memcached当前存储内容所占用字节数
  15. bytes_read Memcached从网络读取到的总字节数
  16. bytes_written Memcached向网络发送的总字节数
  17. limit_maxbytes Memcached在存储时被允许使用的字节总数
  18. curr_items Memcached当前存储的内容数量
  19. total_items Memcached启动以来存储过的内容总数
  20. evictions LRU释放对象数,用来释放内存

stats slabs区块统计:

  1. chunk_size chunk大小,byte
  2. chunks_per_page 每个page的chunk数量
  3. total_pages page数量
  4. total_chunks chunk数量*page数量
  5. get_hits get命中数
  6. cmd_set set数
  7. delete_hits delete命中数
  8. incr_hits incr命中数
  9. decr_hits decr命中数
  10. cas_hits cas命中数
  11. cas_badval cas数据类型错误数
  12. used_chunks 已被分配的chunk数
  13. free_chunks 剩余chunk数
  14. free_chunks_end 分完page浪费chunk数
  15. mem_requested 请求存储的字节数
  16. active_slabs slab数量
  17. total_malloced 总内存数量

被浪费内存数=(total_chunks * chunk_size) - mem_requested,如果太大,则需要调整factor

stats items数据项统计:

  1. number 该slab中对象数,不包含过期对象
  2. age LRU队列中最老对象的过期时间
  3. evicted LRU释放对象数
  4. evicted_nonzero 设置了非0时间的LRU释放对象数
  5. evicted_time 最后一次LRU秒数,监控频率
  6. outofmemory 不能存储对象次数,使用-M会报错
  7. tailrepairs 修复slabs次数
  8. reclaimed 使用过期对象空间存储对象次数

stats settings查看设置:

  1. maxbytes 最大字节数限制,0无限制
  2. maxconns 允许最大连接数
  3. tcpport TCP端口
  4. udpport UDP端口
  5. verbosity 日志0=none,1=som,2=lots
  6. oldest 最老对象过期时间
  7. evictions on/off,是否禁用LRU
  8. domain_socket socket的domain
  9. umask 创建Socket时的umask
  10. growth_factor 增长因子
  11. chunk_size key+value+flags大小
  12. num_threads 线程数,可以通过-t设置,默认4
  13. stat_key_prefix stats分隔符
  14. detail_enabled yes/no,显示stats细节信息
  15. reqs_per_event 最大IO吞吐量(每event)
  16. cas_enabled yes/no,是否启用CAS,-C禁用
  17. tcp_backlog TCP监控日志
  18. auth_enabled_sasl yes/no,是否启用SASL验证

查看key和value

1. cmd上登录memcache

telnet 127.0.0.1 11211

退出 quit

2. 列出所有keys

stats items

3. 通过itemid获取key

接下来基于列出的items id,本例中为7,第2个参数为列出的长度,0为全部列出

 stats cachedump 7 0

4. 通过get获取key值

上面的stats cachedump命令列出了我的session key,接下来就用get命令查找对应的session值

get Sess_sidsvpc1473t1np08qnkvhf6j2

注意:如果有 100byte 的数据,但122byte大小的仓库中的chunk满了;
此时会把122byte仓库的旧数据剔除掉,然后存储[Memcachedd的删除机制]。

Memcached深入分析及内存调优的更多相关文章

  1. JVM实用参数(四)内存调优

    理想的情况下,一个Java程序使用JVM的默认设置也可以运行得很好,所以一般来说,没有必要设置任何JVM参数.然而,由于一些性能问题(很不幸的是,这些问题经常出现),一些相关的JVM参数知识会是我们工 ...

  2. JVM学习笔记(四)------内存调优【转】

    转自:http://blog.csdn.net/cutesource/article/details/5907418 版权声明:本文为博主原创文章,未经博主允许不得转载. 首先需要注意的是在对JVM内 ...

  3. [hadoop] 集群启动和内存调优

    1.启动Hadoop集群 #首先查看下zoo.cfg里面配置的server.id和集群主机的id是否一致 #如果不一致会造成yarn控制不了从节点的启动 cat /home/hadoop/zookee ...

  4. JVM学习笔记(四)------内存调优

    首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提 ...

  5. 【Spark篇】---Spark调优之代码调优,数据本地化调优,内存调优,SparkShuffle调优,Executor的堆外内存调优

    一.前述 Spark中调优大致分为以下几种 ,代码调优,数据本地化,内存调优,SparkShuffle调优,调节Executor的堆外内存. 二.具体    1.代码调优 1.避免创建重复的RDD,尽 ...

  6. 我进行jvm内存调优的一些记录

    jvm内存调优的一些记录 java内存调优的方法和过程 可以使用 jmap -heap pid号 查看,例如pid是9300,执行的结果可能是这样的. root@ubuntu:~# jmap -hea ...

  7. JVM、垃圾回收、内存调优、常见參数

    一.什么是JVM JVM是Java Virtual Machine(Java虚拟机)的缩写.JVM是一种用于计算设备的规范.它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现 ...

  8. MapReduce内存调优

    内存调优 Hadoop处理数据时,出现内存溢出的处理方法?(内存调优) 1.Mapper/Reducer阶段JVM内存溢出(一般都是堆) 1)JVM堆(Heap)内存溢出:堆内存不足时,一般会抛出如下 ...

  9. JVM内存调优原则及几种JVM内存调优方法

      转载,如需帮助,请联系wlgchun@163.com https://blog.csdn.net/LeegooWang/article/details/88696195 如何对JVM进行内存调优? ...

随机推荐

  1. XSS 防范XSS 攻击的措施

    XssSniper--0KEE TEAM               XssSniper--0KEE TEAM XssSniper 扩展介绍 一直以来,隐式输出的DomXSS漏洞难以被传统的扫描工具发 ...

  2. pandas介绍及环境部署

    pandas介绍 Python Data Analysis Library 或 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的.Pandas 纳入了大量库和一些标准的 ...

  3. pyqt5 主界面打开新主界面、打开Dialog、打开提示框的实现模板

    import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import * ###### ...

  4. 匿名内部类的参数引用只能是final,可能遇到的问题及其解决

    这个是我碰到比较多次的问题,一开始是不解,不过查了下大家都觉得没什么,而且只是加个final好像影响也不大,于是我就直接加个final了事,之后也不管了 直到昨天: 遇到了这个宿命般的问题 难道解决方 ...

  5. Python第三方库官网

    Python第三方库官网 https://pypi.python.org/pypi 包下载后的处理: 下载后放到Python的scripts文件夹中(D:\Python3.5\Scripts),用cm ...

  6. requests库的get请求(加上head,加上get参数请求)

    #coding:utf-8 # 导入requests import requests # 构建url url = 'http://www.baidu.com' # 发送请求,获取响应 # respon ...

  7. 怎样解决VMware虚拟机无法连接外网问题

    安装上虚拟机之后,再安装上linux之后,有时会出现ping不通物理机的ip和任何外网包括网关的ip的问题.虚拟机的网卡是桥接状态.下面就让我为大家演示下一下,怎么让虚拟机重新ping通物理机. 工具 ...

  8. 十天精通CSS3(8)

    变形--旋转 rotate() 旋转rotate()函数通过指定的角度参数使元素相对原点进行旋转.它主要在二维空间内进行操作,设置一个角度值,用来指定旋转的幅度.如果这个值为正值,元素相对原点中心顺时 ...

  9. ev3_basic——HITCON CTF 2018

    [MISC] EN-US This challenge provides a jpg file and a pklg file. The jpg is shown a part of string o ...

  10. linux mail 发送邮件附件

    在很多场景中我们会使用Shell命令来发送邮件,而且我们还可能在邮件里面添加附件,本文将介绍使用Shell命令发送带附件邮件的几种方式,希望对大家有所帮助. 文章目录 1 使用mail命令 2 使用m ...