缓存那些事(1)

1. 背景:

所有的应用程序,特别是很多 web 应用程序都需要优化它们访问客户机和将信息返回至客户机的速度。可是,通常返回的都是相同的信息。从数据源(数据库或文件系统)加载数据十分低效,若是每次想要访问该信息时都运行相同的查询,就尤显低效,因此就引入缓存技术。常见的是memcached,由Danga Interactive公司开发的,现在为facebook、amazon等众多web应用提供服务。Memcached是高性能的分布式内存缓存服务器,可以有效的减少数据库访问次数,提高动态web应用的速度,提高可扩展性。

2. 缓存的使用

2.1如何交互

缓存那些事(1)

2.2memcache的特征

协议简单:客户端与服务端之间的通信并非使用复杂的xml格式,而是简单的文本行的协议。通过telnet也可以在memcached上保存、取得数据。

基于libevent的事件处理它将linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一接口,即使对服务器的连接数增加的情况下,也可以发挥O(1)的特性。

内置内存的存储方式memcached中保存的数据都是存储在其内置的内存存储空间中,因此重启memcached、重启操作系统都会导致数据丢失。

Memcached不互相通信memcached尽管是“分布式”缓存服务器,但服务端并没有分布式的功能,各个memcached之间不会相互通信,其分布式如何进行完全取决于客户端。

缓存那些事(1)

2.3memcache客户端连接

实现memcached客户端的语言很多,有perl、php、java、c#等

2.4memcached的内存空间

Memcached采用的是slab allocator的机制分配、管理内存。其基本原理是按照预先分配的内存分割成特定长度的块,以完全解决内存碎片的问题。

缓存那些事(1)

对于已分配的内存,slab alloctator不会释放,而是重复利用。

其中page:分配给slab的内存空间,默认是1MB。分配给slab之后根据slab的大小切分成chunk

Chunk:用于缓存记录的内存空间

Slab class:特定大小的chunk的组

2.5memcached缓存记录的原理

缓存那些事(1)

Memcached中保存着slab内空闲的chunk的列表,根据数据的大小选择合适的slab,将数据缓存于其中。但是由于其分配的是特定长度的内存,因此无法有效的利用。

缓存那些事(1)

如图上的,将100byte的数据缓存到128byte的chunk中。剩下的28个字节就浪费了。目前对这个问题的解决方式仅仅是,预先知道要缓存的数据的大小,从而设定特定大小的chunk组 (通过Growth Factor进行调优)

$ memcached -f 2 –vv

启动后verbose输出:

缓存那些事(1)

2.6缓存失效

Memcached内部不会监视记录是否过期,而是在get时,通过查看时间戳是否过期,从而避免监视上耗费cpu的时间。Memcached不会释放已分配的内存,如果记录超时,客户端就无法再看见该记录,其存储空间即可重复使用,有效缓存分配的内存耗尽 — 在这种情况下,memcached 使用 LRU(最近最少使用)方法从此缓存删除条目。最近未曾使用的条目会从此缓存中先删除,最旧的最先访问。

条目被明确删除 — 总是可以从此缓存内删除条目。

2.7分布式

缓存那些事(1)

向memcached中添加“tokyo”,将“tokyo”传给客户端程序后,客户端实现的算法会根据“键”来决定保存的memcached服务器,服务器选定后,即命令它保存“tokyo”及其值

算法规则:求“键”值整数哈希值,除以服务器台数,得到的余数。

从服务器上取缓存值同上类似,发送的是get命令,只要数据没有因为某些原因被删除,就能获得保存的值。

3.客户端(XMemcached)

4.1缓存命中

直接从缓存中加载信息。

4.2缓存未命中:

Ø 执行一个或多个查询来从数据库加载信息

Ø 格式化适合于显示或进一步处理的信息

Ø 将信息存储到缓存内

Ø 使用格式化了的数据

5.弹性和可用性

如果 memcached 服务宕掉,应用程序应该回退到从原始数据源加载信息并对信息进行显示所需的格式化。此应用程序还应继续尝试在 memcached 内加载和存储信息。一旦 memcached 服务器恢复可用,应用程序就应该自动尝试存储数据

使用Memcache的小技巧,第一个是如果是一个有效分布式存储的数据,key的取名是很有学问的,这个可以按照项目需要去做,但是key值 不要太长,不会冲突就行。第二个就是每个保存在memcache中的数据不要超过1MB。第三个就是开启一个Memcache进程设置内存不要太多也不要 太少,按照自己合适设置就行,尽量最大程度提高对硬件的使用,同样可以采取在一台服务器上开启多个memcached来分担一个memcached并发链 接的压力.