什麼是NoSQLphp
•非關係型數據庫就是NoSQL,關係型數據庫表明MySQL 對於關係型數據庫來講,是須要把數據存儲到庫、表、行、字段裏,查詢的時候根據條件一行一行地去匹配,當量很是大的時候就很耗費時間和資源,尤爲是數據是須要從磁盤裏去檢索python
•NoSQL數據庫存儲原理很是簡單(典型的數據類型爲k-v),不存在繁雜的關係鏈,好比mysql查詢的時候,須要找到對應的庫、表(一般是多個表)以及字段。mysql
•NoSQL數據能夠存儲在內存裏,查詢速度很是快web
•NoSQL在性能表現上雖然能優於關係型數據庫,可是它並不能徹底替代關係型數據庫redis
•NoSQL由於沒有複雜的數據結構,擴展很是容易,支持分佈式算法
常見NoSQL數據庫sql
•k-v形式的:memcached、redis 適合儲存用戶信息,好比會話、配置文件、參數、購物車等等。這些信息通常都和ID(鍵)掛鉤,這種情景下鍵值數據庫是個很好的選擇。mongodb
•文檔數據庫:mongodb 將數據以文檔的形式儲存。每一個文檔都是一系列數據項的集合。每一個數據項都有一個名稱與對應的值,值既能夠是簡單的數據類型,如字符串、數字和日期等;也能夠是複雜的類型,若有序列表和關聯對象。數據存儲的最小單位是文檔,同一個表中存儲的文檔屬性能夠是不一樣的,數據可使用XML、JSON或者JSONB等多種形式存儲。數據庫
•列存儲 Hbasevim
•圖 Neo4J、Infinite Graph、OrientDB
NoSQL數據庫的四大分類
•鍵值(Key-Value)存儲數據庫
這一類數據庫主要會使用到一個哈希表,這個表中有一個特定的鍵和一個指針指向特定的數據。Key/value模型對於IT系統來講的優點在於簡單、易部署。可是若是DBA只對部分值進行查詢或更新的時候,Key/value就顯得效率低下了。舉例如:Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB. 列存儲數據庫。
這部分數據庫一般是用來應對分佈式存儲的海量數據。鍵仍然存在,可是它們的特色是指向了多個列。這些列是由列家族來安排的。如:Cassandra, HBase, Riak. 文檔型數據庫
文檔型數據庫的靈感是來自於Lotus Notes辦公軟件的,並且它同第一種鍵值存儲相相似。該類型的數據模型是版本化的文檔,半結構化的文檔以特定的格式存儲,好比JSON。文檔型數據庫可 以看做是鍵值數據庫的升級版,容許之間嵌套鍵值。並且文檔型數據庫比鍵值數據庫的查詢效率更高。如:CouchDB, MongoDb. 國內也有文檔型數據庫SequoiaDB,已經開源。
•圖形(Graph)數據庫
圖形結構的數據庫同其餘行列以及剛性結構的SQL數據庫不一樣,它是使用靈活的圖形模型,而且可以擴展到多個服務器上。NoSQL數據庫沒有標準的查詢語言(SQL),所以進行數據庫查詢須要制定數據模型。許多NoSQL數據庫都有REST式的數據接口或者查詢API。如:Neo4J, InfoGrid, Infinite Graph.
所以,咱們總結NoSQL數據庫在如下的這幾種狀況下比較適用:一、數據模型比較簡單;二、須要靈活性更強的IT系統;三、對數據庫性能要求較高;四、不須要高度的數據一致性;五、對於給定key,比較容易映射覆雜值的環境。
Memcached是國外社區網站LiveJournal團隊開發,目的是爲了經過緩存數據庫查詢結果,減小數據庫訪問次數,從而提升動態web站點性能。
官方站點http://www.memcached.org/
數據結構簡單(k-v),數據存放在內存裏
多線程
基於c/s架構,協議簡單
基於libevent的事件處理
自主內存存儲處理(slab allowcation)
數據過時方式:Lazy Expiration 和LRU
Memcached的數據流向
Slab Allocation的原理:
將分配的內存分割成各類尺寸的塊(chunk), 並把尺寸相同的塊分紅組(chunk的集合),每一個chunk集合被稱爲slab。
Memcached的內存分配以Page爲單位,Page默認值爲1M,能夠在啓動時經過-I參數來指定。
Slab是由多個Page組成的,Page按照指定大小切割成多個chunk。
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獲取到新的空間時),就從最近未被使用的記錄中搜索,並將其空間分配給新的記錄。從緩存的實用角度來看,該模型十分理想。
memcached能夠經過yum安裝,固然也能夠去官網下載相應的源碼包進行編譯安裝,若是是初次接觸的話,先用最簡單的安裝方式或許會比較好一點,先來看看yum中能夠安裝的memcached版本:
[root@localhost ~]# yum list |grep memcached libmemcached.x86_64 1.0.16-5.el7 @base memcached.x86_64 1.4.15-10.el7_3.1 @base libmemcached.i686 1.0.16-5.el7 base libmemcached-devel.i686 1.0.16-5.el7 base libmemcached-devel.x86_64 1.0.16-5.el7 base memcached-devel.i686 1.4.15-10.el7_3.1 base memcached-devel.x86_64 1.4.15-10.el7_3.1 base opensips-memcached.x86_64 1.10.5-3.el7 epel php-ZendFramework-Cache-Backend-Libmemcached.noarch php-pecl-memcached.x86_64 2.2.0-1.el7 epel python-memcached.noarch 1.48-4.el7 base uwsgi-router-memcached.x86_64 2.0.16-1.el7 epel
安裝包:
yum install -y memcached libmemcached libevent
啓動memcached服務:
systemctl start memcached
查看進程:
[root@localhost ~]# ps aux|grep memcached memcach+ 1245 0.0 0.1 344080 1664 ? Ssl 19:37 0:00 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024 root 1252 0.0 0.0 112720 972 pts/0 R+ 19:38 0:00 grep --color=auto memcached
•-u指定運行該服務的用戶,-p指定監聽端口,-m指定分配給這個進程的內存大小,單位是m,-c指定最大併發數量
查看端口:
[root@localhost ~]# netstat -lntp|grep memcached tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 1245/memcached tcp6 0 0 :::11211 :::* LISTEN 1245/memcached
有兩種方式能夠更改memcached的服務參數,第一種是使用絕對路徑來啓動,而後經過選項來指定參數,例如:
/usr/bin/memcached -u memcached -p XXXX -m 32 -c 2024
第二種方式是修改配置文件:
[root@localhost ~]# vim /etc/sysconfig/memcached PORT="11211" USER="memcached" MAXCONN="1024" CACHESIZE="64" OPTIONS=""
若是須要加上監聽的ip,能夠把OPTIONS="" 改成OPTIONS="127.0.0.1"
三種方式查看memcached狀態:
自帶工具memcached-tool 命令:memcached-tool 127.0.0.1:11211 stats 或者echo stats |nc 127.0.0.1 11211 須要安裝nc工具yum install -y nc 若安裝libmemcached後,可使用命令 memstat --servers=127.0.0.1:11211 查看memcached服務狀態
memcached 有個自帶的工具memcached-tool,能夠用來查看memcached的狀態
主要關注curr_items 和 get_hits 用get_hits 除以 curr_items 查看命中率有多高
[root@localhost ~]# memcached-tool 127.0.0.1:11211 stats #127.0.0.1:11211 Field Value accepting_conns 1 auth_cmds 0 auth_errors 0 bytes 0 bytes_read 7 bytes_written 0 cas_badval 0 cas_hits 0 cas_misses 0 cmd_flush 0 cmd_get 0 cmd_set 0 cmd_touch 0 conn_yields 0 connection_structures 11 curr_connections 10 curr_items 0 decr_hits 0 decr_misses 0 delete_hits 0 delete_misses 0 evicted_unfetched 0 evictions 0 expired_unfetched 0 get_hits 0 get_misses 0 hash_bytes 524288 hash_is_expanding 0 hash_power_level 16 incr_hits 0 incr_misses 0 libevent 2.0.21-stable limit_maxbytes 67108864 listen_disabled_num 0 pid 1245 pointer_size 64 reclaimed 0 reserved_fds 20 rusage_system 0.006359 rusage_user 0.006359 threads 4 time 1534851778 total_connections 11 total_items 0 touch_hits 0 touch_misses 0 uptime 300 version 1.4.15
咱們平時須要關注get_hits(命中數量)以及curr_items(存在memcached中的項目)的值,使用get_hits的值除以curr_items的值,能夠計算出命中率。這是爲了檢測memcached是否有緩存了數據以及是否能被正常的訪問這些緩存的數據
除了memcached-tool以外,還可使用nc來查看memcached的狀態,安裝命令以下:
yum install -y nc
查看狀態命令:
[root@localhost ~]# echo stats|nc 127.0.0.1 11211 STAT pid 1245 STAT uptime 603 STAT time 1534852081 STAT version 1.4.15 STAT libevent 2.0.21-stable STAT pointer_size 64 STAT rusage_user 0.014568 STAT rusage_system 0.007284 STAT curr_connections 10 STAT total_connections 12 STAT connection_structures 11 STAT reserved_fds 20 STAT cmd_get 0 STAT cmd_set 0 STAT cmd_flush 0 STAT cmd_touch 0 STAT get_hits 0 STAT get_misses 0 STAT delete_misses 0 STAT delete_hits 0 STAT incr_misses 0 STAT incr_hits 0 STAT decr_misses 0 STAT decr_hits 0 STAT cas_misses 0 STAT cas_hits 0 STAT cas_badval 0 STAT touch_hits 0 STAT touch_misses 0 STAT auth_cmds 0 STAT auth_errors 0 STAT bytes_read 13 STAT bytes_written 1024 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 0 STAT curr_items 0 STAT total_items 0 STAT expired_unfetched 0 STAT evicted_unfetched 0 STAT evictions 0 STAT reclaimed 0 END
安裝libmemcached包後,還可使用以下命令查看memcached服務狀態:
[root@localhost ~]# memstat --servers=127.0.0.1:11211 Server: 127.0.0.1 (11211) pid: 1245 uptime: 752 time: 1534852230 version: 1.4.15 libevent: 2.0.21-stable pointer_size: 64 rusage_user: 0.019268 rusage_system: 0.007284 curr_connections: 10 total_connections: 13 connection_structures: 11 reserved_fds: 20 cmd_get: 0 cmd_set: 0 cmd_flush: 0 cmd_touch: 0 get_hits: 0 get_misses: 0 delete_misses: 0 delete_hits: 0 incr_misses: 0 incr_hits: 0 decr_misses: 0 decr_hits: 0 cas_misses: 0 cas_hits: 0 cas_badval: 0 touch_hits: 0 touch_misses: 0 auth_cmds: 0 auth_errors: 0 bytes_read: 30 bytes_written: 2068 limit_maxbytes: 67108864 accepting_conns: 1 listen_disabled_num: 0 threads: 4 conn_yields: 0 hash_power_level: 16 hash_bytes: 524288 hash_is_expanding: 0 bytes: 0 curr_items: 0 total_items: 0 expired_unfetched: 0 evicted_unfetched: 0 evictions: 0 reclaimed: 0
使用telnet能夠進入memcached命令行
[root@localhost ~]# telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'.
使用set命令建立數據:
set key1 0 30 2 12 STORED set key2 0 30 3 abc STORED
命令解析:
set key1 0 30 2 set: 建立數據命令(command name) key2: 建立一個名爲key1的key (key) 0 : 特殊標記位(flags) 30 : 定義這個數據的過時時間爲30秒(exptime) 2 : 定義這個key所可以存儲的value長度,單位是字節 (bytes)
獲取數據:
get key1 VALUE key1 0 2 12 END get key2 VALUE key2 0 3 abc END
數據過時了的話就不存在了:
get key1 END get key2 END
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)做爲結束標誌。
由於memcached的數據是存儲在內存中的,當服務須要重啓的時候,須要先讓memcached裏的數據寫到磁盤中,否則數據會丟失。因此介紹一下memcached如何導出和導入數據。
memcached中添加了以下幾個不過時的數據:
[root@localhost ~]# telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. set name 1 0 6 luoluo STORED set age 1 0 2 20 STORED set key1 1 0 5 12345 STORED
添加完以後,按CTRL+]而後輸入quit退出telnet
memcached的狀態以下:
[root@localhost ~]# memcached-tool 127.0.0.1 stats #127.0.0.1:11211 Field Value accepting_conns 1 auth_cmds 0 auth_errors 0 bytes 219 bytes_read 192 bytes_written 3177 cas_badval 0 cas_hits 0 cas_misses 0 cmd_flush 0 cmd_get 4 cmd_set 5 cmd_touch 0 conn_yields 0 connection_structures 11 curr_connections 10 curr_items 3 decr_hits 0 decr_misses 0 delete_hits 0 delete_misses 0 evicted_unfetched 0 evictions 0 expired_unfetched 0 get_hits 1 get_misses 3 hash_bytes 524288 hash_is_expanding 0 hash_power_level 16 incr_hits 0 incr_misses 0 libevent 2.0.21-stable limit_maxbytes 67108864 listen_disabled_num 0 pid 1245 pointer_size 64 reclaimed 0 reserved_fds 20 rusage_system 0.024226 rusage_user 0.036339 threads 4 time 1534853244 total_connections 15 total_items 5 touch_hits 0 touch_misses 0 uptime 1766 version 1.4.15
將數據導出到一個文件裏:
[root@localhost ~]# memcached-tool 127.0.0.1:11211 dump > data.txt Dumping memcache contents Number of buckets: 1 Number of items : 3 Dumping bucket 1 - 3 total items
查看導出文件內容:
[root@localhost ~]# cat data.txt add name 1 1534851478 6 luoluo add key1 1 1534851478 5 12345 add age 1 1534851478 2 20
•注意:導出的數據是帶有一個時間戳的,這個時間戳就是該條數據過時的時間點,若是當前時間已經超過該時間戳,那麼是導入不進去的,其中1534851478這樣的就是時間戳
重啓服務後將數據導入到memcached裏並獲取數據:
[root@localhost ~]# systemctl restart memcached [root@localhost ~]# nc 127.0.0.1 11211 < data.txt STORED STORED STORED [root@localhost ~]# telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. get name END get age END get key1 END
若是導入後發現沒有數據,這是由於備份文件裏記錄的時間戳已通過期了,能夠修改文件中的時間戳保證數據的有效期。能夠寫一個簡單的腳本批量替換這些文件中的時間戳:
[root@localhost ~]# vi replace.sh #!/bin/bash hour=`date -d "+1 hour" +%s` data_time=`cat data.txt |grep add |awk '{print $4}' |sort -n |uniq` for i in $data_time do sed -i "s/$i/$hour/g" `grep $i -rl /root/data.txt` done [root@localhost ~]# sh replace.sh [root@localhost ~]# cat data.txt add name 1 1534857427 6 luoluo add key1 1 1534857427 5 12345 add age 1 1534857427 2 20
再次導入:
[root@localhost ~]# nc 127.0.0.1 11211 <data.txt STORED STORED STORED
而後再到memcached裏查看數據:
[root@localhost ~]# 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 6 luoluo END get age VALUE age 1 2 20 END get key1 VALUE key1 1 5 12345 END
能夠看到,數據正常導入了。
在LNMP、LAMP等環境下,咱們須要讓php與memcached進行交互,就像php與mysql交互那樣,php也得經過某個模塊鏈接memcached後,才能進行數據的呈現、交互等操做。
1.先安裝php的memcache擴展,我這裏的php是LNMP環境的而且在以前已經安裝好了,因此如今進行擴展便可:
[root@localhost ~]# cd /usr/local/src/ [root@localhost src]# wget http://www.apelearn.com/bbs/data/attachment/forum/memcache-2.2.3.tgz [root@localhost src]# tar zxf memcache-2.2.3.tgz [root@locahost src]# cd memcache-2.2.3 [root@localhost memcache-2.2.3]# ls config9.m4 CREDITS memcache_consistent_hash.c memcache_queue.h php_memcache.h config.m4 example.php memcache.dsp memcache_session.c README config.w32 memcache.c memcache_queue.c memcache_standard_hash.c [root@localhost memcache-2.2.3]# /usr/local/php-fpm/bin/phpize # 生成config文件 Configuring for: PHP Api Version: 20131106 Zend Module Api No: 20131226 Zend Extension Api No: 220131226 [root@localhost memcache-2.2.3]# ./configure --with-php-config=/usr/local/php-fpm/bin/php-config [root@localhost memcache-2.2.3]# echo $? 0 [root@localhost memcache-2.2.3]# make && make install [root@localhost memcache-2.2.3]# echo $? 0
安裝完後會有相似這樣的提示:Installing shared extensions: /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/ 會在這個路徑下生成memcache.so的文件
[root@localhost 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添加一行extension="memcache.so「
[root@localhost memcache-2.2.3]# vim /usr/local/php-fpm/etc/php.ini #找到extension=關鍵字,在其下面添加一行 extension=memcache.so
檢查/usr/local/php-fpm/bin/php -m裏是否有memcache模塊:
[root@localhost ~]# /usr/local/php-fpm/sbin/php-fpm -m|grep memcache memcache
測試:
1.下載測試腳本:
curl www.apelearn.com/study_v2/.memcache.txt > 1.php 2>/dev/null
2.執行測試腳本:
[root@localhost ~]# /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 )
出現以上數聽說明沒問題
在負載均衡集羣中,用戶第一次訪問的是A服務器,而且在該服務器上登陸了帳戶,這個登陸信息就保存在session中。因爲是集羣的關係,因此用戶可能下一次再訪問的時候就不是訪問到A服務器上,而是訪問到B服務器上了。可是以前的session卻保存在A服務器上,那麼用戶在B服務器上就只能從新登陸一次,由於在B服務器上並無session信息。因此爲了讓集羣中的服務器都可以共享session,就能夠把session存儲在一個memcached服務器中,全部的web服務器往這臺memcached服務器上讀session信息,就能作到簡單的session共享。
這裏是lnmp環境下的配置:
php服務默認會把session信息存在本地文件中,因此須要修改存儲的類型。
1.編輯php.ini配置文件添加如下兩行:若是這裏不成功在php-fpm.conf對應的pool中添加
session.save_handler = memcache # 指定session的存儲類型 session.save_path = "tcp://192.168.66.132:11211" # 指定memcached服務器的ip和端口
或者php-fpm.conf對應的pool中添加如下兩行:
php_value[session.save_handler] = memcache php_value[session.save_path] = " tcp://192.168.66.132:11211"
2.修改完以後重啓服務:
[root@localhost ~]# /etc/init.d/php-fpm restart Gracefully shutting down php-fpm . done Starting php-fpm done
3.測試,下載測試文件 + 移動文件到默認站點目錄並改名 + curl測試,素質三連:
[root@localhost ~]# wget http://study.lishiming.net/.mem_se.txt [root@localhost ~]# mv .mem_se.txt /data/wwwroot/default/1.php [root@localhost ~]# curl localhost/1.php # 輸出內容以下格式,表明沒毛病 1514470099<br><br>1514470099<br><br>0rmd502kjrsvrnqhqtn1a0eih6
那個 0rmd502kjrsvrnqhqtn1a0eih6 就是memcached中的key,經過這個key才能去memcached裏拿值,若是沒有這個key的話,多是配置文件沒配置對。
4.進入memcached命令行,看看有沒有存儲到對應的session數據:
[root@localhost ~]# telnet 127.0.0.1 11211 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. get 0rmd502kjrsvrnqhqtn1a0eih6 VALUE 0rmd502kjrsvrnqhqtn1a0eih6 0 37 TEST|i:1514470099;TEST3|i:1514470099; END
如上,能夠看到get到了該鍵的值,證實沒問題,可以正常存儲。