1. 程式人生 > >Memcached與Libmemcached介紹及其簡單使用

Memcached與Libmemcached介紹及其簡單使用

如何通過原始碼先大體學習庫忽略具體實現細節呢?
1、首先學會庫中開放出來程式設計師可呼叫函式API,學習其引數配置,大體先忽略被庫內部的呼叫大量函式。
2、找出管理資源超級重要的結構體,從其入手。

1、Memcached

介紹

memcached是一個高效能的記憶體快取物件系統,其實質為一個鍵值對的hashmap索引,其事件處理和網路通訊均是基於libevent。memcached區別於libevent,因為memcached是一個執行程式,不需要編譯成動態連線庫,供其他程式呼叫。memcached通常作為C/S模型中的S,也就是伺服器端,客戶端通過命令快取資料。
基本特點:

  • 協議簡單:使用基於文字行的協議,二進位制協議使用比較少。
  • 基於記憶體儲存:資料儲存在記憶體中,所以讀取速度很快。
  • 事件處理:基於libevent開發,所以可以應對C10問題。
  • 不互相通訊的分散式:多臺memcached伺服器之間不互相通訊,由客戶端實現分散式演算法,所以通常客戶端使用一致性hash策略,通常擁有快隔離,慢恢復的特性。
    這裡寫圖片描述

安裝與啟動

memcached區別於libevent,因為memcached是一個執行程式,不需要編譯成動態連線庫,供其他程式呼叫。所以不需要指定最後庫檔案生成的目錄,僅僅需要指定memcached應用程式放置的目錄,以及編譯過程中libevent庫檔案的目錄。
本機設定應用程式防止預設目錄/usr/local/bin


libevent庫目錄為/usr/loacl/bin。因此安裝很容易了。

ar -zxv -f memcached-1.4.21.tar.gz
cd memcached-1.4.21
./configure --with-libevent=/usr/local/bin CFLAGS="-g -O0"//指定libevent庫目錄以及 編譯成debug版本。
make
make install//install之後,在/usr/local/bin會出現memcached應用程式。

//下面是make install之後的輸出,可以看到。
1、memcached.1 放到了 '/usr/local/share/man/man1'
,以後可以通過man memcached訪問幫助文件。 2、protocol_binary.h協議標頭檔案放到了 '/usr/local/include/memcached' memcached可執行檔案放到了'/usr/local/bin' 3、通常一個開原始碼,裡面會有man資料夾,也就是通過man程式可以開啟的文件,libmemcached-1.0.18裡面一樣有,通常make install會將這些檔案都放到Linux對應的資料夾,然後就可以通過man尋找幫助資訊了,很方便。 make install-recursive make[1]: Entering directory '/home/wangjun/Desktop/memcached-1.4.21' Making install in doc make[2]: Entering directory '/home/wangjun/Desktop/memcached-1.4.21/doc' make install-am make[3]: Entering directory '/home/wangjun/Desktop/memcached-1.4.21/doc' make[4]: Entering directory '/home/wangjun/Desktop/memcached-1.4.21/doc' make[4]: Nothing to be done for 'install-exec-am'. /bin/mkdir -p '/usr/local/share/man/man1' /usr/bin/install -c -m 644 memcached.1 '/usr/local/share/man/man1' make[4]: Leaving directory '/home/wangjun/Desktop/memcached-1.4.21/doc' make[3]: Leaving directory '/home/wangjun/Desktop/memcached-1.4.21/doc' make[2]: Leaving directory '/home/wangjun/Desktop/memcached-1.4.21/doc' make[2]: Entering directory '/home/wangjun/Desktop/memcached-1.4.21' make[3]: Entering directory '/home/wangjun/Desktop/memcached-1.4.21' /bin/mkdir -p '/usr/local/bin' /usr/bin/install -c memcached '/usr/local/bin' /bin/mkdir -p '/usr/local/include/memcached' /usr/bin/install -c -m 644 protocol_binary.h '/usr/local/include/memcached' make[3]: Leaving directory '/home/wangjun/Desktop/memcached-1.4.21' make[2]: Leaving directory '/home/wangjun/Desktop/memcached-1.4.21' make[1]: Leaving directory '/home/wangjun/Desktop/memcached-1.4.21'

