`

memcached 深度解剖

阅读更多
memcached 简介
 memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。起初作者编写它可能是为了提高动态网页应用,为了减轻数据库检索的压力,来做的这个缓存系统。它的缓存是一种分布式的,也就是可以允许不同主机上的多个用户同时访问这个缓存系统,这种方法不仅解决了共享内存只能是单机的弊端,同时也解决了数据库检索的压力,最大的优点是提高了访问获取数据的速度!基于memcache作者对分布式 cache的理解和解决方案。 memcache完全可以用到其他地方 比如分布式数据库, 分布式计算等领域。

memcached 协议

memcached 协议简单的说有一组规定好的字符串组成,例如:
socket.write "get #{cache_key}\r\n"
socket.write "gets #{cache_key}\r\n"
socket.write "incr #{cache_key} #{amount}#{noreply}\r\n"
 


memcached 和nginx 结合使用:
原文地址:
http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/
配置例子:
  location /dynamic_request {
	   # append an extenstion for proper MIME type detection
           if ($args ~* format=json) { rewrite ^/dynamic_request/?(.*)$ /dynamic_request.js$1 break; }
           if ($args ~* format=xml)  { rewrite ^/dynamic_request/?(.*)$ /dynamic_request.xml$1 break; }
 
           memcached_pass 127.0.0.1:11211;
           error_page 404 = @dynamic_request;
}

架构图:


memcached 内部数据存储分析:
memcached 的数据结构可以简单的有slab -> chunks 来描述,slab 可以理解为一个内存块,一个slab是memcached一次申请内存的最小单位,在memcache中,一个slab大小默认为1M,每个slab被划分为若干个chunk,每个chunk里保存一个item,slab安装自己的id分别组成链表,这些链表又按id挂在一个slabclass数组上,整个结构看起来有点像二维数组。slabclass的长度在memcached 1.1中是21,在memcached 1.2中是200。
slab有一个初始chunk大小,memcached1.1中是1字节,memcached1.2中是80字节,
memcached 1.2中有一个factor值,默认为1.25, memcached -help 查看一下参数factor

SlabClass(1.2版本)
id 从 0 开始
|------| 0          slab
|  id1 | ------->|-------|
|  id2 |            |chunk| -> item {key:value} 这个根据slabId 计算chunk大小
|   ..   |            |   ....   |
|------| 199

class SlabClass
{
    int size #chunk size
    int perslab chunk个数
    Array *slot #空闲槽
    int slabs #slab 数量
    Array * slab_list 指针数值 1M slab #不够就申请slab,并加入slab_list 中。
}



find slab id


unsigned int slabs_clsid(const size_t size) {
    int res = POWER_SMALLEST;

    if (size == 0)
        return 0;
    while (size > slabclass[res].size)
        if (res++ == power_largest)     /* won't fit in the biggest slab */
            return 0;
    return res;
}


以下是根据slabid计算chunk大小的公式(1.2版本):
chunk 大小 = 初始大小 * factor ^ id 
slab_id  =  0
chunk 大小 = 80字节 * 1.25 ^ 0
slab_id  =  1
chunk 大小 = 80字节 * 1.25 ^ 1

id = 0 的slab 永远都是 80字节每个chunk,除非你重编译源码
那么 id为0的slab有 (1024* 1024)/80= 13107 个chunk
memcached1.2版本 会初始化 id 到 40.



:~> memcached -vvv
slab class   1: chunk size        96 perslab   10922
slab class   2: chunk size       120 perslab    8738
slab class   3: chunk size       152 perslab    6898
slab class   4: chunk size       192 perslab    5461
slab class   5: chunk size       240 perslab    4369
slab class   6: chunk size       304 perslab    3449
slab class   7: chunk size       384 perslab    2730
slab class   8: chunk size       480 perslab    2184
slab class   9: chunk size       600 perslab    1747
slab class  10: chunk size       752 perslab    1394
slab class  11: chunk size       944 perslab    1110
slab class  12: chunk size      1184 perslab     885
slab class  13: chunk size      1480 perslab     708
slab class  14: chunk size      1856 perslab     564
slab class  15: chunk size      2320 perslab     451
slab class  16: chunk size      2904 perslab     361
slab class  17: chunk size      3632 perslab     288
slab class  18: chunk size      4544 perslab     230
slab class  19: chunk size      5680 perslab     184
slab class  20: chunk size      7104 perslab     147
slab class  21: chunk size      8880 perslab     118
slab class  22: chunk size     11104 perslab      94
slab class  23: chunk size     13880 perslab      75
slab class  24: chunk size     17352 perslab      60
slab class  25: chunk size     21696 perslab      48
slab class  26: chunk size     27120 perslab      38
slab class  27: chunk size     33904 perslab      30
slab class  28: chunk size     42384 perslab      24
slab class  29: chunk size     52984 perslab      19
slab class  30: chunk size     66232 perslab      15
slab class  31: chunk size     82792 perslab      12
slab class  32: chunk size    103496 perslab      10
slab class  33: chunk size    129376 perslab       8
slab class  34: chunk size    161720 perslab       6
slab class  35: chunk size    202152 perslab       5
slab class  36: chunk size    252696 perslab       4
slab class  37: chunk size    315872 perslab       3
slab class  38: chunk size    394840 perslab       2
slab class  39: chunk size    493552 perslab       2
slab class  40: chunk size    616944 perslab       1
slab class  41: chunk size    771184 perslab       1
slab class  42: chunk size   1048576 perslab       1
<26 server listening (auto-negotiate)
<27 send buffer was 124928, now 268435456
<28 send buffer was 124928, now 268435456


直到 chunk 大小为1M,最有一个slab_id中对应的chunk只有一个。
那么memcached为什么使用这种方式存储那,是因为通过chunk的大小就能得到slab_id,从而找到slab,但是,这样做有一个缺点就是空间利用率下降了,chunk的大小可能不会是1M的整数倍.
计算slab_id公式如下:
factor^id = chunk 大小 /  初始大小
id = log(chunk 大小 /  初始大小 ) / log(factor)
这样通过chunk 大小就能得到 slab id 了.
例如:
id = log(80字节 / 80字节) / log(1.25) = 0


你知道了slab和chunk的关系,就可以改变factor 来优化你的memcached了。
需要提醒的是,因为id=0的chunk为80字节,如果你保存的数据超过80字节,性能会有一些损耗。

修改chunk size
/* 修改slab.c 文件中的 slabs_init方法 */

 while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) {
        /* Make sure items are always n-byte aligned */
        if (size % CHUNK_ALIGN_BYTES)
            size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);

		slabclass[i].size = 200 /*size;*/
		slabclass[i].perslab = 5000 /*settings.item_size_max / slabclass[i].size;*/
        size *= factor;
        if (settings.verbose > 1) {
            fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n",
                    i, slabclass[i].size, slabclass[i].perslab);
        }
    }


slab class   1: chunk size       200 perslab    5000
slab class   2: chunk size       200 perslab    5000
slab class   3: chunk size       200 perslab    5000
slab class   4: chunk size       200 perslab    5000
slab class   5: chunk size       200 perslab    5000
slab class   6: chunk size       200 perslab    5000
slab class   7: chunk size       200 perslab    5000
slab class   8: chunk size       200 perslab    5000
slab class   9: chunk size       200 perslab    5000


 
#  Item_Size   Max_age  1MB_pages Count   Full?
       1     200 B      245 s       2         5139      no
#  Item_Size   Max_age  1MB_pages Count   Full?
      1     200 B      245 s       5         21966      no  


根据以上代码我发现,memcache slab 只取一个 slab_class ,需要如下修改
/* 修改slabs_clsid */
unsigned int slabs_clsid(size_t size) {
        return 1;
}

/* 修改slab_init */
void slabs_init(const size_t limit, const double factor, const bool prealloc) {

//while (++i < POWER_LARGEST && size <= settings.item_size_max / factor) {                                                  
    //    /* Make sure items are always n-byte aligned */                                                                       
    //    if (size % CHUNK_ALIGN_BYTES)                                                                                         
    //        size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES);                                                           
    //                                                                                                                          
    //       slabclass[i].size = 200;//size;                                                                                    
    //  slabclass[i].perslab = 5000;/*settings.item_size_max / slabclass[i].size;*/                                             
    //  size *= factor;                                                                                                         
    //  if (settings.verbose > 1) {                                                                                             
    //      fprintf(stderr, "slab class %3d: chunk size %9u perslab %7u\n",                                                     
    //               i, slabclass[i].size, slabclass[i].perslab);                                                               
//  }                                                                                                                           
//  }                                                                                                                           
    i = 1;
    power_largest = i;                                                                                                        

    slabclass[1].size = 200; //settings.item_size_max;                                                                          
    slabclass[1].perslab = 5000;

    //slabclass[power_largest].size = settings.item_size_max;                                                                   
    //slabclass[power_largest].perslab = 1;   


如下结果
 slab class   1: chunk size       200 perslab    5000

 #  Item_Size   Max_age  1MB_pages Count   Full?
       1     200 B        7 s       3            10137      no



Memcached一些特性和限制
在 Memcached 中可以保存的item数据量是没有限制的,只有内存足够
最大30天的数据过期时间, 设置为永久的也会在这个时间过期,常量REALTIME_MAXDELTA 60*60*24*30 控制
最大键长为250字节,大于该长度无法存储,常量KEY_MAX_LENGTH 250 控制
单个item最大数据是1MB,超过1MB数据不予存储,常量POWER_BLOCK 1048576 进行控制,它是默认的slab大小
最大同时连接数是200,通过 conn_init()中的freetotal 进行控制,最大软连接数是1024,通过 settings.maxconns=1024 进行控制
跟空间占用相关的参数:settings.factor=1.25, settings.chunk_size=48, 影响slab的数据占用和步进方式

在新版本中可以使用 -I  来设置slab滴大小

-I            Override the size of each slab page. Adjusts max item size
              (default: 1mb, min: 1k, max: 128m)




As far as this list is concerned, if you run a 32-bit
Linux OS, memcached can only use 2GB of memory for the entire process.  That
includes the memory needed for connections.  If you run a 64-bit Linux  OS you do not have this limit
1
0
分享到:
评论

相关推荐

    Memcached深度分析.docx

    **Memcached深度解析** Memcached是由danga.com(LiveJournal的技术团队)开发的一款分布式内存对象缓存系统,其设计初衷是减轻动态系统中的数据库负载,从而提升系统的整体性能。作为一个广泛应用的开源软件,...

    memcached全面剖析.pdf

    memcached是一款高性能、分布式内存对象缓存系统,最初由Danga Interactive开发,用于减少数据库负载,通过缓存数据和对象来加速Web应用程序。它以key-value的形式存储数据,支持多种编程语言,如Perl、PHP、Python...

    memcached 64位 window

    标题"memcached 64位 window"指的是在Windows操作系统上运行的64位版本的Memcached缓存系统。Memcached是一种分布式内存对象缓存系统,广泛用于减轻数据库负载,提高Web应用的性能。由于是64位版本,这意味着它可以...

    memcached安装软件 libevent magent memcached

    Memcached是一款高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库的负载。它通过在内存中存储数据来提供快速的数据访问,从而提高应用的性能。本篇文章将详细讲解如何安装和配置memcached,...

    memcached windows稳定版

    在终端(也即cmd命令界面)下输入 ‘c:\memcached\memcached.exe -d install’ 安装 3. 再输入: ‘c:\memcached\memcached.exe -d start’ 启动。NOTE: 以后memcached将作为windows的一个服务每次开机时自动启动...

    memcached安装包以及MemCachedClient

    **Memcached 安装与使用详解** Memcached 是一款高性能的分布式内存缓存系统,用于在Web应用中减轻数据库负载。它将数据存储在内存中,以键值对的形式提供快速访问,尤其适用于高并发场景。Memcached 使用简单,可...

    memcached服务器端memcached.exe 下载

    标题“memcached服务器端memcached.exe 下载”指的是获取memcached服务端的可执行文件,`memcached.exe`是Windows环境下运行memcached服务的程序。这个绿色版的memcached意味着它无需安装,下载解压后即可直接运行,...

    windows下memcached+memcached.dll 5.3.8

    标题中的“Windows下memcached+memcached.dll 5.3.8”指的是在Windows操作系统上安装和使用Memcached服务的场景,其中`memcached.dll 5.3.8`是Memcached服务器的一个特定版本的动态链接库文件。Memcached是一款高...

    安装Memcached及Memcached配置

    Memcached 是一个高性能的分布式内存对象缓存系统,常用于减轻数据库负载,提高Web应用的响应速度。在本文中,我们将详细介绍如何安装和配置Memcached,以及如何查询其运行状态。 1. **安装Memcached** - 首先,你...

    python-memcached python-memcached

    Python-memcached是Python语言的一个库,用于与Memcached缓存系统进行交互。Memcached是一种高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库的负载,提高数据访问速度。Python-memcached库则...

    memcached.exe及memcached.dll

    **Memcached:高性能分布式内存缓存系统** Memcached是一款开源、高性能、分布式内存对象缓存系统,用于在动态系统中减少数据库负载,提升应用程序性能。它通过存储数据和对象到内存中,使得频繁访问的数据可以更快...

    php7 的memcached扩展php_memcached.dll扩展

    Memcached是一种分布式内存对象缓存系统,广泛应用于Web应用程序,以提高数据读取速度,减轻数据库负载。在PHP环境中,使用Memcached扩展可以方便地存储和检索数据,尤其适用于处理高并发场景。 `...

    memcached官方jar和一些网上的资料

    **Memcached 深度解析** Memcached 是一个高性能、分布式的内存对象缓存系统,最初由 Danga Interactive 创建,现已成为许多Web应用程序中的标准组件。它被设计用来减轻数据库的负载,通过将数据存储在内存中,快速...

    php memcached安装文档以及Memcached扩展

    1. **下载Memcached**:首先,你需要从官方网站获取最新版的Memcached源码,或者在Windows环境下,可以直接下载编译好的`memcached.exe`。将`memcached.exe`放在一个方便的位置,例如`C:\Program Files`,并确保该...

    memcached-1.5.4

    **memcached-1.5.4源码分析与编译指南** `memcached`是一款高性能、分布式的内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库负载,提高数据访问速度。它通过将数据存储在内存中,实现快速读取,避免了频繁...

    memcached安装包以及java所需的memcached架包

    **memcached** 是一款高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库负载,提高数据访问速度。它将数据存储在内存中,以键值对的形式提供快速的数据检索服务。memcached的设计目标是简洁和...

Global site tag (gtag.js) - Google Analytics