Memcached深入分析及内存调优

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

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

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

  1. [email protected]:~$ 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. [email protected]:~$ memcached -d -m256 -p11211 -u liyd -vv
  2. [email protected]:~$ 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的删除机制]。

原文地址:https://www.cnblogs.com/chenrenshui/p/9245911.html

时间: 2024-10-29 08:43:14

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

tomcat完结篇,JVM状态监控与内存调优。

本篇合适对tomcat和JVM有一定了解的朋友. 常用的内置变量介绍: CATALINA_BASE  //用于设定可以具有写权限或者自定义部分的文件存放位置,适用场景,需要在一节点上启动多个tomcat实例,就可以定义多个CATALINA_BASE. CATALINA_OPTS //定义JVM的运行属性 JAVA_OPTS  //定义多个JVM相同运行属性. JAVA_HOME  //用于设定java或JDK运行时候的本地位置. JRE_HOME   //这是一个JAVA_HOME的别名. 了解

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

转自:http://blog.csdn.net/cutesource/article/details/5907418 版权声明:本文为博主原创文章,未经博主允许不得转载. 首先需要注意的是在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM. 对JVM内存的系统级的调优主要的目的是减少GC的频率和Fu

Spark Memory Tuning (内存调优)

调整 Spark 应用程序的内存使用情况和 GC behavior 已经有很多的讨论在 Tuning Guide 中.我们强烈建议您阅读一下.在本节中, 我们将在 Spark Streaming applications 的上下文中讨论一些 tuning parameters (调优参数). Spark Streaming application 所需的集群内存量在很大程度上取决于所使用的 transformations 类型.例如, 如果要在最近 10 分钟的数据中使用 window oper

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

一.前述 Spark中调优大致分为以下几种 ,代码调优,数据本地化,内存调优,SparkShuffle调优,调节Executor的堆外内存. 二.具体    1.代码调优 1.避免创建重复的RDD,尽量使用同一个RDD 2.对多次使用的RDD进行持久化 如何选择一种最合适的持久化策略? 默认情况下,性能最高的当然是MEMORY_ONLY,但前提是你的内存必须足够足够大,可以绰绰有余地存放下整个RDD的所有数据.因为不进行序列化与反序列化操作,就避免了这部分的性能开销:对这个RDD的后续算子操作,

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

JVM实用参数(四)内存调优 原文地址,译文地址,作者:PATRICK PESCHLOW,译者:郑旭东  校对:梁海舰 理想的情况下,一个Java程序使用JVM的默认设置也可以运行得很好,所以一般来说,没有必要设置任何JVM参数.然而,由于一些性能问题(很不幸的是,这些问题经常出现),一些相关的JVM参数知识会是我们工作中得好伙伴.在这篇文章中,我们将介绍一些关于JVM内存管理的参数.知道并理解这些参数,将对开发者和运维人员很有帮助. 所有已制定的HotSpot内存管理和垃圾回收算法都基于一个相

JVM内存调优

JVM的常见配置汇总 堆设置: -Xms:初始堆大小  一般设置为小于4G -Xmx:最大堆大小  一般设置为小于4G 一般-Xms与Xmx的值相等,避免每次垃圾回收完成后JVM重新分配内存 -XX:NewSize=n 设置年轻代大小 -XX:NewRatio=n 设置年轻代和年老代的比值 如果设置了-XX:NewSize,那么久不在设置-XX:NewRatio 收集器的设置 -XX:+UseParallelGC:设置并行收集器 -XX:+UseConcMarkSweepGX:设置并发收集器 垃

【转】jvm 内存模型及内存调优

一,JVM内存模型概括 还有一个寄存器,线程运行于其上面 1.程序计数器 记录线程的执行位置,线程私有内存,唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域 2.线程栈(VM stack) 栈的默认大小是1M -Xss2m 这样设置成2M 异常 :Fatal: Stack size too small 异常的引起一般是线程数目太多 3.本地方法栈(native stack) 即为一些Native方法分配的stack 异常:java.lang.OutOfMemo

MySQL内存调优

原文链接: MySQL Memory Allocation -- by Rick James原文日期: Created 2010; Refreshed Oct, 2012, Jan, 2014 翻译人员: 铁锚翻译日期: 2014年5月28日 MySQL 内存分配-- 高速设置方案假设仅使用MyISAM存储引擎,设置 key_buffer_size为可用内存的20%,(再加上设置 innodb_buffer_pool_size = 0 ) 假设仅使用InnoDB存储引擎,设置 innodb_bu

JVM-常用内存调优参数总结

一.内存调整参数 -Xmx2g    设置堆内存最大值为2g -Xmx512m  设置堆内存最大值为512m -Xms1g   设置堆内存最小值1g -Xmn  设置堆新生代的大小,例如:-Xmn512m -XX:PermSize  设置Perm Generation的最小值,例如:-XX:PermSize=32m -XX:MaxPermSize  设置Perm Generation的最大值,例如:-XX:MaxPermSize=64m -Xss  设置线程栈的大小,例如: -Xss128k -