本文主要参考了charlee翻译的《Memcached全面剖析》
1. Memcached是什么?
许多Web应用都将数据保存到RDBMS中,应用程序从中读取数据并在浏览器中显示。但随着数据量的增大和访问的集中,就会出现(问题出现:)RDBMS的负载加重、数据库响应恶化、网站显示延迟等重大影响。
What is Memcached?
Free & open source, high-performance, distributed memory object caching system, generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.
Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering.
Memcached是一个高性能的分布式内存对象缓存系统。目标是,通过缓存数据库查询、API调用或网页渲染结果,减少数据库(select)访问次数,以加速动态Web应用的响应速度,提高可扩展性。(通过减轻数据库负载来使动态Web应用提速)
这时就该Memcached大显身手了。
图1.1 一般情况下Memcached的用途
适用场景
Memcached适用于多查询(get)少更新的场景。对于更新数据操作,数据每次还是会落地到DB;而对于查询操作,若缓存命中则直接返回,无需再请求DB。
2. 特征
Key-Value
Simple Protocol
- set/cas/get/gets
- incr/decr
- stats
Lazy Expiration
LRU
Access
- telnet host port
- printf 'stats\r\n' | nc host port
简单协议
目前,Memcached使用简单的基于文本行的协议,还支持二进制协议。
常用操作命令
保存数据
set:store this data(无论存不存在键相同的数据,都保存)
cas (check and set):store this data but only if no one else has updated since I last fetched it(仅当从我上次取来之后没有人更新它时,才保存)
优势:防止高并发下的数据不一致问题。
如果操作失败,可以增加重试机制(2次get-cas)。
获取数据
get
gets:需要一次取得多条数据时使用(批量操作)。它可以非同步地同时取得多个键值,(优势:)其速度要比循环调用get快数十倍。
增一和减一操作
可以将Memcached上特定的键值作为计数器使用。但在实际项目中很少使用这个特性,因为它没落地数据,一旦服务器崩溃就全完了。对于单个维度的计数,可以使用redis的INCR和DECR命令或MySQL的handlersocket;对于用户的多维度计数,可以使用redis的hashes数据结构。
incr
decr
增一和减一是原子操作。但未设置初始值时,不会自动赋成0。因此,应当进行错误检查,必要时加入初始化操作。而且,服务器端也不会对超过232时的行为进行检查。
统计监控
stats:用于查询服务器维护的统计信息和其它内部数据
3. 内存存储
Slab Allocator机制:整理内存以便重复使用
目前,Memcached默认情况下使用Slab Allocator机制来分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,(缺点:)这种方式会导致内存碎片,加重操作系统内存管理器的负担,在最坏的情况下,会导致操作系统比Memcached进程本身还慢。Slab Allocator就是为了解决该问题而诞生的。
Slab源于Jeff Bonwick为SunOS操作系统首次引入的一种内存处理机制。Slab的设计理念是基于对象缓冲的,基本想法是避免重复大量的初始化和清理操作。(用途:)Slab主要用于频繁分配释放的内存对象。如果是采用系统自带的malloc/free的话,反复地操作会造成大量内存碎片,操作系统将会花费大量的时间去查找连续的内存块来满足malloc的请求。——摘自《Memcached源码剖析笔记》
下面来看看Slab Allocator的原理。下面是Memcached文档中的Slab Allocator的目标:
the primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issues totally by using fixed-size memory chunks coming from a few predetermined size classes.
也就是说,Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。
Slab Allocator的原理相当简单。将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合,Slab Class)(图2.1)。
图2.1 Slab Allocator的构造图
而且,Slab Allocator还有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。
Slab Allocator的主要术语
Page
分配给Slab的内存空间,默认是1MB。分配给Slab之后,根据Slab的大小切分成Chunk。
Chunk
用于缓存记录的内存空间
Slab Class
特定大小的Chunk组
在Slab中缓存记录的原理
下面说明Memcached是如何针对客户端发送的数据来选择Slab并缓存到Chunk中。
(第1步)Memcached根据收到的数据的大小,选择最适合该数据大小的Slab(图2.2)。(第2步)Memcached中保存着Slab内空闲Chunk的列表,根据该列表选择Chunk,然后将数据缓存于其中。
图2.2 选择存储记录的Chunk组的方法
Slab Allocator的缺点
Slab Allocator解决了当初的内存碎片问题,但新的机制也给Memcached带来了新的问题。
这个问题就是,由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的Chunk中,剩余的28字节就浪费了(图2.3)。
图2.3 Chunk空间的使用
对于该问题,目前还没有完美的解决方案。但在文档中记载了比较有效的解决方案:
The most efficient way to reduce the waste is to use a list of size classes that closely matches (if that's at all possible) common sizes of objects that the clients of this particular installation of memcached are likely to store.
就是说,如果预先知道客户端发送的数据的常用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的Chunk组的列表,就可以减少浪费。
使用Growth Factor进行调优
Memcached在启动时,指定Growth Factor因子(-f选项),就可以在某种程度上控制Slab之间的差异。默认值为1.25。
在直接使用Memcached默认值进行部署之前,最好是重新计算一下数据的预期平均长度,调整Growth Factor,以获得最恰当的设置。(内存是珍贵的资源,浪费就太可惜了。)
接下来介绍一下,如何使用Memcached的stats命令来查看slabs的利用率等各种各样的信息。
stats:查看memcached的内部状态
Memcached有个名为stats的命令,使用它可以获得各种各样的信息。
查看slabs的使用状况
使用Memcached的创造者Brad写的名为memcached-tool的Perl脚本,可以方便地获得slab的使用情况(它将返回值整理成容易阅读的格式)。
从这个脚本获得的信息对于调优非常方便,强烈推荐使用!
总结
本章简单说明了Memcached的缓存机制和调优方法。希望读者能够理解Memcached的内存管理原理及其优缺点。
4. 删除机制和发展方向
Memcached是缓存,所以数据不会永久保存在服务器上,这是向系统中引入Memcached的前提。本章介绍Memcached的数据删除机制,以及Memcached的最新发展方向——二进制协议和外部引擎支持。
Memcached在数据删除方面有效利用资源
懒惰删除机制:数据不会真正从Memcached中消失
Memcached不会释放已分配的内存。记录超时后,客户端就无法再看见该记录(invisible),其存储空间即可重复使用。
(源码剖析)在Memcached中删除一个item对象的时候,并不是从内存中释放,而是简单的进行标记处理,再将其指针放入slot回收插槽,下次分配的时候直接使用。
Lazy Expiration:懒惰检测机制
Memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为Lazy Expiration。因此,Memcached不会在过期监视上耗费CPU时间。
(源码剖析)Memcached不花过多的时间检测各个item对象是否过期,当get获取数据时,才检查item对象是否应该删除。你不访问,我就不处理。
LRU:从缓存中有效删除数据的原理
Memcached会优先使用已过期的记录的空间。但即使如此,也会发生追加新纪录时空间不足的情况,此时就要使用名为Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,(实现:)当Memcached的内存空间不足时(无法从Slab Class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。
从缓存的实用角度来看,该模型十分理想。
不过,有些情况下LRU机制反倒会造成麻烦。话说回来,Memcached毕竟不是存储器,而是缓存,所以推荐使用LRU。
Memcached的最新发展方向
Memcached的roadmap上有两个大的目标。一个是二进制协议的策划和实现,另一个是外部引擎的加载功能。
关于二进制协议
使用二进制协议的理由是它不需要文本协议的解析处理,使得原本高速的Memcached的性能更上一层楼,还能减少文本协议的漏洞。
外部引擎支持
外部引擎支持的必要性
世界上有许多Memcached的派生系统,其理由是希望永久保存数据、实现数据冗余等,即使牺牲一些性能也在所不惜。
总结
本章介绍了Memcached的超时原理、内部如何删除数据等,在此之上又介绍了二进制协议和外部引起支持等Memcached的最新发展方向。这些功能要到1.3版才会支持,尽请期待!
5. 分布式算法
Memcached的分布式
Memcached虽然成为“分布式”缓存系统,但服务器端并没有“分布式”功能,各个Memcached不会相互通信以共享信息。服务器端仅包括前面介绍的内存存储功能,其实现非常简单。至于Memcached的分布式,则是完全由客户端程序库实现。这种分布式是Memcached的最大特点。(Memcached不互相通信的分布式)
Memcached的分布式是什么意思?
这里多次使用了“分布式”这个词,但并未做详细解释。现在开始简单地介绍一下其原理,各个客户端的实现基本相同。
图4.1 分布式简介:准备
保存数据
首先,向memcached中添加“tokyo”。(第1步)将“tokyo”传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的Memcached服务器。(第2步)服务器选定后,即(set/cas)命令它保存“tokyo”及其值。
图4.2 分布式简介:添加时
获取数据
接下来,获取保存的数据。获取时,也要将要获取的键“tokyo”传递给函数库。(第1步)函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,(第2步)然后发送获取命令(get/gets)。只要数据没有因为某些原因被删除,就能获得保存的值。
相关推荐
memcached 源码剖析笔记和源码。 Memcached 是一个自由、源码开放、高性能、分布式内存对象缓存系统,目的在于过减轻数据库负载来使动态 Web 应用程序提速。
Memcached 源码剖析笔记 Memcached 是一个自由、开源、高性能、分布式内存对象缓存系统,旨在通过减轻数据库负载来使动态 Web 应用程序提速。下面是 Memcached 源码剖析笔记的知识点总结: 1. 背景 Memcached 的...
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的...
《Memcached源码剖析笔记》是一份深入解析Memcached内部工作原理和技术细节的文档,旨在帮助读者理解这个高性能分布式内存对象缓存系统的设计与实现。Memcached被广泛应用于动态Web应用程序,通过缓存数据和对象,...
**Memcached源码剖析笔记** **1. 背景** Memcached是一个高效且流行的分布式内存对象缓存系统,主要用于动态Web应用。它的主要目的是通过将数据和对象存储在内存中来减少对数据库的访问频率,从而提升应用程序的...
2. "memcached权威指南.pdf":这是一份全面介绍Memcached的参考资料,可能包括了Memcached的工作原理、配置选项、API接口、性能调优、故障排查等方面的内容,适合初学者和进阶用户阅读。 3. ...
标题 "memcached-笔记资料.rar" 暗示了这个压缩包包含的是关于 memcached 的学习资料,这是一款广泛使用的分布式内存对象缓存系统。它主要用于减轻数据库的负载,通过在内存中存储常用数据,提高应用程序的响应速度...
**Memcached笔记** Memcached是一种高性能的分布式内存对象缓存系统,它被广泛应用于Web应用中,用于减轻数据库的负载,提高数据访问速度。本文将深入探讨Memcached的基础知识、工作原理、安装与配置,以及如何在...
包含资源:memcached代码分析详解 memcached命令参数大全 memcached深度分析 memcached完全剖析(1-5)整理 memcached源码分析(自己整理 未完) Memcached源码剖析笔记 分布式存储系统架构
memcached原始码阅读笔记阅读memcached最好有libevent基础,memcached是基于libevent构建起来的。通由libevent提供的事件驱动机制触发memcached中的IO事件。已经有大牛剖析过libevent源码了,推荐阅读:个人认为,...
**标题解析:** "memcached之客户端memadmin安装" 这个标题涉及到的是关于`memcached`的一...通过上述分析,我们可以构建一个全面的`memcached`客户端`memadmin`的安装和使用教程,帮助用户更好地理解和掌握这一工具。
5. **用户认证和授权**:笔记应用可能涉及用户登录和权限管理,通过分析这部分代码,可以学习如何实现安全的用户认证和授权机制。 6. **前端技术**:可能结合HTML、CSS和JavaScript构建用户界面,了解前后端如何...
【Redis完整版笔记】深入解析Redis作为NoSQL数据库的关键特性 Redis是一款高性能的Key-Value内存数据库,广泛应用于缓存、消息队列、计数器等多个场景。在NoSQL数据库的大潮中,Redis以其出色的速度和灵活性...
笔记会讲解如何设置错误报告级别,使用try-catch块处理异常,以及如何记录和分析日志。 7. 模板引擎:为了分离业务逻辑和视图,笔记可能包含关于使用PHP模板引擎(如Smarty或Twig)的内容,这有助于提高代码的...
【谷粒商城官方笔记.zip】是一个包含谷粒商城官方资料的压缩包,主要涉及Java编程、前后端分离技术以及尚硅谷的课程内容。这个压缩包里有多个文档和资源,让我们逐一探讨其中蕴含的重要知识点。 首先,我们看到一个...