Memcached工作原理

字数 1912阅读 3129

Memcached工作原理

@[memcached]

[toc]

1. Memcached软件工作原理

  • memcached是一套C/S模式架构的软件,在服务器端启动服务守护进程,可以为memcached服务器指定监听的IP地址、端口号、并发访问连接数、以及分配多少内存来处理客户端的请求的参数;

  • memcached软件是由C语言来实现的,全部代码仅有2000多行,采用的是异步I/O,其实现方式是基于事件的单进程和单线程的。使用libevent作为事件通知机制,多个服务器端可以协同工作,但这些服务器端之间是没有任何通信联系的,每个服务器只对自己的数据进行管理。应用程序端通过指定缓存服务器的IP地址和端口,就可以连接memcached服务进行相互通信。

  • 需要被缓存的数据以Key/Value键值对的形式保存在服务器端预分配的内存空间中,每个被缓存的数据都有唯一的标识Key,操作memcached中的数据是通过这个唯一标识Key进行的。缓存到Memcached中的数据仅放置在memcached服务预分配的内存中,而非储存在磁盘中,因此存取速度非常快;

  • 由于Memcached服务自身没有对缓存的数据进行持久性存储的设计,因此,在服务器端的memcached服务进程重启之后,存储在内存中的这些数据就会丢失。且当内存中缓存的数据容量达到启动时设定的内存值时,就自动使用LRU(最近最少使用算法)算法删除过期的缓存数据。

  • memcached软件开发的早,当初仅为缓存而设计的,因此在设计之初并没有过多考虑数据的永久性问题。因此如果使用memcached作为缓存数据服务,要考虑数据丢失后带来的问题,例如:是否可以重新生成数据,还有,在高并发场合数据丢失会不会导致网站架构雪崩。

  • 为了满足数据可以持久性保留的需求,sina网基于memcached服务开发了一款NoSQL软件,名字叫MemcacheDB,可以实现在缓存的基础上增加了持久缓存的特性。

  • memcached支持各种语言编写的客户端API,包括PHP 、PYthon、Java、C等;

2. memcached的特性

memcached作为高并发、高性能的缓存服务,具有如下特征:

  • 协议简单
    memcached的协议实现比较简单,使用的是基于文本行的协议,能通过telnet直接操作memcached服务存取数据;

  • 基于libevent的事件处理
    简单的说,libevent是一套得C开发的程序库,它将BSD系统的kqueue、Linux系统的epoll等事件处理功能封装成一个接口,确保即使服务器端连接数增加,也能发挥很好的性能;
    memcached就是利用这个库进行异步事件处理。

  • 内置的内存管理方式
    memcached有一套自己管理内存的方式,这套管理方式非常高效,所有的数据都保存在memcached内置的内存中,当存入的数据占满内存空间时,memcached就使用LRU算法自动删除不使用的缓存,即重用过期数据的内存空间。memcached是为缓存系统设计的,因此,没有考虑数据的容灾问题,和机器的内存一样,重启机器后数据将会丢失,如果希望重启数据依然能保留,那么就需要采用sina网开发的memcachedb持久性内存缓存系统,当然还有常见的NoSQL服务,如:Redis,内存缓存:memcached,memcachedb,TokyoTyrant,MongoDB,Cassandra,redis,tair,CouchDB
    linux运维人员必会开源运维工具体系:http://oldboy.blog.51cto.com/2561410/775056

  • 互不通信的memcached服务之间具有分布式特征
    各个memcached服务器之间互相不通信,都是独立的存取数据,不共享任何信息。通过对客户端的设计,让Memcached具有分布式功能,能支持海量缓存和大规模应用。

3. Memcached内存管理机制

  • Memcached利用Slab Allocation机制来分配和管理内存。传统的内存管理方式是:使用完通过malloc分配的内存后通过free来回收内存。这种方式容易产生内存碎片并降低操作系统对内存的管理效率。Slab Allocation机制不存在这样的问题。它按照预先分配的大小,将分配的内存分割成特定长度的内存块,再把尺寸相同的内存块分成组,这些内存块不会释放,可以重复利用。

  • Memcached服务器端保存着一个空闲的内存块列表,当有数据存入时根据接收到的数据大小,分配一个能存下这个数据的最小内存块。这种方式有时会造成内存浪费,例如:将200字节的一个数据存入300字节的一个内存块中,就会有100字节的内存被浪费掉,不能被使用。

避免浪费内存的办法是:

  1. 预先计算出应用存入的数据大小,或把同一业务类型的数据存入一个Memcached服务器中,确保存入的数据大小相对均匀,这样就可以减少内存的浪费。

  2. 还有一种办法是,在memcached服务启动时,通过“ -f ” 选项指定一个增长因子(或叫增长系数),它能控制内存组(slab)之间的大小差异。在应用中使用Memcached时,通常可以不重新设置这个参数,使用默认值1.25进行部署。如果想优化memcached对内存的使用,可以考虑重新计算数据的预期平均长度,调整这个参数来获得合适的设置值。

4. Memcached 的删除机制

  • 前面已经介绍过Memcached不会释放已分配的内存空间,在数据过期后,客户端不能通过Key取出它的值,其存储空间被重新利用。

  • Memcached使用的是一种Lazy Expiration 策略,自己不会监控存入的“Key/Value”对是否过期,而是在获取Key值时查看记录的时间戳,检查“key/value”键值对的空间是否过期。这种策略不会在过期检测上浪费CPU资源。

  • Memcached在分配空间时,优先使用已经过期的Key/Value键值对空间,当分配的内存空间占满时,Memcached就会使用LRU(最近最少使用算法)算法来分配空间,删除最近最少使用的Key/Value键值对,将其空间分配给新Key/Value键值对。在某些情况下,如果不想使用LRU算法,那么可以通过“-M” 参数来启动Memcached,这样Memcached在内存耗尽时,会返回一个报错信息。

推荐阅读更多精彩内容