啟動:
簡單的啟動命令如下,設定-l和-p分別用來設定ip和監聽的埠。-vv是輸出一些執行資訊。
$memcached -l 192.168.1.112 -p 8888 -vv

-vv指示輸出相應的除錯資訊,看了原始碼就知道是怎麼回事了。

工具memcached-tool

#!/usr/bin/perl
#
# memcached-tool:
#   stats/management tool for memcached.
#
# Author:
#   Brad Fitzpatrick <[email protected]>
#
# License:
#   public domain.  I give up all rights to this
#   tool.  modify and copy at will.
#

use strict;
use IO::Socket::INET;

my $host = shift;
my $mode = shift || "display";
my ($from, $to);

if ($mode eq "display") {
    undef $mode if @ARGV;
} elsif ($mode eq "move") {
    $from = shift;
    $to = shift;
    undef $mode if $from < 6 || $from > 17;
    undef $mode if $to   < 6 || $to   > 17;
    print STDERR "ERROR: parameters out of range\n\n" unless $mode;
} elsif ($mode eq 'dump') {
    ;
} elsif ($mode eq 'stats') {
    ;
} else {
    undef $mode;
}

undef $mode if @ARGV;

die 
"Usage: memcached-tool <host[:port]> [mode]\n
       memcached-tool 10.0.0.5:11211 display    # shows slabs
       memcached-tool 10.0.0.5:11211            # same.  (default is display)
       memcached-tool 10.0.0.5:11211 stats      # shows general stats
       memcached-tool 10.0.0.5:11211 move 7 9   # takes 1MB slab from class #7
                                                # to class #9.

You can only move slabs around once memory is totally allocated, and only
once the target class is full.  (So you can't move from #6 to #9 and #7
to #9 at the same itme, since you'd have to wait for #9 to fill from
the first reassigned page)
" unless $host && $mode;

$host .= ":11211" unless $host =~ /:\d+/;

my $sock = IO::Socket::INET->new(PeerAddr => $host,
                 Proto    => 'tcp');
die "Couldn't connect to $host\n" unless $sock;


if ($mode eq "move") {
    my $tries = 0;
    while (1) {
    print $sock "slabs reassign $from $to\r\n";
    my $res = <$sock>;
    $res =~ s/\s+//;
    if ($res eq "DONE") {
        print "Success.\n";
        exit 0;
    } elsif ($res eq "CANT") {
        print "Error: can't move from $from to $to.  Destination not yet full?  See usage docs.\n";
        exit;
    } elsif ($res eq "BUSY") {
        if (++$tries == 3) {
        print "Failed to move after 3 tries.  Try again later.\n";
        exit;
        }

        print "Page busy, retrying...\n";
        sleep 1;
    }
    }

    exit;
}

if ($mode eq 'dump') {
    my %items;
    my $totalitems;

    print $sock "stats items\r\n";

    while (<$sock>) {
        last if /^END/;
        if (/^STAT items:(\d*):number (\d*)/) {
            $items{$1} = $2;
            $totalitems += $2;
        }
    }
    print STDERR "Dumping memcache contents\n";
    print STDERR "  Number of buckets: " . scalar(keys(%items)) . "\n";
    print STDERR "  Number of items  : $totalitems\n";

    foreach my $bucket (sort(keys(%items))) {
        print STDERR "Dumping bucket $bucket - " . $items{$bucket} . " total items\n";
        print $sock "stats cachedump $bucket $items{$bucket} 1\r\n";
        my %keyexp;
        while (<$sock>) {
            last if /^END/;
            # return format looks like this
            # ITEM foo [6 b; 1176415152 s]
            if (/^ITEM (\S+) \[.* (\d+) s\]/) {
                $keyexp{$1} = $2;
            }
        }

        foreach my $k (keys(%keyexp)) {
            my $val;
            print $sock "get $k\r\n";
            my $response = <$sock>;
            $response =~ /VALUE (\S+) (\d+) (\d+)/;
            my $flags = $2;
            my $len = $3;
            read $sock, $val , $len;
            # get the END
            $_ = <$sock>;
            $_ = <$sock>;
            print "add $k $flags $keyexp{$k} $len\r\n$val\r\n";
        }
    }
    exit;
}

