非关系数据库一Memcached

时间:2021-07-01 04:23:21

第三十四课 非关系数据库一Memcached

目录

一、nosql介绍

二、memrcached介绍

三、安装memcached

四、查看memcachedq状态

五、memcached命令行

六、memcached数据导出和导入

七、php连接memcached

八、memcached中存储sessions

一、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

二、memrcached介绍

Memcached是国外社区网站LiveJournal团队开发,目的是为了通过缓存数据库查询结果,减少数据库访问次数,从而提高动态web站点性能。

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

数据结构简单(k-v),数据存放在内存里

多线程

基于c/s架构,协议简单

基于libevent的事件处理

自主内存存储处理(slab allowcation)

数据过期方式:Lazy Expiration 和 LRU

memcached数据流向

非关系数据库一Memcached

Slab Allocation的原理

非关系数据库一Memcached

将分配的内存分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合),每个chunk集合被称为slab。

Memcached的内存分配以Page为单位,Page默认值为1M,可以在启动时通过-I参数来指定。

Slab是由多个Page组成的,Page按照指定大小切割成多个chunk。

Memcached在启动时通过-f选项可以指定 Growth Factor因子。该值控制chunk大小的差异。默认值为1.25。

通过memcached-tool命令查看指定Memcached实例的不同slab状态,可以看到各Item所占大小(chunk大小)差距为1.25

命令:# memcached-tool 127.0.0.1:11211 display

Lazy Expiration

Memcached 内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,Memcached不会在过期监视上耗费CPU时间。

LRU

Memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当内存空间不足时(无法从slab class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。

三、安装memcached

1.安装memcached,libmemcached,libevent

[root@lanquark sh]# yum install -y memcached libmemcached libevent
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
epel/x86_64/metalink | 6.8 kB 00:00:00
...中间略...
Installed:
libevent.x86_64 0:2.0.21-4.el7 libmemcached.x86_64 0:1.0.16-5.el7 memcached.x86_64 0:1.4.15-10.el7_3.1
Complete!

2.启动memcached服务

[root@lanquark sh]# systemctl start memcached.service
[root@lanquark sh]# systemctl status memcached.service
[root@lanquark sh]# systemctl enable memcached.service

3.编译memcached配置文件

vim /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
#测试环境设为127.0.0.1
OPTIONS="127.0.0.1"

4.重启memcached服务

[root@lanquark sh]# systemctl restart memcached.servicec

四、查看memcached状态

1.用memcached-tool查看

[root@lanquark sh]# 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 12641
pointer_size 64
reclaimed 0
reserved_fds 20
rusage_system 0.012032
rusage_user 0.004812
threads 4
time 1534868520
total_connections 11
total_items 0
touch_hits 0
touch_misses 0
uptime 90
version 1.4.15

2.nc工具查看,如果没有nc,可以用yum安装

[root@lanquark sh]# rpm -q nc
package nc is not installed [root@lanquark sh]# yum -y install nc
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* epel: mirrors.tongji.edu.cn
Resolving Dependencies
--> Running transaction check
---> Package nmap-ncat.x86_64 2:6.40-13.el7 will be installed
--> Processing Dependency: libpcap.so.1()(64bit) for package: 2:nmap-ncat-6.40-13.el7.x86_64
--> Running transaction check
---> Package libpcap.x86_64 14:1.5.3-11.el7 will be installed
--> Finished Dependency Resolution
...中间略...
Installed:
nmap-ncat.x86_64 2:6.40-13.el7
Dependency Installed:
libpcap.x86_64 14:1.5.3-11.el7
Complete! Complete!
[root@lanquark sh]# echo stats |nc 127.0.0.1 11211
STAT pid 12641
STAT uptime 30508
STAT time 1534898938
STAT version 1.4.15
STAT libevent 2.0.21-stable
STAT pointer_size 64
STAT rusage_user 1.488076
STAT rusage_system 0.930047
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

3.通过memstat查看

#如果没有memstat命令,需安装libmemcached
[root@lanquark sh]# memstat --servers=127.0.0.1:11211
Server: 127.0.0.1 (11211)
pid: 12641
uptime: 30985
time: 1534899415
version: 1.4.15
libevent: 2.0.21-stable
pointer_size: 64
rusage_user: 1.523973
rusage_system: 0.931317
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: 2071
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

五、memcached命令行

1.连接memcached

[root@lanquark sh]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

2.set 命令用于将 value(数据值) 存储在指定的 key(键) 中。

[root@lanquark sh]# 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
ab
STORED
get key2
VALUE key2 0 2
ab
END
^] 基础语法:
set key flags exptime bytes [noreply]
value 参数说明如下: key:键值 key-value 结构中的 key,用于查找缓存值。 flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息。 exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远) bytes:在缓存中存储的字节数 noreply(可选): 该参数告知服务器不需要返回数据 value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)

3.add 命令用于将 value(数据值) 存储在指定的 key(键) 中。

