2018-08-20nosql(memcached)筆記

21.1 nosql介紹

什麼是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

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數據庫在以下的這幾種情況下比較適用:1、數據模型比較簡單;2、需要靈活性更強的IT系統;3、對數據庫性能要求較高;4、不需要高度的數據一致性;5、對於給定key,比較容易映射覆雜值的環境。

21.2 memrcached介紹

Memcached是國外社區網站LiveJournal團隊開發,目的是爲了通過緩存數據庫查詢結果,減少數據庫訪問次數,從而提高動態web站點性能。

官方站點http://www.memcached.org/

數據結構簡單(k-v),數據存放在內存裏

多線程

基於c/s架構,協議簡單

基於libevent的事件處理

自主內存存儲處理(slab allowcation)

數據過期方式:Lazy Expiration 和LRU
Memcached的數據流向
2018-08-20nosql(memcached)筆記
Slab Allocation的原理:

將分配的內存分割成各種尺寸的塊(chunk), 並把尺寸相同的塊分成組(chunk的集合),每個chunk集合被稱爲slab。
Memcached的內存分配以Page爲單位,Page默認值爲1M,可以在啓動時通過-I參數來指定。
Slab是由多個Page組成的,Page按照指定大小切割成多個chunk。
2018-08-20nosql(memcached)筆記
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

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"

21.4 查看memcached狀態

三種方式查看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

21.5 memcached命令行

使用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)作爲結束標誌。

21.6 memcached數據導出和導入

因爲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

可以看到,數據正常導入了。

21.7 php連接memcached

在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
)

出現以上數據說明沒問題

21.8 memcached中存儲sessions

在負載均衡集羣中,用戶第一次訪問的是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到了該鍵的值,證明沒問題,能夠正常存儲。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章