前期一直用的數據庫mysql,屬於關係型數據庫。現介紹一款非關係型數據庫——NoSQL;NoSQL=Not Only SQL,意爲「不只僅是SQL」,即非關係型數據庫。php
- 關係型數據庫:
例如京東或者淘寶這些大型電商平臺,有着很龐大的數據結構體系,有用戶表,商品表,用戶信息,商品信息,等當產生一個訂單的時候,或者查詢數據,是哪一個用戶,在什麼時間,購買了哪些商品,當調取一個用戶在某個時間買了什麼東西的時候這些數據是存在必定的關聯的。mysql
- 非關係型數據庫:
NoSQL的存在就是不須要這些錯綜複雜的理念,一個key對應一個value。例如一個用戶下對應着他的採購訂單。且數據所有存在閃存中。不須要再次從磁盤中調取。nginx
NoSQL是不能夠替代Mysql獨立存在的。例如現實運維環境中,咱們一臺WEB安裝了一個Discuz,隨着訪問量的增長,數據庫扛不住那麼大的壓力;怎麼辦呢?咱們設置一個NoSQL,當用戶讀取完畢後會直接放在NoSQL中,當用戶再次讀取的時候,會直接從緩存中讀取,不須要再次從數據庫中讀取。帖子的ID就相似於Key,帖子的內容就相似於Value。web
NoSQL由於沒有複雜的數據結構,擴展很是容易,支持分佈式。因此擴展也比較容易。若是你的A服務器受到瓶頸,增長服務器讓讓其繼續緩存唄,由於不像關係型數據庫須要互相關聯,NoSQL直接橫向擴展便可!redis
mysql的話只有前面說到的主主,主從,多主多從針對從進行負載均衡。要麼就是分庫分表,前提是關聯的數據庫不能夠分開,不關聯的數據庫能夠分開。算法
- k-v形式的:memcached、redis
適合儲存用戶信息,好比會話、配置文件、參數、購物車等等。這些信息通常都和ID(鍵)掛鉤,這種情景下鍵值數據庫是個很好的選擇。sql
- 文檔數據庫:mongodb
將數據以文檔的形式儲存。每一個文檔都是一系列數據項的集合。每一個數據項都有一個名稱與對應的值,值既能夠是簡單的數據類型,如字符串、數字和日期等;也能夠是複雜的類型,若有序列表和關聯對象。數據存儲的最小單位是文檔,同一個表中存儲的文檔屬性能夠是不一樣的,數據可使用XML、JSON或者JSONB等多種形式存儲。mongodb
列存儲: Hbase數據庫
圖存儲: Neo4J、Infinite Graph、OrientDBjson
Memcached是國外社區網站LiveJournal團隊開發,目的是爲了經過緩存數據庫查詢結果,減小數據庫訪問次數,從而提升動態web站點性能。
常規做業流程是:用戶發起請求給NGINX,而後再次調用PHP,PHP和mysql打交道,當用戶PHP獲取到請求轉給NGINX,NGINX再次把請求數據交給用戶。
若是併發量很大,請求mysql的隊列比較多,耗費資源,時間。
所以如圖,增長一個緩存層Memcached。這樣訪問過的數據所有丟在緩存中,當再次請求這個數據的時候就直接從Memcached讀取,少數據庫訪問次數,以提升動態web應用的速度、提升可擴展性。
其原理爲:
將分配的內存分割成各類尺寸的塊(chunk), 並把尺寸相同的塊分紅組(chunk的集合),每一個chunk集合被稱爲slab。
Memcached的內存分配以Page爲單位,Page默認值爲1M,能夠在啓動時經過-I 參數來指定。
Slab是由多個Page組成的,Page按照指定大小切割成多個chunk。
Memcached的數據過時方式,有兩種形式:
- Lazy Expiration
Memcached 內部不會監視記錄是否過時,而是在get時查看記錄的時間戳,檢查記錄是否過時。這種技術被稱爲lazy(惰性)expiration。所以,Memcached不會在過時監視上耗費CPU時間。
- LRU
Memcached會優先使用已超時的記錄的空間,但即便如此,也會發生追加新記錄時空間不足的狀況,此時就要使用名爲Least Recently Used(LRU)機制來分配空間。顧名思義,這是刪除「最近最少使用」的記錄的機制。所以,當內存空間不足時(沒法從slab class獲取到新的空間時),就從最近未被使用的記錄中搜索,並將其空間分配給新的記錄。從緩存的實用角度來看,該模型十分理想。
安裝、啓動memcached
[root@ying01 ~]# yum install -y memcached [root@ying01 ~]# systemctl start memcached
查看端口、以及進程
[root@ying01 ~]# netstat -lntp |grep memcached tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 1326/memcached tcp6 0 0 :::11211 :::* LISTEN 1326/memcached [root@ying01 ~]# ps aux |grep memcache memcach+ 1326 0.0 0.3 325604 3244 ? Ssl 11:44 0:00 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024 root 1338 0.0 0.0 112720 984 pts/0 S+ 11:46 0:00 grep --color=auto memcache [root@ying01 ~]#
上面進程中,能夠看到默認的啓動信息
/usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024
此爲默認啓動設置:p 端口 m 64M -c 指定最大併發數 -u指定運行memcached服務的用戶
能夠更改其默認設置:
[root@ying01 ~]# vim /etc/sysconfig/memcached PORT="11211" USER="memcached" MAXCONN="1024" CACHESIZE="64" OPTIONS="127.0.0.1" //更改成監控ip
[root@ying01 ~]# /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024
用命令 memcached-tool 127.0.0.1:11211 stats
[root@ying01 ~]# memcached-tool 127.0.0.1:11211 stats |head -5 #127.0.0.1:11211 Field Value accepting_conns 1 auth_cmds 0 auth_errors 0 bytes 0
還能夠用此命令:echo stats |nc 127.0.0.1 11211
[root@ying01 ~]# yum install -y nc //主要安裝nc [root@ying01 ~]# echo stats |nc 127.0.0.1 11211 | head -5 STAT pid 1326 STAT uptime 924 STAT time 1534910395 STAT version 1.4.15 STAT libevent 2.0.21-stable
此命令也能夠: memstat --servers=127.0.0.1:11211
[root@ying01 ~]# yum install -y libmemcached //若沒有安裝,請安裝 [root@ying01 ~]# memstat --servers=127.0.0.1:11211 |head -5 Server: 127.0.0.1 (11211) pid: 1326 uptime: 992 time: 1534910463 version: 1.4.15
Memcached相似於mysql同樣,一樣支持相似於mysql中建立一個庫,建立一個表,插入一個表,查看錶數據等。
首先須要安裝 telnet 命令
[root@ying01 ~]# yum install -y telnet
鏈接 Memcached,進行一些操做:
[root@ying01 ~]# telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. set key2 0 30 2 //設置 key2 數值,30秒過時,2字節 12 //此時輸入任意2字節 STORED //系統表示已儲存 get key2 //查看key2的內容 VALUE key2 0 2 12 END get key2 //再次查看key2,已經沒有數值,由於過時時間爲30秒 END
簡單釋義:
手動存儲一個數據: set key2 0 30 2
其中key2 表明着 key值
- 0表明着 flags 標記
- 30表明着 過時時間
- 2表明着 2個字節
Memcached語法標準格式:
<command name> <key> <flags> <exptime> <bytes>\r\n <data block>\r\n
- 注:\r\n在windows下是Enter鍵
- <command name> 能夠是set, add, replace
- set表示按照相應的<key>存儲該數據,沒有的時候增長,有的時候覆蓋
- add表示按照相應的<key>添加該數據,可是若是該<key>已經存在則會操做失敗
- replace表示按照相應的<key>替換數據,可是若是該<key>不存在則操做失敗。
- <key> 客戶端須要保存數據的key
- <flags> 是一個16位的無符號的整數(以十進制的方式表示)。該標誌將和須要存儲的數據一塊兒存儲,並在客戶端get數據時返回。客戶端能夠將此標誌用作特殊用途,此標誌對服務器來講是不透明的。
- <exptime> 爲過時的時間。若爲0表示存儲的數據永遠不過時(但可被服務器算法:LRU 等替換)。若是非0(unix時間或者距離此時的秒數),當過時後,服務器能夠保證用戶得不到該數據(以服務器時間爲標準)。
- <bytes> 須要存儲的字節數,當用戶但願存儲空數據時<bytes>能夠爲0
- <data block>須要存儲的內容,輸入完成後,最後客戶端須要加上\r\n(直接點擊Enter)做爲結束標誌。
演示以上命令 注意:在telnet模式下,使用「Ctrl + Backspace鍵刪除」
set key5 1 60 3 //存儲一個3字節值 www STORED get key5 //查詢key5的值 VALUE key5 1 3 www END replace key5 1 200 6 //替換key5的值 www123 STORED get key5 //查詢替換後的值 VALUE key5 1 6 www123 END delete key5 //刪除key5的值 DELETED get key5 END
memcached命令刪除 : Ctrl + Backspace
memcached退出 : ctrl+] 而後 quit
set ok 1 0 5 ^] telnet> quit Connection closed. [root@ying01 ~]#
經過查看其狀態,能夠看到set 、 get 等操做數據
[root@ying01 ~]# memstat --servers=127.0.0.1:11211 //查看狀態,裏面有記錄的 cmd_get: 4 cmd_set: 6 cmd_flush: 0 cmd_touch: 0 get_hits: 1 get_misses: 1 delete_misses: 3 delete_hits: 0
查看內容,結果消失了,說明過時了;
[root@ying01 ~]# memcached-tool 127.0.0.1:11211 dump Dumping memcache contents Number of buckets: 0 Number of items :
此時再次進入memcached,建立數據,再查看
[root@ying01 ~]# telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. set name 1 200 5 //設置過時時間200s 12345 STORED get name VALUE name 1 5 12345 END ^] telnet> quit Connection closed. [root@ying01 ~]# memcached-tool 127.0.0.1:11211 dump Dumping memcache contents Number of buckets: 1 Number of items : 1 Dumping bucket 1 - 1 total items add name 1 1534913629 5 12345
導出數據
[root@ying01 ~]# memcached-tool 127.0.0.1:11211 dump > data.txt Dumping memcache contents Number of buckets: 1 Number of items : 1 Dumping bucket 1 - 1 total items [root@ying01 ~]# ls data.txt data.txt [root@ying01 ~]# cat data.txt add name 1 1534913629 5 12345
導出數據
[root@ying01 ~]# nc 127.0.0.1 11211 < data.txt //由於在 200s內,因此能夠導入 STORED
**注意:**導出的數據是帶有一個時間戳的,這個時間戳就是該條數據過時的時間點,若是當前時間已經超過該時間戳,那麼是導入不進去的。
下載memcache包、解壓
[root@xavi ~]# cd /usr/local/src [root@xavi src]# wget http://www.apelearn.com/bbs/data/attachment/forum/memcache-2.2.3.tgz [root@ying01 src]# tar zxf memcache-2.2.3.tgz [root@ying01 src]# cd memcache-2.2.3 [root@ying01 memcache-2.2.3]# /usr/local/php-fpm/bin/phpize Configuring for: PHP Api Version: 20131106 Zend Module Api No: 20131226 Zend Extension Api No: 220131226
執行配置文件並編譯
[root@ying01 memcache-2.2.3]# ./configure --with-php-config=/usr/local/php-fpm/bin/php-config [root@ying01 memcache-2.2.3]# make [root@ying01 memcache-2.2.3]# make install
查看 生成so文件
[root@ying01 memcache-2.2.3]# ls /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/ memcache.so opcache.a opcache.so
在php.ini添加此語句,讓調用此擴展模塊
[root@ying01 memcache-2.2.3]# vim /usr/local/php-fpm/etc/php.ini extension="memcache.so" //添加此語句
查看其是否存在
[root@ying01 memcache-2.2.3]# /usr/local/php-fpm/sbin/php-fpm -m [PHP Modules] cgi-fcgi Core ctype curl date dom ereg exif fileinfo filter ftp gd hash iconv json libxml mbstring mcrypt memcache //模塊已經在 PHP Modules 裏面 mysql
查看1.php內容
[root@ying01 memcache-2.2.3]# curl www.apelearn.com/study_v2/.memcache.txt > 1.php 2>/dev/null //下載 寫入 [root@ying01 memcache-2.2.3]# cat 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(); ?>
執行此php
[root@ying01 memcache-2.2.3]# /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>[root@ying01 memcache-2.2.3]#
應用場景:爲LNMP架構下作的負載均衡。
假如第一次登陸是在A服務器上,第二次登陸是在B服務器上,假如使用的是nginx代理upstream可使用ip_hash;若是使用LVS呢?
解決方法是:把session不存在服務器的磁盤上,而是存在memcached上去。memcached做爲一個公共的服務器,任何web服務器均可以鏈接!
[root@ying01 ~]# wget http://study.lishiming.net/.mem_se.txt //下載此存session的腳本 [root@ying01 ~]# vim .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(); ?>