[root@lanquark sh]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
add new_key 0 900 10
data_value
STORED 基本语法:
add key flags exptime bytes [noreply]
value 参数说明如下: key:键值 key-value 结构中的 key,用于查找缓存值。 flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息。 exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远) bytes:在缓存中存储的字节数 noreply(可选): 该参数告知服务器不需要返回数据 value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)

4.replace 命令用于替换已存在的 key(键) 的 value(数据值)。

如果 key 不存在,则替换失败,并且您将获得响应 NOT_STORED。

[root@lanquark sh]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
add mykey 0 900 10
data_value
STORED
get mykey
VALUE mykey 0 10
data_value
END
replace mykey 0 900 16
some_other_value
STORED
get mykey
VALUE mykey 0 16
some_other_value
END 基本语法:
replace key flags exptime bytes [noreply]
value 参数说明如下: key:键值 key-value 结构中的 key,用于查找缓存值。 flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息。 exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远) bytes:在缓存中存储的字节数 noreply(可选): 该参数告知服务器不需要返回数据 value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)

5.append 命令用于向已存在 key(键) 的 value(数据值) 后面追加数据 。

[root@lanquark sh]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
set runoob 0 900 9
memcached
STORED
get runoob
VALUE runoob 0 9
memcached
END
append runoob 0 900 5
redis
STORED
get runoob
VALUE runoob 0 14
memcachedredis
END 基本语法:
append key flags exptime bytes [noreply]
value 参数说明如下: key:键值 key-value 结构中的 key,用于查找缓存值。 flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息。 exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远) bytes:在缓存中存储的字节数 noreply(可选): 该参数告知服务器不需要返回数据 value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)

六、memcached数据导出和导入

1.memcached数据导出

[root@lanquark sh]# 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@lanquark sh]# cat data.txt
add mykey 0 1534901468 16
some_other_value
add new_key 0 1534901149 10
data_value
add runoob 0 1534901739 14
memcachedredis

2.memcached数据的导入

[root@lanquark sh]# nc 127.0.0..1 11211 < data.txt
Ncat: Could not resolve hostname "127.0.0..1": Name or service not known. QUITTING.
[root@lanquark sh]# nc 127.0.0.1 11211 < data.txt
NOT_STORED
STORED
NOT_STORED
[root@lanquark sh]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
#new_key过期,所以查不到数据
get new_key
END
#runoob值未过期
get runoob
VALUE runoob 0 14
memcachedredis
END

七、php连接memcached

1.安装php的memcached的扩展

#下载memcache插件
root@lanquark src]# wget http://www.apelearn.com/bbs/data/attachment/forum/memcache-2.2.3.tgz
#解压软件包
[root@lanquark src]# tar -zxvf memcache-2.2.3.tgz [root@lanquark src]# cd memcache-2.2.3/
[root@lanquark memcache-2.2.3]# /usr/local/php-fpm/bin/phpize ./configure --with-php-config=/usr/local/php-fpm/bin/php-config [root@lanquark memcache-2.2.3]# make && make install
...略...
Build complete.
Don't forget to run 'make test'. Installing shared extensions: /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
#编译php.ini
[root@lanquark memcache-2.2.3]# vim /usr/local/php-fpm/etc/php.ini
#在extension部分增加
extension=memcache.so #验证
[root@lanquark memcache-2.2.3]# /usr/local/php-fpm/sbin/php-fpm -m | grep mem
memcache

2.新建测试脚本

[root@lanquark memcache-2.2.3]# cd /usr/local/nginx/html/
[root@lanquark html]# 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@lanquark html]# /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@lanquark html]#

八、memcached中存储sessions

本实例是在lamp/lnmp环境下实现

编辑php.ini添加两行(需要重启后才能生产)
session.save_handler = memcache
session.save_path = "tcp://127.0.0.1:11211" 或者httpd.conf中对应的虚拟主机中添加
php_value session.save_handler "memcache"
php_value session.save_path "tcp://127.0.0.1:11211" 或者php-fpm.conf对应的pool中添加
php_value[session.save_handler] = memcache
php_value[session.save_path] = " tcp://127.0.0.1:11211 " [root@lanquark html]# vim /usr/local/php-fpm/etc/php.ini
#在末尾添加,保存文件内容后。然后重启服务器
session.save_handler = memcache
session.save_path = "tcp://127.0.0.1:11211" #新建session测试文件
[root@lanquark html]# vim session.php
<?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();
?> ~
"session.php" [New] 12L, 237C written
[root@lanquark html]# curl localhost/session.php
1534905865<br><br>1534905865<br><br>44v9rm4hitgelt78gl02r7rbt2
[root@lanquark html]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get 44v9rm4hitgelt78gl02r7rbt2
VALUE 44v9rm4hitgelt78gl02r7rbt2 0 37
TEST|i:1534905865;TEST3|i:1534905865;
END
#说明session有保存在memcached中