if ($mode eq 'stats') {
    my %items;

    print $sock "stats\r\n";

    while (<$sock>) {
        last if /^END/;
        chomp;
        if (/^STAT\s+(\S*)\s+(.*)/) {
            $items{$1} = $2;
        }
    }
    printf ("#%-17s %5s %11s\n", $host, "Field", "Value");
    foreach my $name (sort(keys(%items))) {
      printf ("%24s %12s\n", $name, $items{$name});

    }
    exit;
}

# display mode:

my %items;  # class -> { number, age, chunk_size, chunks_per_page,
            #            total_pages, total_chunks, used_chunks,
            #            free_chunks, free_chunks_end }

print $sock "stats items\r\n";
while (<$sock>) {
    last if /^END/;
    if (/^STAT items:(\d+):(\w+) (\d+)/) {
    $items{$1}{$2} = $3;
    }
}

print $sock "stats slabs\r\n";
while (<$sock>) {
    last if /^END/;
    if (/^STAT (\d+):(\w+) (\d+)/) {
    $items{$1}{$2} = $3;
    }
}

print "  #  Item_Size   Max_age  1MB_pages Count   Full?\n";
foreach my $n (1..40) {
    my $it = $items{$n};
    next if (0 == $it->{total_pages});
    my $size = $it->{chunk_size} < 1024 ? "$it->{chunk_size} B " : 
    sprintf("%.1f kB", $it->{chunk_size} / 1024.0);
    my $full = $it->{free_chunks_end} == 0 ? "yes" : " no";
    printf "%3d   %8s %7d s %7d %7d %7s\n",
                        $n, $size, $it->{age}, $it->{total_pages},
                        $it->{number}, $full;
}

1、memcached-tool指令碼可以方便地獲得slab的使用情況。

2、使用方法也極其簡單:perl memcached-tool server_ip:prot option

3、有了這個工具就需要自己寫指令碼,連線客戶端,傳送相應的資訊了,這個就很容易使用了,其實獲取資訊的方法就是給伺服器端傳送相應的指令。

Memcached啟動命令列引數詳解

啟動Memcached時候,可以通過命令列引數配置。主要通過修改struct settings中的變數值,修改整個memcached工作引數。以下介紹struct settings結構體以及其預設初始值。

//原始碼內部使用的設定結構體
struct settings {
    size_t maxbytes;
    int maxconns;
    int port;
    int udpport;
    char *inter;
    int verbose;
    rel_time_t oldest_live; /* ignore existing items older than this */
    int evict_to_free;
    char *socketpath;   /* path to unix socket if using local socket */
    int access;  /* access mask (a la chmod) for unix domain socket */
    double factor;          /* chunk size growth factor */
    int chunk_size;
    int num_threads;        /* number of worker (without dispatcher) libevent threads to run */
    int num_threads_per_udp; /* number of worker threads serving each udp socket */
    char prefix_delimiter;  /* character that marks a key prefix (for stats) */
    int detail_enabled;     /* nonzero if we're collecting detailed stats */
    int reqs_per_event;     /* Maximum number of io to process on each
                               io-event. */
    bool use_cas;
    enum protocol binding_protocol;
    int backlog;
    int item_size_max;        /* Maximum item size, and upper end for slabs */
    bool sasl;              /* SASL on/off */
    bool maxconns_fast;     /* Whether or not to early close connections */
    bool lru_crawler;        /* Whether or not to enable the autocrawler thread */
    bool slab_reassign;     /* Whether or not slab reassignment is allowed */
    int slab_automove;     /* Whether or not to automatically move slabs */
    int hashpower_init;     /* Starting hash power level */
    bool shutdown_command; /* allow shutdown command */
    int tail_repair_time;   /* LRU tail refcount leak repair time */
    bool flush_enabled;     /* flush_all enabled */
    char *hash_algorithm;     /* Hash algorithm in use */
    int lru_crawler_sleep;  /* Microsecond sleep between items */
    uint32_t lru_crawler_tocrawl; /* Number of items to crawl per run */
};

struct settings settings;//全域性結構體變數

