memcached全面剖析–memcached的应用和兼容程序

mixi案例研究

mixi在提供服务的初期阶段就使用了memcached。 随着网站访问量的急剧增长,单纯为数据库添加slave已没法知足须要,所以引入了memcached。 此外,咱们也从增长可扩展性的方面进行了验证,证实了memcached的速度和稳定性都能知足须要。 如今,memcached已成为mixi服务中很是重要的组成部分。javascript

memcached-0005-01.png

图1 如今的系统组件php

服务器配置和数量

mixi使用了许许多多服务器,如数据库服务器、应用服务器、图片服务器、 反向代理服务器等。单单memcached就有将近200台服务器在运行。 memcached服务器的典型配置以下:java

 

  • CPU:Intel Pentium 4 2.8GHz
  • 内存:4GB
  • 硬盘:146GB SCSI
  • 操做系统:Linux(x86_64)

    这些服务器之前曾用于数据库服务器等。随着CPU性能提高、内存价格降低, 咱们积极地将数据库服务器、应用服务器等换成了性能更强大、内存更多的服务器。 这样,能够抑制mixi总体使用的服务器数量的急剧增长,下降管理成本。 因为memcached服务器几乎不占用CPU,就将换下来的服务器用做memcached服务器了。mysql

    memcached进程

    每台memcached服务器仅启动一个memcached进程。分配给memcached的内存为3GB, 启动参数以下:linux

    /usr/bin/memcached -p 11211 -u nobody -m 3000 -c 30720

    因为使用了x86_64的操做系统,所以能分配2GB以上的内存。32位操做系统中, 每一个进程最多只能使用2GB内存。也曾经考虑过启动多个分配2GB如下内存的进程, 但这样一台服务器上的TCP链接数就会成倍增长,管理上也变得复杂, 因此mixi就统一使用了64位操做系统。ios

    另外,虽然服务器的内存为4GB,却仅分配了3GB,是由于内存分配量超过这个值, 就有可能致使内存交换(swap)。连载的第2次中 前坂讲解过了memcached的内存存储“slab allocator”,当时说过,memcached启动时 指定的内存分配量是memcached用于保存数据的量,没有包括“slab allocator”自己占用的内存、 以及为了保存数据而设置的管理空间。所以,memcached进程的实际内存分配量要比 指定的容量要大,这一点应当注意。web

    mixi保存在memcached中的数据大部分都比较小。这样,进程的大小要比 指定的容量大不少。所以,咱们反复改变内存分配量进行验证, 确认了3GB的大小不会引起swap,这就是如今应用的数值。算法

    memcached使用方法和客户端

    如今,mixi的服务将200台左右的memcached服务器做为一个pool使用。 每台服务器的容量为3GB,那么全体就有了将近600GB的巨大的内存数据库。 客户端程序库使用了本连载中屡次提到车的Cache::Memcached::Fast, 与服务器进行交互。固然,缓存的分布式算法使用的是第4次介绍过的 Consistent Hashing算法。sql

    应用层上memcached的使用方法由开发应用程序的工程师自行决定并实现。 可是,为了防止车轮再造、防止Cache::Memcached::Fast上的教训再次发生, 咱们提供了Cache::Memcached::Fast的wrap模块并使用。数据库

    经过Cache::Memcached::Fast维持链接

    Cache::Memcached的状况下,与memcached的链接(文件句柄)保存在Cache::Memcached包内的类变量中。 在mod_perl和FastCGI等环境下,包内的变量不会像CGI那样随时从新启动, 而是在进程中一直保持。其结果就是不会断开与memcached的链接, 减小了TCP链接创建时的开销,同时也能防止短期内反复进行TCP链接、断开 而致使的TCP端口资源枯竭。

    可是,Cache::Memcached::Fast没有这个功能,因此须要在模块以外 将Cache::Memcached::Fast对象保持在类变量中,以保证持久链接。

    package Gihyo::Memcached; use strict; use warnings; use Cache::Memcached::Fast; my @server_list = qw/192.168.1.1:11211 192.168.1.1:11211/; my $fast; ## 用于保持对象 sub new { my $self = bless {}, shift; if ( !$fast ) { $fast = Cache::Memcached::Fast->new({ servers => \@server_list }); } $self->{_fast} = $fast; return $self; } sub get { my $self = shift; $self->{_fast}->get(@_); }

    上面的例子中,Cache::Memcached::Fast对象保存到类变量$fast中。

    公共数据的处理和rehash

    诸如mixi的主页上的新闻这样的全部用户共享的缓存数据、设置信息等数据, 会占用许多页,访问次数也很是多。在这种条件下,访问很容易集中到某台memcached服务器上。 访问集中自己并非问题,可是一旦访问集中的那台服务器发生故障致使memcached没法链接, 就会产生巨大的问题。

    连载的第4次 中提到,Cache::Memcached拥有rehash功能,即在没法链接保存数据的服务器的状况下, 会再次计算hash值,链接其余的服务器。

    可是,Cache::Memcached::Fast没有这个功能。不过,它可以在链接服务器失败时, 短期内再也不链接该服务器的功能。

    my $fast = Cache::Memcached::Fast->new({ max_failures => 3, failure_timeout => 1 });

    在failure_timeout秒内发生max_failures以上次链接失败,就再也不链接该memcached服务器。 咱们的设置是1秒钟3次以上。

    此外,mixi还为全部用户共享的缓存数据的键名设置命名规则, 符合命名规则的数据会自动保存到多台memcached服务器中, 取得时从中仅选取一台服务器。建立该函数库后,就可使memcached服务器故障 再也不产生其余影响。

    memcached应用经验

    到此为止介绍了memcached内部构造和函数库,接下来介绍一些其余的应用经验。

    经过daemontools启动

    一般状况下memcached运行得至关稳定,但mixi如今使用的最新版1.2.5 曾经发生过几回memcached进程死掉的状况。架构上保证了即便有几台memcached故障 也不会影响服务,不过对于memcached进程死掉的服务器,只要从新启动memcached, 就能够正常运行,因此采用了监视memcached进程并自动启动的方法。 因而使用了daemontools。

    daemontools是qmail的做者DJB开发的UNIX服务管理工具集, 其中名为supervise的程序可用于服务启动、中止的服务重启等。

    • daemontools#!/bin/sh if [ -f /etc/sysconfig/memcached ];then . /etc/sysconfig/memcached fi exec 2>&1 exec /usr/bin/memcached -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN $OPTIONS
       

      监视

      mixi使用了名为“nagios”的开源监视软件来监视memcached。

      在nagios中能够简单地开发插件,能够详细地监视memcached的get、add等动做。 不过mixi仅经过stats命令来确认memcached的运行状态。

      define command { command_name check_memcached command_line $USER1$/check_tcp -H $HOSTADDRESS$ -p 11211 -t 5 -E -s 'stats\r\nquit\r\n' -e 'uptime' -M crit }

      此外,mixi将stats目录的结果经过rrdtool转化成图形,进行性能监视, 并将天天的内存使用量作成报表,经过邮件与开发者共享。

      memcached的性能

      连载中已介绍过,memcached的性能十分优秀。咱们来看看mixi的实际案例。 这里介绍的图表是服务所使用的访问最为集中的memcached服务器。

      memcached-0005-02.png

      图2 请求数

      memcached-0005-05.png

      图5 CPU利用率

      可见,仍然有idle的部分。所以,memcached的性能很是高, 能够做为Web应用程序开发者放心地保存临时数据或缓存数据的地方。

      兼容应用程序

      memcached的实现和协议都十分简单,所以有不少与memcached兼容的实现。 一些功能强大的扩展能够将memcached的内存数据写到磁盘上,实现数据的持久性和冗余。 连载第3次介绍过,之后的memcached的存储层将变成可扩展的(pluggable),逐渐支持这些功能。

      这里介绍几个与memcached兼容的应用程序。

      repcached
      为memcached提供复制(replication)功能的patch。
      Flared
      存储到QDBM。同时实现了异步复制和fail over等功能。
      memcachedb
      存储到BerkleyDB。还实现了message queue。
      Tokyo Tyrant
      将数据存储到Tokyo Cabinet。不只与memcached协议兼容,还能经过HTTP进行访问。

      Tokyo Tyrant案例

      mixi使用了上述兼容应用程序中的Tokyo Tyrant。Tokyo Tyrant是平林开发的 Tokyo Cabinet DBM的网络接口。它有本身的协议,但也拥有memcached兼容协议, 也能够经过HTTP进行数据交换。Tokyo Cabinet虽然是一种将数据写到磁盘的实现,但速度至关快。

      mixi并无将Tokyo Tyrant做为缓存服务器,而是将它做为保存键值对组合的DBMS来使用。 主要做为存储用户上次访问时间的数据库来使用。它与几乎全部的mixi服务都有关, 每次用户访问页面时都要更新数据,所以负荷至关高。MySQL的处理十分笨重, 单独使用memcached保存数据又有可能会丢失数据,因此引入了Tokyo Tyrant。 但无需从新开发客户端,只需原封不动地使用Cache::Memcached::Fast便可, 这也是优势之一。关于Tokyo Tyrant的详细信息,请参考本公司的开发blog。

      总结

      到本次为止,“memcached全面剖析”系列就结束了。咱们介绍了memcached的基础、内部结构、 分散算法和应用等内容。读完后若是您能对memcached产生兴趣,就是咱们的荣幸。 关于mixi的系统、应用方面的信息,请参考本公司的开发blog。 感谢您的阅读