Memcache介绍
首先说一下,Memcache是项目名称,Memcached是服务器端程序,有时候Memcache也是客户端名称。
Memcached是一款开源、高性能、分布式内存对象缓存系统,可应用各种需要缓存的场景,其主要目的是通过降低对Database的访问来加速web应用程序。它是一个基于内存的“键值对”存储,用于存储数据库调用、API调用或页面引用结果的直接数据,如字符串、对象等。
memcached是以LiveJournal旗下Danga Interactive 公司的Brad Fitzpatric 为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。
Memcached是一个高性能的不通信(各服务器间彼此无视:不在服务器间进行数据同步)分布式的内存对象缓存系统,O(1)的执行效率;通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。
Memcached是以守护程序方式运行于一个或多个服务器中,随时会接收客户端的连接和操作。memcached是一种无阻塞的socket通信方式服务,基于libevent(redhat系统中支持事件驱动I/O的库)库,由于无阻塞通信,对内存读写速度非常之快。Memcached是一个缓存服务器但本身无法决定缓存任何数据一半依赖于客户端(软件开发时是否支持memcached客户端库)一半依赖于服务器。Memcached是一个内存缓存服务器存储键值一一对应;它的下线是key默认最大不能超过128bytes数据最小48bytes最大1MB也就是一个slabs如果要存2M的值不能使用两个slabs因为两个slabs不是连续的无法再内存中存储故需要修改slabs的大小;多个key和value进行存储时即使这个slabs没有利用完那么也不会存放别的数据。
Memcached是一款开发工具,它既不是一个代码加速器,也不是数据库中间件。其设计哲学思想主要反映在如下方面:
1) 简单key/value存储
服务器不关心数据本身的意义及结构,只要是可序列化数据即可。存储项由“键、过期时间、可选的标志及数据”四个部分组成;
2) 协议简单
Memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。因此,通过telnet也能在memcached上保存数据、取得数据。如下:
1 2 3 4 5 6 7 8 9 10 |
$ telnet localhost 11211 Trying 127.0.0.1... Connected to localhost.localdomain (127.0.0.1). Escape character is '^]'. set foo 0 0 3 (保存命令) bar (数据) STORED (结果) get foo (取得命令) VALUE foo 0 3 (数据) bar (数据) |
3) 功能的实现一半依赖于客户端,一半基于服务器端
客户负责发送存储项至服务器端、从服务端获取数据以及无法连接至服务器时采用相应的动作;服务端负责接收、存储数据,并负责数据项的超时过期;
4) 内置内存存储方式
为了提高性能,memcached 中保存的数据都存储在 memcached 内置的内存存储空间中。由于数据仅存在于内存中,因此重启 memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指定值之后,就基于 LRU(Least Recently Used)算法自动删除不使用的缓存。memcached 本身是为缓存而设计的服务器,因此并没有过多考虑数据的永久性问题。
5) 互不通信的分布式
memcached 尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个 memcached 不会互相通信以共享信息。那么,怎样进行分布式呢?这完全取决于客户端的实现。
6) 基于libevent库的事件处理
Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe 传递给worker线程,进行读写IO, 网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency和锁的问题,比如,Memcached最常用的stats 命令,实际Memcached所有操作都要对这个全局变量加锁,进行计数等工作,带来了性能损耗。
libevent 是个程序库,它将 Linux 的 epoll、BSD 类操作系统的 kqueue 等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥 O(1)的性能。memcached 使用这个 libevent 库,因此能在 Linux、BSD、Solaris 等操作系统上发挥其高性能。关于事件处理这里就不再详细介绍,可以参考 Dan Kegel 的 The C10K Problem。
memcache缓存图解
这里先说一下,memcached虽然被称为“分布式缓存”,但是memcached本身完全不具备分布式的功能,memcached集群之间不会相互通信,所谓的“分布式”完全依赖于客户端程序的实现,就像上面的流程图一样。
基于上面这幅图,介绍一个Memcache读取写入的流程:
写入操作
1)应用程序输入需要写缓存的数据。
2)调用Memcache API将Key输入路由算法模块,路由算法根据Key和MemCache集群服务器列表得到一台服务器编号。
3)由服务器编号得到MemCache及其的IP地址和端口号。
4)MemCache API调用通信模块和指定编号的服务器通信,将数据写入该服务器,完成一次分布式缓存的写操作。
但执行写操作时,会将之前缓存的任何受此写入操作影响的结果设定为无效。此过程有助于防止缓存和数据库之间出现数据不一致性。
读取操作
读取操作和写入操作方式是一样,只要使用相同的路由算法和服务器列表,且应用程序查询的Key跟写入的Key是相同的,Memcache客户端总是会访问相同的服务器端去读取数据,只要服务器中还缓存着该数据,就能保证缓存命中。
这种Memcache集群的方式也是从分区容错性的方面考虑的,假如node2宕机了,那么node2上面存储的数据都不可用了,此时由于集群中node0和node1还存在,下一次请求node2中存储的Key值得时候,肯定是没有命中的。这时先从数据库中拿到要缓存的数据,然后路由算法模块根据Key值在node0和node1中选取一个节点,把对应的数据放进去,这样下一次就又可以走缓存了。这种集群的做法很好,但是缺点是成本比较大。
Memcached客户端API
许多语言都实现了连接memcached的客户端,以Perl和php为主,仅memcached网站上列出来的语言就有:
●Perl – cache::memcached
●Php – memcached
●C/C++ – libmemcached
●Python
●Ruby
●C#
●Lua
等等….
Memcached的特性和限制
先说一下:对于Memcached的特性和限制说明,可以在看完整个Memcached所有章节后来回来看,那个时候你才可能对以下说明更能理解。
1)Memcached中可以保存的item数据量是没有限制的,只要你的内存足够大。
2)Memcached单进程在32位机中最大使用内存为2G,64位机则没有限制。
3)Key最大为250个字节,超过该长度无法存储。
4)单个item最大数据是1MB,超过1MB的数据不予存储。
5)Memcahced是不安全的,比如已知某个Memcache节点,可以直接telnet过去,并通过flush_all所有键值失效。
6)不能够遍历Memcache中素有的item,因为这个操作的速度相对缓慢且会阻塞其他的操作。
7)Memcached的高性能源自两个阶段哈希结构:第一阶段在客户端,通过hash算法根据key值算出一个节点;第二阶段在服务端,通过一个内部hash算法,查找真正的item并返回给客户端。
8)Memcached设置添加某一个key值的时候,传入expiry为0表示这个key值永久有效,但这个key值也会在30天之后失效,这个是Memcached源码定义的。