//memcached的main函式啟動,首先會此函式,初始化預設設定。
static void settings_init(void) {  
    //開啟CAS業務,如果開啟了那麼在item裡面就會多一個用於CAS的欄位。可以在啟動memcached的時候通過-C選項禁用  
    settings.use_cas = true;  

    settings.access = 0700; //unix socket的許可權位資訊  
    settings.port = 11211;//memcached監聽的tcp埠  
    settings.udpport = 11211;//memcached監聽的udp埠  
    //memcached繫結的ip地址。如果該值為NULL,那麼就是INADDR_ANY。否則該值指向一個ip字串  
    settings.inter = NULL;  

    settings.maxbytes = 64 * 1024 * 1024; //memcached能夠使用的最大記憶體  
    settings.maxconns = 1024; //最多允許多少個客戶端同時線上。不同於settings.backlog  

    settings.verbose = 0;//執行資訊的輸出級別.該值越大輸出的資訊就越詳細  
    settings.oldest_live = 0; //flush_all命令的時間界限。插入時間小於這個時間的item刪除。  
    settings.evict_to_free = 1;  //標記memcached是否允許LRU淘汰機制。預設是可以的。可以通過-M選項禁止    
    settings.socketpath = NULL;//unix socket監聽的socket路徑.預設不使用unix socket   
    settings.factor = 1.25; //item的擴容因子  
    settings.chunk_size = 48; //最小的一個item能儲存多少位元組的資料(set、add命令中的資料)  
    settings.num_threads = 4; //worker執行緒的個數  
     //多少個worker執行緒為一個udp socket服務 number of worker threads serving each udp socket  
    settings.num_threads_per_udp = 0;  

    settings.prefix_delimiter = ':'; //分隔符  
    settings.detail_enabled = 0;//是否自動收集狀態資訊  

    //worker執行緒連續為某個客戶端執行命令的最大命令數。這主要是為了防止一個客戶端霸佔整個worker執行緒  
    //,而該worker執行緒的其他客戶端的命令無法得到處理  
    settings.reqs_per_event = 20;  

    settings.backlog = 1024;//listen函式的第二個引數,不同於settings.maxconns  
    //使用者命令的協議,有檔案和二進位制兩種。negotiating_prot是協商,自動根據命令內容判斷  
    settings.binding_protocol = negotiating_prot;  
    settings.item_size_max = 1024 * 1024;//slab記憶體頁的大小。單位是位元組  
    settings.maxconns_fast = false;//如果連線數超過了最大同時線上數(由-c選項指定),是否立即關閉新連線上的客戶端。  

    //用於指明memcached是否啟動了LRU爬蟲執行緒。預設值為false,不啟動LRU爬蟲執行緒。  
    //可以在啟動memcached時通過-o lru_crawler將變數的值賦值為true,啟動LRU爬蟲執行緒  
    settings.lru_crawler = false;  
    settings.lru_crawler_sleep = 100;//LRU爬蟲執行緒工作時的休眠間隔。單位為微秒   
    settings.lru_crawler_tocrawl = 0; //LRU爬蟲檢查每條LRU佇列中的多少個item,如果想讓LRU爬蟲工作必須修改這個值  

    //雜湊表的長度是2^n。這個值就是n的初始值。可以在啟動memcached的時候通過-o hashpower_init  
    //設定。設定的值要在[12, 64]之間。如果不設定,該值為0。雜湊表的冪將取預設值16  
    settings.hashpower_init = 0;  /* Starting hash power level */  

    settings.slab_reassign = false;//是否開啟調節不同型別item所佔的記憶體數。可以通過 -o slab_reassign選項開啟  
    settings.slab_automove = 0;//自動檢測是否需要進行不同型別item的記憶體調整,依賴於settings.slab_reassign的開啟  

    settings.shutdown_command = false;//是否支援客戶端的關閉命令,該命令會關閉memcached程序  

    //用於修復item的引用數。如果一個worker執行緒引用了某個item,還沒來得及解除引用這個執行緒就掛了  
    //那麼這個item就永遠被這個已死的執行緒所引用而不能釋放。memcached用這個值來檢測是否出現這種  
    //情況。因為這種情況很少發生,所以該變數的預設值為0(即不進行檢測)。  
    //在啟動memcached時,通過-o tail_repair_time xxx設定。設定的值要大於10(單位為秒)  
    //TAIL_REPAIR_TIME_DEFAULT 等於 0。  
    settings.tail_repair_time = TAIL_REPAIR_TIME_DEFAULT;   
    settings.flush_enabled = true;//是否執行客戶端使用flush_all命令  
}

