`
z7swf
  • 浏览: 186028 次
社区版块
存档分类
最新评论

memcached server LRU 深入分析

 
阅读更多

转自:http://www.iteye.com/topic/225692

 

Memcached,人所皆知的remote distribute cache(不知道的可以javaeye一下下,或者google一下下,或者baidu一下下,但是鉴于baidu的排名商业味道太浓(从最近得某某事 件可以看出),所以还是建议javaeye一下下),使用起来也非常的简单,它被用在了很多网站上面,几乎很少有大型的网站不会使用memcached。

曾经我也看过很多剖析memcached内部机制的文章,有一点收获,但是看过之后又忘记了,而且没有什么深刻的概念,但是最近我遇到一个问题,这个问题迫使我重新来认识memcache,下面我阐述一下我遇到的问题

问题:我有几千万的数据,这些数据会经常被用到,目前来看,它必须要放到memcached中,以保证访问速度,但是我的memcached中数据经常会 有丢失,而业务需求是memcached中的数据是不能丢失的。我的数据丢失的时候,memcached server的内存才使用到60%,也就是还有40%内存被严重的浪费掉了。但不是所有的应用都是这样,其他应用内存浪费的就比较少。为什么内存才使用到 60%的时候LRU就执行了呢(之所以确定是LRU执行是因为我发现我的数据丢失的总是前面放进去的,而且这个过程中,这些数据都没有被访问,比如第一次 访问的时候,只能访问第1000w条,而第300w条或者之前的数据都已经丢失了,从日志里看,第300w条肯定是放进去了)。

带着这些疑问,我开始重新审视memcached这个产品,首先从它的内存模型开始:我们知道c++里分配内存有两种方式,预先分配和动态分配,显然,预 先分配内存会使程序比较快,但是它的缺点是不能有效利用内存,而动态分配可以有效利用内存,但是会使程序运行效率下降,memcached的内存分配就是 基于以上原理,显然为了获得更快的速度,有时候我们不得不以空间换时间。

也就是说memcached会预先分配内存,对了,memcached分配内存方式称之为allocator,首先,这里有3个概念:
1 slab
2 page
3 chunk
解释一下,一般来说一个memcahced进程会预先将自己划分为若干个slab,每个slab下又有若干个page,每个page下又有多个 chunk,如果我们把这3个咚咚看作是object得话,这是两个一对多得关系。再一般来说,slab得数量是有限得,几个,十几个,或者几十个,这个 跟进程配置得内存有关。而每个slab下得page默认情况是1m,也就是说如果一个slab占用100m得内存得话,那么默认情况下这个slab所拥有 得page得个数就是100,而chunk就是我们得数据存放得最终地方。

举一个例子,我启动一个memcached进程,占用内存100m,再打开telnet,telnet localhost 11211,连接上memcache之后,输入stats  slabs,回车,出现如下数据:

Java代码  收藏代码
  1. STAT  1 :chunk_size  80   
  2. STAT 1 :chunks_per_page  13107   
  3. STAT 1 :total_pages  1   
  4. STAT 1 :total_chunks  13107   
  5. STAT 1 :used_chunks  13107   
  6. STAT 1 :free_chunks  0   
  7. STAT 1 :free_chunks_end  13107   
  8. STAT 2 :chunk_size  100   
  9. STAT 2 :chunks_per_page  10485   
  10. STAT 2 :total_pages  1   
  11. STAT 2 :total_chunks  10485   
  12. STAT 2 :used_chunks  10485   
  13. STAT 2 :free_chunks  0   
  14. STAT 2 :free_chunks_end  10485   
  15. STAT 3 :chunk_size  128   
  16. STAT 3 :chunks_per_page  8192   
  17. STAT 3 :total_pages  1   
  18. STAT 3 :total_chunks  8192   
  19. STAT 3 :used_chunks  8192   
  20. STAT 3 :free_chunks  0   
  21. STAT 3 :free_chunks_end  8192   
STAT 1:chunk_size 80
STAT 1:chunks_per_page 13107
STAT 1:total_pages 1
STAT 1:total_chunks 13107
STAT 1:used_chunks 13107
STAT 1:free_chunks 0
STAT 1:free_chunks_end 13107
STAT 2:chunk_size 100
STAT 2:chunks_per_page 10485
STAT 2:total_pages 1
STAT 2:total_chunks 10485
STAT 2:used_chunks 10485
STAT 2:free_chunks 0
STAT 2:free_chunks_end 10485
STAT 3:chunk_size 128
STAT 3:chunks_per_page 8192
STAT 3:total_pages 1
STAT 3:total_chunks 8192
STAT 3:used_chunks 8192
STAT 3:free_chunks 0
STAT 3:free_chunks_end 8192



以上就是前3个slab得详细信息
chunk_size表示数据存放块得大小,chunks_per_page表示一个内存页page中拥有得chunk得数 量,total_pages表示每个slab下page得个数。total_chunks表示这个slab下chunk得总数(=total_pages * chunks_per_page),used_chunks表示该slab下已经使用得chunk得数量,free_chunks表示该slab下还可以 使用得chunks数量。

从上面得示例slab 1一共有1m得内存空间,而且现在已经被用完了,slab2也有1m得内存空间,也被用完了,slab3得情况依然如此。 而且从这3个slab中chunk得size可以看出来,第一个chunk为80b,第二个是100b,第3个是128b,基本上后一个是前一个得 1.25倍,但是这个增长情况我们是可以控制得,我们可以通过在启动时得进程参数 –f来修改这个值,比如说 –f 1.1表示这个增长因子为1.1,那么第一个slab中得chunk为80b得话,第二个slab中得chunk应该是80*1.1左右。

解释了这么多也该可以看出来我遇到得问题得原因了,如果还看不出来,那我再补充关键的一句:memcached中新的value过来存放的地址是 该value的大小决定的,value总是会被选择存放到chunk与其最接近的一个slab中,比如上面的例子,如果我的value是80b,那么我这 所有的value总是会被存放到1号slab中,而1号slab中的free_chunks已经是0了,怎么办呢,如果你在启动memcached的时候 没有追加-M(禁止LRU,这种情况下内存不够时会out of memory),那么memcached会把这个slab中最近最少被使用的chunk中的数据清掉,然后放上最新的数据。这就解释了为什么我的内存还有 40%的时候LRU就执行了,因为我的其他slab中的chunk_size都远大于我的value,所以我的value根本不会放到那几个slab中, 而只会放到和我的value最接近的chunk所在的slab中(而这些slab早就满了,郁闷了)。这就导致了我的数据被不停的覆盖,后者覆盖前者。

问题找到了,解决方案还是没有找到,因为我的数据必须要求命中率时100%,我只能通过调整slab的增长因子和page的大小来尽量来使命中率 接近100%,但是并不能100%保证命中率是100%(这话怎么读起来这么别扭呢,自我检讨一下自己的语文水平),如果您说,这种方案不行啊,因为我的 memcached server不能停啊,不要紧还有另外一个方法,就是memcached-tool,执行move命令,如:move 3 1,代表把3号slab中的一个内存页移动到1号slab中,有人问了,这有什么用呢,比如说我的20号slab的利用率非常低,但是page却又很多, 比如200,那么就是200m,而2好slab经常发生LRU,明显page不够,我就可以move 20 2,把20号slab的一个内存页移动到2号slab上,这样就能更加有效的利用内存了(有人说了,一次只移动一个page,多麻烦啊?ahuaxuan 说,还是写个脚本,循环一下吧)。

有人说不行啊,我的memcache中的数据不能丢失啊,ok,试试新浪的memcachedb吧,虽然我没有用过,但是建议大家可以试试,它也使利用 memcache协议和berkeleyDB做的(写到这里,我不得不佩服danga了,我觉得它最大的贡献不是memcache server本身,而是memcache协议),据说它被用在新浪的不少应用上,包括新浪的博客。

补充,stats slab命令可以查看memcached中slab的情况,而stats命令可以查看你的memcached的一些健康情况,比如说命中率之类的,示例如下:

Java代码  收藏代码
  1. STAT pid  2232   
  2. STAT uptime 1348   
  3. STAT time 1218120955   
  4. STAT version 1.2 . 1   
  5. STAT pointer_size 32   
  6. STAT curr_items 0   
  7. STAT total_items 0   
  8. STAT bytes 0   
  9. STAT curr_connections 1   
  10. STAT total_connections 3   
  11. STAT connection_structures 2   
  12. STAT cmd_get 0   
  13. STAT cmd_set 0   
  14. STAT get_hits 0   
  15. STAT get_misses 0   
  16. STAT bytes_read 26   
  17. STAT bytes_written 16655   
  18. STAT limit_maxbytes 104857600   
STAT pid 2232
STAT uptime 1348
STAT time 1218120955
STAT version 1.2.1
STAT pointer_size 32
STAT curr_items 0
STAT total_items 0
STAT bytes 0
STAT curr_connections 1
STAT total_connections 3
STAT connection_structures 2
STAT cmd_get 0
STAT cmd_set 0
STAT get_hits 0
STAT get_misses 0
STAT bytes_read 26
STAT bytes_written 16655
STAT limit_maxbytes 104857600


从上面的数据可以看到这个memcached进程的命中率很好,get_misses低达0个,怎么回事啊,因为这个进程使我刚启动的,我只用 telnet连了一下,所以curr_connections为1,而total_items为0,因为我没有放数据进去,get_hits为0,因为我 没有调用get方法,最后的结果就是misses当然为0,哇哦,换句话说命中率就是100%,又yy了。

该到总结的时候了,从这篇文章里我们可以得到以下几个结论:
结论一,memcached得LRU不是全局的,而是针对slab的,可以说是区域性的。
结论二,要提高memcached的命中率,预估我们的value大小并且适当的调整内存页大小和增长因子是必须的。
结论三,带着问题找答案理解的要比随便看看的效果好得多。

分享到:
评论

相关推荐

    memcached server

    标题提到的"memcached server"指的是这个服务端程序,用于在多台服务器之间共享数据,通过缓存常用数据来提升整体性能。版本1.2.6是其历史的一个稳定版本,尽管现在已经有了更新的版本,但这个版本依然具有一定的...

    memcached32位&64位

    sc delete "Memcached Server" memcached的基本设置: -p 监听的端口 -l 连接的IP地址, 默认是本机 -d start 启动memcached服务 -d restart 重起memcached服务 -d stop|shutdown 关闭正在运行的memcached服务 -d ...

    Memcached服务器(windows版本和Windows server版本)

    - **LRU(Least Recently Used)**: 当内存空间不足时,Memcached会采用LRU策略,优先淘汰最近最少使用的数据。 ### 5. 安全性与性能优化 - **安全性**: 默认情况下,Memcached不提供任何安全机制,所有数据都是...

    mon-cache:mongoose 缓存到 redis、memcached 或 lru-cache

    mon-cache 是 mongoose 缓存到 redis、memcached 或 lru-cache。 这利用了 npm 模块缓存客户端。 初始化 lru缓存 options = { store : "memory" } ; require ( 'mon-cache' ) ( mongoose , options ) ; Redis ...

    LinQ to Memcached with SQL Server Change Tracking

    1.Memcached 安装、部署、Demo程序 ...5.SQL Server Change Tracking集成Memcached 6.项目应用(IM基础数据缓存,例:Category、Brand、Manufacturer等) 7.了解Memcached实现机制,数据模型并做培训

    memcached源代码分析

    4. **LRU(Least Recently Used)策略**:当内存空间不足时,memcached会使用LRU策略淘汰最近最少使用的item,以腾出空间给新的请求。 5. **线程模型**:memcached采用单线程模型,通过非阻塞I/O和事件驱动模型来...

    Memcached1.4.13 For Windows 32/64

    sc delete "Memcached Server" memcached的基本设置: -p 监听的端口 -l 连接的IP地址, 默认是本机 -d start 启动memcached服务 -d restart 重起memcached服务 -d stop|shutdown 关闭正在运行的memcached服务 -d ...

    Memcached内存分析、调优、集群

    ### Memcached内存分析、调优、集群:深入理解与实践 #### 1. Memcached背景与概述 Memcached是一款高性能的分布式内存缓存服务器,它最初由LiveJournal的运营人员开发,现已成为开源社区中不可或缺的一部分。其...

    Memcached 1.4.13(Windows 32/64)最新稳定版

    sc delete "Memcached Server" memcached的基本设置: -p 监听的端口 -l 连接的IP地址, 默认是本机 -d start 启动memcached服务 -d restart 重起memcached服务 -d stop|shutdown 关闭正在运行的memcached服务 ...

    memcached全面剖析.pdf

    - **LRU(Least Recently Used)机制**: 当内存不足时,memcached采用LRU算法自动删除最少最近使用的数据项。 #### memcached的发展方向 - **二进制协议**: 新版本的memcached支持更高效的二进制协议,可以提高...

    Memcached 内存分析、调优、集群

    ### Memcached内存分析、调优、集群 #### 1. Memcached背景 Memcached是一款高性能的分布式内存对象缓存系统,旨在通过减轻数据库负载来加速动态Web应用的响应速度。它通过在内存中缓存数据和对象来减少读取数据库...

    windwos server memcached

    **Windows Server 上的 Memcached 安装与使用详解** Memcached 是一款高性能、分布式内存对象缓存系统,常用于减轻数据库负载,提升Web应用的性能。在Windows Server环境下,我们同样可以利用Memcached来实现数据...

    memcached安装及java应用使用memcached

    - **缓存策略**:如LRU(最近最少使用)或LFU(最不经常使用)的实现。 - **分片和负载均衡**:在多台服务器上部署memcached,以提高可扩展性。 7. **异常处理**:处理连接错误、超时等问题的方法。 8. **性能...

    Memcached完全剖析(转)

    当内存不足时,Memcached会使用LRU(Least Recently Used)策略进行数据淘汰,优先移除最近最少使用的数据。 **二、主要特性** 1. **分布式**: Memcached 不依赖于特定的硬件或软件环境,它可以根据服务器集群的IP...

    神级memcached源代码分析文档_1.4.0代码分析

    总结,通过深入分析Memcached的源代码,我们可以了解到其高效运行背后的设计思想和技术实现,这对于优化缓存性能、解决实际问题以及理解分布式系统有着极大的帮助。对于开发者而言,这是一份宝贵的参考资料,能...

    memcached分析-main

    通过对memcached的线程模型和网络事件处理的分析,我们可以看到其高效的设计:主线程与工作线程的分离,确保了连接建立的快速响应和连接处理的并发性。libevent的事件驱动模型,则使得memcached能够灵活、高效地处理...

    memcached服务器端memcached.exe 下载

    4. **缓存策略**:支持LRU(Least Recently Used)最近最少使用算法,当内存满时自动淘汰较旧的数据。 5. **持久化**:虽然默认不支持数据持久化,但可以通过第三方工具或插件实现数据备份和恢复。 在实际应用中,...

    缓存服务器memcached下载

    3. **空间管理**:Memcached采用LRU(Least Recently Used)策略来处理内存满的情况,即最近最少使用的数据会被优先淘汰。 **三、Memcached的安装与配置** 在多数操作系统上,可以通过包管理器安装Memcached,例如...

Global site tag (gtag.js) - Google Analytics