`

[笔记] Memcached全面剖析

阅读更多

本文主要参考了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

-        Java client

简单协议

目前,Memcached使用简单的基于文本行的协议,还支持二进制协议

常用操作命令

保存数据

Ÿ   setstore this data(无论存不存在键相同的数据,都保存)

Ÿ   cas (check and set)store this data but only if no one else has updated since I last fetched it(仅当从我上次取来之后没有人更新它时,才保存)

优势防止高并发下的数据不一致问题

如果操作失败,可以增加重试机制(2get-cas)

获取数据

Ÿ   get

Ÿ   gets:需要一次取得多条数据时使用(批量操作)。它可以非同步地同时取得多个键值,(优势)其速度要比循环调用get快数十倍

增一和减一操作

可以将Memcached上特定的键值作为计数器使用。但在实际项目中很少使用这个特性,因为它没落地数据,一旦服务器崩溃就全完了。对于单个维度的计数,可以使用redisINCRDECR命令MySQLhandlersocket;对于用户的多维度计数,可以使用redishashes数据结构。

Ÿ   incr

Ÿ   decr

增一和减一是原子操作。但未设置初始值时,不会自动赋成0。因此,应当进行错误检查,必要时加入初始化操作。而且,服务器端也不会对超过232时的行为进行检查

统计监控

Ÿ   stats:用于查询服务器维护的统计信息和其它内部数据

3.      内存存储

Slab Allocator机制:整理内存以便重复使用

目前,Memcached默认情况下使用Slab Allocator机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行mallocfree来进行的。但是,(缺点)这种方式会导致内存碎片,加重操作系统内存管理器的负担在最坏的情况下,会导致操作系统比Memcached进程本身还慢Slab Allocator就是为了解决该问题而诞生的

Slab源于Jeff BonwickSunOS操作系统首次引入的一种内存处理机制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,以获得最恰当的设置。(内存是珍贵的资源,浪费就太可惜了。)

接下来介绍一下,如何使用Memcachedstats命令来查看slabs的利用率等各种各样的信息。

stats:查看memcached的内部状态

Memcached有个名为stats的命令,使用它可以获得各种各样的信息。

查看slabs的使用状况

使用Memcached的创造者Brad写的名为memcached-toolPerl脚本,可以方便地获得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 UsedLRU)机制分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,(实现:)当Memcached内存空间不足时(无法从Slab Class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录

缓存的实用角度来看,该模型十分理想

不过,有些情况下LRU机制反倒会造成麻烦。话说回来,Memcached毕竟不是存储器,而是缓存,所以推荐使用LRU

Memcached的最新发展方向

Memcachedroadmap上有两个大的目标。一个是二进制协议的策划和实现,另一个是外部引擎的加载功能。

关于二进制协议

使用二进制协议的理由是它不需要文本协议解析处理使得原本高速的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)。只要数据没有因为某些原因被删除就能获得保存的值


4.3 分布式简介:获取

分布式算法

取模算法

简单来说,就是“根据服务器台数的余数进行散列”。求得键的整数哈希值(CRC32),再除以服务器台数,根据其余数来选择服务器。

缺点

余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。那就是添加或移除服务器时,缓存重组的代价相当巨大。添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器,从而影响缓存的命中率

但由于使用了新的分布式方法,现在可以轻而易举地添加memcached服务器了。这种分布式方法称为Consistent Hashing

Consistent Hashing一致性哈希算法

Consistent Hashing的简单说明

Consistent Hashing如下图所示:首先,求出Memcached服务器(节点)的哈希值,并将其配置到02SUP(32)的圆上。然后,用同样的方法求出存储数据的的哈希值,并映射到圆上。然后,从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过2SUP(32)仍然找不到服务器,就会保存到第一台memcached服务器上。

4.4 Consistent Hashing基本原理

从上图的状态中,添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化而影响缓存的命中率,但Consistent Hashing中,只有在圆上增加服务器的地点逆时针方向的第一台服务器上的键会受到影响

4.5 Consistent Hashing添加服务器

优势:)因此,Consistent Hashing最大限度地抑制了键的重新分布。而且,有的Consistent Hashing的实现方法还采用了虚拟节点的思想。使用一般的hash函数的话,服务器的映射地点的分布非常不均匀。因此,使用虚拟节点的思想为每个物理节点(服务器)在圆上分配100200个点。(优势:)这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布

总结

本章介绍了Memcached的分布式算法,主要有Memcached的分布式是由客户端函数库实现,以及高效率地分散数据Consisting Hashing算法。

6.      Memcached的应用和兼容程序

mixi案例研究

mixi在提供服务的初期阶段就使用了Memcached

随着网站访问量的急剧增加,单纯为数据库添加slave已无法满足需要。因此引入了Memcached。此外,我们也从增加可扩展性的方面进行了验证,证明了Memcached的速度和稳定性都能满足需要。现在,Memcached已成为mixi服务中非常重要的组成部分。


1 mixi现在的系统组件

 

 

玩的开心!^_^

  • 大小: 28.2 KB
  • 大小: 23.4 KB
  • 大小: 11 KB
  • 大小: 7 KB
  • 大小: 17.2 KB
  • 大小: 21.9 KB
  • 大小: 25.6 KB
  • 大小: 38.7 KB
  • 大小: 45.1 KB
  • 大小: 30.7 KB
分享到:
评论

相关推荐

    Memcached 源码剖析笔记

    memcached 源码剖析笔记和源码。 Memcached 是一个自由、源码开放、高性能、分布式内存对象缓存系统,目的在于过减轻数据库负载来使动态 Web 应用程序提速。

    Memcached源码剖析笔记

    Memcached源码剖析笔记:从源码级别剖析memcached的实现原理,讲的比较细。

    Memcached源码剖析笔记.docx

    Memcached源码剖析笔记

    Memcached源码剖析笔记.pdf

    Memcached源码剖析笔记

    Memcached 学习资料(memcached Memcached使用手册 Memcached源码剖析笔记)

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的...

    Memcached源码剖析笔记_wrapper1

    1.背景Memcached 是一个高性能的分布式内存对象缓存系统,用于动态 Web 应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从

    memcache源码分析

    包含资源:memcached代码分析详解 memcached命令参数大全 memcached深度分析 memcached完全剖析(1-5)整理 memcached源码分析(自己整理 未完) Memcached源码剖析笔记 分布式存储系统架构

    NoSQL学习笔记

    NoSQL学习笔记,分析常用NoSQL技术优劣,进行对比,并深入分析了Memcached数据缓冲技术。

    decode-memcached:memcached原始码剖析注释

    memcached原始码阅读笔记阅读memcached最好有libevent基础,memcached是基于libevent构建起来的。通由libevent提供的事件驱动机制触发memcached中的IO事件。已经有大牛剖析过libevent源码了,推荐阅读:个人认为,...

    高性能高并发服务器架构大全

     Memcached和Lucene笔记 110  使用开源软件,设计高性能可扩展网站 110  面向高负载的架构Lighttpd+PHP(FastCGI)+Memcached+Squid 113  思考高并发高负载网站的系统架构 113  "我在SOHU这几年做的一些...

Global site tag (gtag.js) - Google Analytics