//然後通過命令列引數,修改對應的值。  
while (-1 != (c = getopt(argc, argv,
          "a:"  /* access mask for unix socket */
          "A"  /* enable admin shutdown commannd */
          "p:"  /* TCP port number to listen on */
          "s:"  /* unix socket path to listen on */
          "U:"  /* UDP port number to listen on */
          "m:"  /* max memory to use for items in megabytes */
          "M"   /* return error on memory exhausted */
          "c:"  /* max simultaneous connections */
          "k"   /* lock down all paged memory */
          "hi"  /* help, licence info */
          "r"   /* maximize core file limit */
          "v"   /* verbose */
          "d"   /* daemon mode */
          "l:"  /* interface to listen on */
          "u:"  /* user identity to run as */
          "P:"  /* save PID in file */
          "f:"  /* factor? */
          "n:"  /* minimum space allocated for key+value+flags */
          "t:"  /* threads */
          "D:"  /* prefix delimiter? */
          "L"   /* Large memory pages */
          "R:"  /* max requests per event */
          "C"   /* Disable use of CAS */
          "b:"  /* backlog queue limit */
          "B:"  /* Binding protocol */
          "I:"  /* Max item size */
          "S"   /* Sasl ON */
          "F"   /* Disable flush_all */
          "o:"  /* Extended generic options */
        ))) {
        switch (c) {
        ........
        }
}   

