memcached安裝與應用
什麽是Nosql
非關系型數據庫就是NoSQL,關系型數據庫代表MySQL
對於關系型數據庫來說,是需要把數據存儲到庫、表、行、字段裏,查詢的時候根據條件一行一行地去匹配,當量非常大的時候就很耗費時間和資源,尤其是數據是需要從磁盤裏去檢索
NoSQL數據庫存儲原理非常簡單(典型的數據類型為k-v),不存在繁雜的關系鏈,比如mysql查詢的時候,需要找到對應的庫、表(通常是多個表)以及字段。
NoSQL數據可以存儲在內存裏,查詢速度非常快
NoSQL在性能表現上雖然能優於關系型數據庫,但是它並不能完全替代關系型數據庫
NoSQL因為沒有復雜的數據結構,擴展非常容易,支持分布式
常見Nosql數據庫
k-v形式的:memcached、redis 適合儲存用戶信息,比如會話、配置文件、參數、購物車等等。這些信息一般都和ID(鍵)掛鉤,這種情景下鍵值數據庫是個很好的選擇。
文檔數據庫:mongodb 將數據以文檔的形式儲存。每個文檔都是一系列數據項的集合。每個數據項都有一個名稱與對應的值,值既可以是簡單的數據類型,如字符串、數字和日期等;也可以是復雜的類型,如有序列表和關聯對象。數據存儲的最小單位是文檔,同一個表中存儲的文檔屬性可以是不同的,數據可以使用XML、JSON或者JSONB等多種形式存儲。
列存儲 Hbase
圖 Neo4J、Infinite Graph、OrientDB
21.2memcached介紹
系統環境:centos 7.x86_64
Memcached是國外社區網站LiveJournal團隊開發,目的是為了通過緩存數據庫查詢結果,減少數據庫訪問次數,從而提高動態web站點性能。
官方站點 http://www.memcached.org/
數據結構簡單(k-v),數據存放在內存裏
多線程
基於c/s架構,協議簡單
基於libevent的事件處理
自主內存存儲處理(slab allowcation)
數據過期方式:Lazy Expiration 和LRU
slab allowcation原理
將分配的內存分割成各種尺寸的塊(chunk), 並把尺寸相同的塊分成組(chunk的集合),每個chunk集合被稱為slab。
Slab是由多個Page組成的,Page按照指定大小切割成多個chunk。
mark
growth factor
Memcached在啟動時通過-f選項可以指定 Growth Factor因子。該值控制chunk大小的差異。默認值為1.25。
通過memcached-tool命令查看指定Memcached實例的不同slab狀態,可以看到各Item所占大小(chunk大小)差距為1.25
命令:# memcached-tool 127.0.0.1:11211 display
memcached數據過期方式
Lazy Expiration
Memcached 內部不會監視記錄是否過期,而是在get時查看記錄的時間戳,檢查記錄是否過期。這種技術被稱為lazy(惰性)expiration。因此,Memcached不會在過期監視上耗費CPU時間。
LRU
Memcached會優先使用已超時的記錄的空間,但即使如此,也會發生追加新記錄時空間不足的情況,此時就要使用名為Least Recently Used(LRU)機制來分配空間。顧名思義,這是刪除“最近最少使用”的記錄的機制。因此,當內存空間不足時(無法從slab class獲取到新的空間時),就從最近未被使用的記錄中搜索,並將其空間分配給新的記錄。從緩存的實用角度來看,該模型十分理想。
21.3安裝memcached
官方版本:
mark
本次實驗使用系統自帶版本:memcached.x86_64 1.4.15-10.el7_3.1
安裝
[root@adailinux ~]# yum install -y memcached libmemcached libevent
#memcached依賴於libevent和libmemecached,如果系統沒有安裝這兩個包,需要手動安裝。
啟動
[root@adailinux ~]# systemctl start memcached
[root@adailinux ~]# ps aux |grep memcached
memcach+ 2363 0.7 0.2 325556 1192 ? Ssl 16:15 0:00 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024
root 2370 0.0 0.1 112664 972 pts/0 S+ 16:15 0:00 grep --color=auto memcached
說明:
-u:表示指定用戶
-p:表示監聽端口
-m:表示分配的內存
-c:表示最大並發數
[root@adailinux ~]# netstat -lntp |grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0: LISTEN 2363/memcached
tcp6 0 0 :::11211 ::: LISTEN 2363/memcached
memcached啟動參數配置:
[root@adailinux ~]# vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""
說明: OPTIONS可以自定義選項,可以使用“memcached -h”查看其選項。
21.4 查看memcached的狀態
方法1:
[root@adailinux ~]# memcached-tool 127.0.0.1:11211 stats
方法2:(前提是安裝了libmemcached包)
[root@adailinux ~]# memstat --servers=127.0.0.1:11211
方法3:
[root@adailinux ~]# telnet 127.0.0.1 11211
#連接memcached
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
stats
#查看memcached的狀態
STAT pid 1277 (進程ID)
STAT uptime 176145 (服務器運行秒數,秒)
STAT time 1448592684 (服務器當前unix時間戳)
STAT version 1.4.15 (服務器版本)
STAT libevent 2.0.21-stable
STAT pointer_size 64 (操作系統字大小 32/64位)
STAT rusage_user 3.869494 (進程累計用戶時間,秒)
STAT rusage_system 4.636292 (進程累計系統時間,秒)
STAT curr_connections 11 (當前打開連接數)
STAT total_connections 21 (曾打開的連接總數)
STAT connection_structures 12 (服務器分配的連接結構數)
STAT reserved_fds 20
STAT cmd_get 483 (執行get命令總數)
STAT cmd_set 144 (執行set命令總數)
STAT cmd_flush 0 (指向flush_all命令總數)
STAT cmd_touch 0
STAT get_hits 369 (get命中次數)
STAT get_misses 114 (get未命中次數)
STAT delete_misses 0 (delete未命中次數)
STAT delete_hits 0 (delete命中次數)
STAT incr_misses 0 (incr未命中次數)
STAT incr_hits 0 (incr命中次數)
STAT decr_misses 0 (decr未命中次數)
STAT decr_hits 0 (decr命中次數)
STAT cas_misses 0 (cas未命中次數)
STAT cas_hits 0 (cas命中次數)
STAT cas_badval 0 (使用擦拭次數)
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 82819 (讀取字節總數)
STAT bytes_written 104266 (寫入字節總數)
STAT limit_maxbytes 67108864 (分配的內存數(字節))
STAT accepting_conns 1 (目前接受的連接數)
STAT listen_disabled_num 0
STAT threads 4 (線程數)
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT bytes 4789 (存儲item字節數)
STAT curr_items 20 (item個數)
STAT total_items 144 (item總數)
STAT expired_unfetched 15
STAT evicted_unfetched 0
STAT evictions 0 (獲取空間刪除item的總數)
STAT reclaimed 36
END
quit
#退出
Connection closed by foreign host.
說明: 需要經常關註:get_hits(get命中次數)和curr _items(當前項目數)的比值,該比值代表其命中率。
使用nc命令查看memcached狀態
[root@adailinux ~]# yum install -y nc
[root@adailinux ~]# echo stats |nc 127.0.0.1 11211
21.5 memcached命令行
[root@adailinux ~]# telnet 127.0.0.1 11211
#連接到memcached
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
###按Ctrl+]或者輸入quit可以退出
set adai 0 30 2
#添加數據
ab
STORED
說明:
adai:鍵值名稱;
0:標記,記錄額外信息
30:數據保留時長
2:數據長度(字符數)
get adai
#查看數據
VALUE adai 0 2
ab
END
註: 進入memcached後可以使用Ctrl+backspace鍵逐個刪除當前行數據,Ctrl+u一次性清除當前行數據。
memcached語法規則
command name set/add/replace
key 查找關鍵字
flags 客戶機使用它存儲關於鍵值對的額外信息(標記)
exptime 該數據的存活時間,0表示永遠
bytes 存儲字節數
data block 存儲的數據塊(可直接理解為key-value結構中的value)
格式: < command name > < key > < flags > < expiretime > < bytes >\r\n < data block >\r\n
<command name> 可以是"set", "add", "replace"
"set"表示按照相應的<key>存儲該數據,沒有的時候增加,有的覆蓋
"add"表示按照相應的<key>添加該數據,但是如果該<key>已經存在則會操作失敗
"replace"表示按照相應的<key>替換數據,但是如果該<key>不存在則操作失敗
<key> 客戶端需要保存數據的key
<flags> 是一個16位的無符號的整數(以十進制的方式表示)
該標誌將和需要存儲的數據一起存儲,並在客戶端get數據時返回
客戶可以將此標誌用做特殊用途,此標誌對服務器來說是不透明的
<exptime> 過期的時間
若為0表示存儲的數據永遠不過時(但可被服務器算法:LRU 等替換)
如果非0(unix時間或者距離此時的秒數),當過期後,服務器可以保證用戶得不到該數據(以服務器時間為標準)
<bytes> 需要存儲的字節數(不包含最後的"\r\n"),當用戶希望存儲空數據時,<bytes>可以為0
最後客戶端需要加上"\r\n"作為"命令頭"的結束標誌(=Enter)。
<data block>:要存儲的內容(在上述參數設置完畢後,enter後再輸入數據)
示例:
set key1 0 0 2
12
STORED
添加一個數據
get key1
VALUE key1 0 2
12
END
#查看數據
delete key1 0
DELETED
#刪除一個數據
get key1
END
quit
Connection closed by foreign host.
[root@localhost ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
set adai 0 0 3
123
STORED
get adai
VALUE adai 0 3
123
END
replace adai 2 200 5
12345
STORED
#更改數據
get adai
VALUE adai 2 5
12345
END
quit
Connection closed by foreign host.
查看數據狀態:
[root@localhost ~]# memcached-tool 127.0.0.1:11211 display
Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM
1 96B 22s 1 1 yes 0 0 0
#Item_Size項目大小(類似於塊的概念),該列以遞增的形式顯示
註: 某數據超出其expire time之後該數據就會消失,如果expire time=0,表示永不失效,可使用LRU等算法替換該數據。
21.6 memcached數據導出和導入
因為memcached數據不能持久化(重啟memcached服務數據會丟失),所以在重啟服務之前最好將其中的數據導出,待重啟完畢後再將數據導入memcached,防止數據丟失。
數據導出
準備數據:
[root@adailinux ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
set name 1 0 4
adai
STORED
set age 1 0 2
26
STORED
set weight 1 0 2
80
set high 1 0 3
180
STORED
^]
telnet> quit
Connection closed.
查看數據狀態:
[root@adailinux ~]# memstat --servers=127.0.0.1:11211
curr_items: 4
即,當前有4個項目。
導出數據:
[root@adailinux ~]# memcached-tool 127.0.0.1:11211 dump > /tmp/memdata.bak
Dumping memcache contents
Number of buckets: 1
Number of items : 4
Dumping bucket 1 - 4 total items
[root@adailinux ~]# cat /tmp/memdata.bak
add high 1 1506759339 3
180
add name 1 1506759339 4
adai
add weight 1 1506759339 2
80
add age 1 1506759339 2
26
導入數據
[root@adailinux ~]# nc 127.0.0.1 11211 < /tmp/memdata.bak
NOT_STORED
NOT_STORED
NOT_STORED
NOT_STORED
#數據已經存在,所以無法導入。
[root@adailinux ~]# systemctl restart memcached
[root@adailinux ~]# date -d "+1 hour" +%s
1506768265
#獲取1小時後的時間戳,
#將memdata.bak中的時間戳更改為該值
[root@adailinux ~]# vim /tmp/memdata.bak
add high 1 1506768265 3
180
add name 1 1506768265 4
adai
add weight 1 1506768265 2
80
add age 1 10000000 2
26
[root@adailinux ~]# nc 127.0.0.1 11211 < /tmp/memdata.bak
STORED
STORED
STORED
STORED
[root@adailinux ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
get name
VALUE name 1 4
adai
END
get age
END
get high
VALUE high 1 3
180
END
get weight
VALUE weight 1 2
80
END
註: 導出的數據是帶有一個時間戳的,這個時間戳就是該條數據過期的時間點,如果數據已經存在或者當前時間已經過了這個時間點,數據將無法成功導入。
21.7 php連接memcached
使用PHP連接memcached需要先編譯安裝PHP的memcached擴展模塊。(本機之前已經安裝過PHP,所以直接重新編譯,如果是首次安裝,需要下載安裝包。)
[root@adailinux src]# pwd
/usr/local/src
下載模塊:
[root@adailinux src]# wget http://www.apelearn.com/bbs/data/attachment/forum/memcache-2.2.3.tgz
[root@adailinux src]# tar -zxvf memcache-2.2.3.tgz
[root@adailinux src]# cd memcache-2.2.3/
[root@adailinux memcache-2.2.3]# /usr/local/php-fpm/bin/phpize
報錯:
Cannot find autoconf. Please check your autoconf installation and the
$PHP_AUTOCONF environment variable. Then, rerun this script.
即,缺少autoconf。。此時無法生產configure文件
[root@adailinux memcache-2.2.3]# yum install -y autoconf
[root@adailinux memcache-2.2.3]# /usr/local/php-fpm/bin/phpize
搞定!!
編譯:
[root@adailinux memcache-2.2.3]# ./configure --with-php-config=/usr/local/php-fpm/bin/php-config
[root@adailinux memcache-2.2.3]# echo $?
0
[root@adailinux memcache-2.2.3]# make && make install
Installing shared extensions: /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
[root@adailinux memcache-2.2.3]# ls /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
memcache.so
即,生成memcache.so模塊文件。
加載模塊:
[root@adailinux memcache-2.2.3]# vim /usr/local/php-fpm/etc/php.ini
添加如下參數:
extension=memcache.so
[root@adailinux memcache-2.2.3]# /usr/local/php-fpm/sbin/php-fpm -m
memcache
即,memcache模塊加載成功!
測試
下載測試腳本,查看PHP是否支持memcache擴展。
測試腳本內容如下:
[root@adailinux src]# vim 1.php
<?php
//連接Memcache Memcache
$mem = new Memcache;
$mem->connect("localhost", 11211);
//保存數據
$mem->set(‘key1‘, ‘This is first value‘, 0, 60);
$val = $mem->get(‘key1‘);
echo "Get key1 value: " . $val ."<br>";
//替換數據
$mem->replace(‘key1‘, ‘This is replace value‘, 0, 60);
$val = $mem->get(‘key1‘);
echo "Get key1 value: " . $val . "<br>";
//保存數組數據
$arr = array(‘aaa‘, ‘bbb‘, ‘ccc‘, ‘ddd‘);
$mem->set(‘key2‘, $arr, 0, 60);
$val2 = $mem->get(‘key2‘);
echo "Get key2 value: ";
print_r($val2);
echo "<br>";
//刪除數據
$mem->delete(‘key1‘);
$val = $mem->get(‘key1‘);
echo "Get key1 value: " . $val . "<br>";
//清除所有數據
$mem->flush();
$val2 = $mem->get(‘key2‘);
echo "Get key2 value: ";
print_r($val2);
echo "<br>";
//關閉連接
$mem->close();
?>
測試:
[root@adailinux src]# /usr/local/php-fpm/bin/php 1.php
Get key1 value: This is first value<br>Get key1 value: This is replace value<br>Get key2 value: Array
(
[0] => aaa
[1] => bbb
[2] => ccc
[3] => ddd
)
<br>Get key1 value: <br>Get key2 value: <br>
該情況說明配置成功!
21.8 memcached中存儲session
更改session存貯位置(memcached)。
session測試
以下為更改存儲位置前,session文件的錯處位置:
測試腳本內容如下:
[root@adailinux ~]# cat .mem_se.txt
<?php
session_start();
if (!isset($_SESSION[‘TEST‘])) {
$_SESSION[‘TEST‘] = time();
}
$_SESSION[‘TEST3‘] = time();
print $_SESSION[‘TEST‘];
print "<br><br>";
print $_SESSION[‘TEST3‘];
print "<br><br>";
print session_id();
?>
將該腳本放到當前機器默認站點的根目錄/data/wwwroot/www:
[root@adailinux ~]# cd /data/wwwroot/www
[root@adailinux www]# mv /root/.mem_se.txt 1.php
#進行移動並重命名
執行如下命令:
[root@adailinux www]# curl localhost/1.php
1506768299<br><br>1506768299<br><br>pcqf6d4r4sjeede4nkpvjni9n6
##此時存儲了一個session
[root@adailinux www]# ls /tmp/
sess_pcqf6d4r4sjeede4nkpvjni9n6
##該文件為執行上面命令生成的session文件
更改session存儲路徑
方法1:
[root@adailinux ~]# vim /usr/local/php-fpm/etc/php.ini
;session.save_handler = files
默認情況值為files,存放在/tmp/下
session.save_handler = memcache
##指定存儲類型
session.save_path = "tcp://192.168.8.131:11211"
##指定memcached服務器的IP和端口
重啟php服務:
[root@adailinux www]# /etc/init.d/php-fpm restart
Gracefully shutting down php-fpm . done
Starting php-fpm done
刪除/tmp/下原因的session文件:
[root@adailinux www]# rm -rf /tmp/sess*
在此創建session:
[root@adailinux www]# curl localhost/1.php
1506769084<br><br>1506769084<br><br>qe73bqse8rmckfchgb7j5b8ba6
###註:此處最後面的值為key
查看session信息:
[root@adailinux www]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is ‘^]‘.
get qe73bqse8rmckfchgb7j5b8ba6
VALUE qe73bqse8rmckfchgb7j5b8ba6 0 37
TEST|i:1506769084;TEST3|i:1506769084;
END
如果無法看到session數據的鍵值,
就無法直接在memcached中查看,
解決辦法是將memcached數據導出:
[root@adailinux www]# memcached-tool 127.0.0.1:11211 dump > /tmp/memdata.bak
[root@adailinux www]# cat /tmp/memdata.bak
add qe73bqse8rmckfchgb7j5b8ba6 0 1506770524 37
TEST|i:1506769084;TEST3|i:1506769084;
成功!
方法2:
在httpd.conf中定義session的保存路徑:
php_value session.save_handler "memcache"
php_value session.save_path "tcp://192.168.8.130:11211"
方法3:
在php-fpm.conf對應的pool中定義session的保存路徑:
php_value[session.save_handler] = memcache
php_value[session.save_path] = " tcp://192.168.8.130:11211 "
memcached安裝與應用