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。 感謝您的閱讀