從上面分析流程可知,首先定義結構體變數,然後初始化其部分變數,最後通過迴圈處理命令列引數,設定對應的值。很簡單的過程,下面詳細解釋每個命令列引數對應的功能,加粗的部分是比較常用的指令,現在對於這些指令不太理解每關係,搞懂了後面的原始碼剖析,那麼命令就非常懂了。

  • “A”:是否執行客戶端使用shutdown命令。預設是不允許的。該選項將允許。客戶端的shutdown命令會將memcached程序殺死。該選項會將settings.shutdown_command賦值為true
  • “a”:unix socket的許可權位資訊(訪問掩碼)。該選項的引數賦值給settings.access
  • “U:”:大寫U。memcached監聽的UDP埠值,預設埠為11211。該選項的引數賦值給settings.udpport
  • “p:”:小寫p,memcached監聽的tcp埠。預設埠為11211, 該選項的引數賦值給settings.port
  • “s:”:小寫s。unix socket監聽的socket路徑。該選項的引數賦值給settings.socketpath
  • “m:”:小寫m。memcached能夠使用的最大記憶體值,預設是64MB。引數單位為MB。該引數賦值給settings.maxbytes
  • “M”:大寫M。預設情況下,當memcached的記憶體使用完後,將進行LRU機制淘汰item以騰出空間。如果使用本選項那麼將關閉LRU功能。當然關閉LRU不代表不能儲存新資料。如果memcached裡面存有過期失效的item,那麼就可以儲存新資料。否則將無法儲存。該選項將settings.evict_to_free賦值為0。
  • “c:”:小寫c。每個執行緒最多允許多少個客戶端同時線上(這個值不等價於listen函式的第二個引數),該選項和後面的b選項有所不同。 預設值為1024個。該選項引數賦值給settings.maxconns
  • “h”:顯示幫助資訊。
  • “i”:顯示memcached和libevent的版權資訊。
  • “k”:小寫k。將memcached使用到的記憶體鎖定在記憶體中,不準OS把memcached的記憶體移動到虛擬記憶體。因為當OS把memcached的記憶體移動到虛擬記憶體可能會導致頁錯誤,降低memcached的響應時間。
  • “v”:小寫v。輸出memcached執行時的一些資訊。-v -vv -vvv輸出的資訊依次增加。該選項會增加settings.verbose的值。
  • “l:”:小寫L。memcached繫結的ip地址。如果不設定這個選項,那麼memcached將使用INADDR_ANY。如果想指定多個IP地址,那麼該選項的引數可以由多個ip組成,ip之間用逗號分隔。也可以多次使用這個選項,此時埠應該尾隨ip而不是單獨用-p選項指定。例如-l 127.0.0.1:8888,192.168.1.112:9999 或者 -l 127.0.0.1:8888 -l 192.168.1.112:9999該選項引數將賦值給settings.inter
  • “d”:以守護程序的形式執行memcached。
  • “r”:將core檔案大小設定為不受限制。
  • “R:”:worker執行緒連續為某個客戶端執行命令的最大命令數。該選項的引數賦值給settings.reqs_per_event
  • “u:”:小寫u。當以root使用者啟動memcached的時候需要指定memcached的所屬使用者,其他使用者啟動memcached不需要此選項
  • “P:”:大寫p。該選項的引數指明memcached的pid儲存檔案。要和-d選項配合使用。注意執行的使用者是否有許可權寫對應的檔案。
  • “f:”:item的擴容因子。預設值為1.25。該選項的引數值可以是小數但必須大於1.0。該選項引數將賦值給settings.factor
  • “n:”:設定最小的item(key+value+flags)能儲存多少位元組的資料。該選項引數賦值給settings.chunk_size
  • “t:”:該選項的引數用於指定worker執行緒的個數,不建議超過64個。如果不設定該選項預設有4個執行緒。該引數會賦值給settings.num_threads
  • “D:”:引數字元作為字首和ID的分隔符。使用了該選項才會自動收集狀態資訊。也可以在啟動memcached後,客戶端使用stats detail on命令開啟,此時預設的分隔符為冒號”:”。該選項引數會賦值為settings.prefix_delimiter,並將settings.detail_enabled賦值為1。
  • “L”:如果OS允許的話,那麼向OS申請更大的記憶體頁。OS的預設記憶體頁為4KB。大的記憶體頁可以有效降低頁表的大小,提高效率。此選項會使得memcached預先先OS全部所需的申請記憶體。當然這些記憶體儘量是用大記憶體頁分配的。
  • “C:” :大寫C。memcached預設是使用CAS的,本選項是禁用CAS。本選項會將settings.use_cas賦值為false。
  • “b:”:listen函式的第二個引數。該選項的引數賦值給settings.backlog。如果不設定該選項,那麼預設為1024。該選項和前面的c選項有所不同。
  • “B:”:memcached支援文字協議和二進位制協議。該選項的引數用於指定使用的協議。預設情況下是根據客戶端的命令而自動判斷(也叫協商),引數只能取auto、binary、ascii這三個字串值。將引數將賦值給settings.binding_protocol
  • “I:”:大寫i。slab分配器中,每一個頁的大小。這個選項的引數是一個數值表示頁的大小。預設單位是B也可以在數值後面帶K或者M(大小寫都行),表示KB和MB。頁的大小小於1KB或者大於128MB都是不允許的。不推薦使用該選項。本選項引數會賦值給settings.item_size_max
  • “S”:大寫S。開啟sasl安全協議。會將settings.sasl賦值為true。
  • “F”:禁止客戶端的flush_all命令。預設是允許客戶端的flush_all命令的。該選項將settings.flush_enabled賦值為false。
  • “o:”:小寫o。啟動擴充套件選項,有下面幾個子選項可以設定。這個選項是用來優化的。
    • maxconns_fast:如果連線數超過了最大同時線上數(由-c選項指定),立即關閉新連線上的客戶端。該選項將settings.maxconns_fast賦值為true。
    • hashpower:雜湊表的長度是2^n。可以通過選項hashpower設定指數n的初始值。如果不設定將取預設值16。該選項必須有引數,引數取值範圍只能為[12, 64]。本選項引數值賦值給settings.hashpower_init。
    • slab_reassign: 該選項沒有引數。用於調節不同型別的item所佔的記憶體。不同型別是指大小不同。某一類item已經很少使用了,但仍佔用著記憶體。可以通過開啟slab_reassign排程記憶體,減少這一類item的記憶體。如果使用了本選項,settings.slab_reassign賦值為true。
    • slab_automove:依賴於slab_reassign。用於主動檢測是否需要進行記憶體排程。該選項的引數是可選的。引數的取值範圍只能為0、1、2。引數2是不建議的。本選項引數賦值給settings.slab_automove。如果本選項沒有引數,那麼settings.slab_automove賦值為1。
    • hash_algorithm:用於指定雜湊演算法。該選項必須帶有引數。並且引數只能是字串jenkins或者murmur3。
    • tail_repair_time:用於檢測是否有item被已死執行緒所引用。一般不會出現這種情況,所以預設不開啟這種檢測。如果需要開啟這種檢測,那麼需要使用本選項。本選項需要一個引數,引數值必須不小於10。該引數賦值給settings.tail_repair_time。
    • lru_crawler:本選項用於啟動LRU爬蟲執行緒。該選項不需要引數。本選項會導致settings.lru_crawler賦值為true。
    • lru_crawler_sleep:LRU爬蟲執行緒工作時的休眠間隔。本選項需要一個引數作為休眠時間,單位為微秒,取值範圍是[0, 1000000]。該引數賦值給settings.lru_crawler_sleep。
    • lru_crawler_tocrawl:LRU爬蟲檢查每條LRU佇列中的多少個item。該選項帶有一個引數。引數會賦值給settings.lru_crawler_tocrawl。

Memcached連線及儲存命令

////////////////////////////////////////1、啟動
memcached -m 64 -p 11211 -vvv //slabs大小 埠 列印資訊等級

////////////2、連線,客戶端和伺服器連線比較簡單,基於文字而不是二進位制,所以基於使telent即可
$ telnet localhost 11211  //連線
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get foo   //輸入指令
VALUE foo 0 2
hi
END
stats
STAT pid 8861
quit   //telnet退出指令

///////////////////////////////3、命令介紹
First, the client sends a command line which looks like this:
<command name> <key> <flags> <exptime> <bytes> [noreply]\r\n
cas <key> <flags> <exptime> <bytes> <cas unique> [noreply]\r\n

<command name>是"set", "add", "replace", "append" or "prepend"
"set" :“儲存這個資料”,一般是更新已有的快取,也可以用於新增。
"add" :新增快取,快取中不存在新增的KEY。
"Replace":替換現有的快取,快取中一定已經儲存KEY
"Append":在現有的快取資料後新增快取資料。
"Prepend":在現有的快取資料前新增快取資料
"Cas":check and set操作,儲存快取,前提是在check後沒有其它人修改過資料,用於多客戶端同時設定相同的KEY時的原子操作。
"key":快取的KEY
"flags":最開始是16位的無符號整數,現在的版本一般是32位。使用者客戶端儲存自定義標記資料,客戶端自定義這個資料如何儲存,例如我經過壓縮儲存標記為1,那麼這個返回的時候flag會是1,然後就知道是經過壓縮的,那麼客戶端庫會反壓縮給應用使用。一種標記作用而已。具體如何處理,需要客戶端處理。
"exptime":快取過期時間。0表示不自動失效,可以是Unix time或當前伺服器時間的偏移量(秒為單位),如果你想設定當前時間後1分鐘過期,則此引數為60。
設定秒數:從設定開始數,第n秒後失效。
時間戳, 到指定的時間戳後失效。

"bytes":快取資料的長度
"cas unique":unique 64-bit value of an existing entry,cas操作的時候回傳的值,用於伺服器端判斷快取是否改變。
"noreply":伺服器不響應處理結果。

After this line, the client sends the data block:
<data block>\r\n  //\r\n結束

After sending the command line and the data blockm the client awaits
the reply, which may be:

"STORED\r\n":表示儲存成功。
"NOT_STORED\r\n":表示未儲存,但並不是錯誤。如:對已經有的KEY使用add。
"EXISTS\r\n":表示使用cas命令設定資料未成功,在你最後一次獲取資料後,資料已經被其它人修改。
"NOT_FOUND\r\n":表示使用cas儲存資料時候,key不儲存。

//4、命令使用介紹

////////////////////////////////////////////////
delete刪除一個已經存在的鍵
get key  
VALUE key 0 12  
prepend12345  
END  
delete key  
DELETED  
get key  
END 

/////////////////////////////////////
add增加一個不存在的key
存在,則返回錯誤。
不存在則成功。
telnet localhost 11211  
add key 0 0 5  
12345  
STORED  
add key 0 0 1  
1  
NOT_STORED 

/////////////////////////////////////
repalce替換已經存在的key值
不存在,則錯誤
存在,則修改
replace key 0 0 3  
123  
STORED  
replace key1 0 0 3  
123  
NOT_STORED    //key1不存在 

///////////////////////////////////
set設定鍵
存在,則修改
不存在,則新增,總和add和repalce功能。
set key 0 0 2  
12  
STORED  
/////////////////////////////////////
append :是在現有快取資料後面新增資料。如果 key 不存在,伺服器響應 NOT_STORED

get key  
VALUE key 0 3  
123  
END  
append key 0 0 2  
45  
STORED  
get key  
VALUE key 0 5  
12345  
END  

prepend 是在現有快取資料前面新增資料。如果 key 不存在,伺服器響應 NOT_STORED
get key  
VALUE key 0 5  
12345  
prepend key 0 0 7  
prepend  
STORED  
get key  
VALUE key 0 12  
prepend12345  
END  
prepend key1 0 0 1  
1  
NOT_STORED  
////////////////////////////////////////////////////////////////////
incr,decr 命令:增加/減少值的大小
如果快取資料中儲存的是數字形式的字串,則可以使用incr/decr對資料進行遞增和遞減操作,伺服器響應操作過的結果。操作後的值不會為負數。
格式: incr/decr key number\r\n
add key 0 0 2  
10  
STORED  
incr key 1    // 遞增 1  
11  
decr key 2    // 遞減 2  
9  
add key1 0 0 2  
aa  
STORED  
incr key1 1   // 對非數字的快取操作會返回錯誤  
CLIENT_ERROR cannot increment or decrement non-numeric value  

應用場景------秒殺功能,
一個人下單,要牽涉資料庫讀取,寫入訂單,更改庫存,及事務要求, 對於傳統型資料庫來說,
壓力是巨大的。
可以利用memcached的incr/decr功能, 在記憶體儲存count庫存量,秒殺1000臺
每人搶單主要在記憶體操作,速度非常快,搶到count<=1000 的號人,得一個訂單號,再去另一個頁面慢慢支付,相當於通過這個實現了一個原子操作,因為在memcached內部訪問同一個items是原子的,這種資料庫分離的操作使用起來很方便。

////////////////////////////////////////////////////////////////////
stats命令
 用於把memcached當前的執行資訊全部統計出來。
stats item命令
 用於檢視條目狀態。
stats slabs命令
 檢視記憶體情況

stats命令的顯示如下圖:
這裡寫圖片描述

2、Libmemcached

介紹

memcached通常以伺服器的形式執行,雖然稱memcached是分散式資料庫,但是其服務端本身不支援分散式業務,這就需要客戶端自己實現分佈管理以及記憶體池功能。Libmemcached是一個開源的Memcached客戶端庫,其內部實現了分散式管理、記憶體池等功能。通過API的形式提供出來,使用程式設計師可以專心上層業務邏輯,避免底層與memcached互動的細節,所以Libmemcached編譯,安裝之後就會以動態庫的方式提供出來給程式設計師呼叫。注意連結串列的時候必須指定-lmemcached。如果是QT建立工程,那麼必須在*pro檔案裡面加入這句話LIBS += -L/usr/local/lib -lmemcached

Libmemcached特性:

  • 非同步和同步傳輸支援。
  • 支援一致性hash分散式演算法。
  • 可調雜湊演算法來匹配金鑰。
  • 訪問大物件支援。
  • 本地複製。
  • 提供了一些管理memcached伺服器的工具命令

安裝

下載最新版、解壓、./configure 、 make 、 make install三步。
響應的庫檔案和標頭檔案分別位於/usr/local/lib、/usr/loacl/include/libmemcached
其中標頭檔案夾中包含有三個檔案。
1、memcached.h:庫對應的c介面
2、memcached.hpp:將對應的c介面封裝成c++介面,所以c++使用起來可能更加方便
3、util.h:基於庫實現的一些高階功能,例如連線池的功能,就在這個標頭檔案中實現。
需要使用庫,包含上述響應的標頭檔案即可,可以肯定,庫的作者已經幫助我們做好了一切,我們僅僅需要呼叫,就可以和伺服器memcached通訊存值。

這裡寫程式碼片

基本函式呼叫說明

程式設計師可呼叫的函式標頭檔案全