非关系型数据库就是NoSQL,关系型数据库代表MySQL
对于关系型数据库来说,是需要把数据存储到库、表、行、字段里,查询的时候根据条件一行一行地去匹配,当量非常大的时候就很耗费时间和资源,尤其是数据是需要从磁盘里去检索
NoSQL数据库存储原理非常简单(典型的数据类型为k-v),不存在繁杂的关系链,比如mysql查询的时候,需要找到对应的库、表(通常是多个表)以及字段。
NoSQL数据可以存储在内存里,查询速度非常快
NoSQL在性能表现上虽然能优于关系型数据库,但是它并不能完全替代关系型数据库
NoSQL因为没有复杂的数据结构,扩展非常容易,支持分布式
常见的NOSQL数据库:
k-v形式的:memcached、redis 适合储存用户信息,比如会话、配置文件、参数、购物车等等。这些信息一般都和ID(键)挂钩,这种情景下键值数据库是个很好的选择。
列存储 Hbase
图 Neo4J、Infinite Graph、OrientDB
memcached是国外的社区网站LiveJournal团队开发,目的是为了通过缓存数据库查询结果,减少数据库访问次数,从而提高动态web站点性能。
官方站点 http://www.memcached.org/
数据结构简单(k-v),数据存放在内存里 (memcached数据不支持落地,不支持持久化,如果重启服务器,或重启了memcached服务,数据就会丢失)
为了保证数据安全,可以定期把数据存到磁盘里,重启服务之前,也要把数据先做一个落地,存到磁盘中,然后在重启服务。重启服务后,在把磁盘的数据导入到内存中去。
多线程
基于c/s架构,协议简单
基于libevent的事件处理
自主内存存储处理(slab allowcation)
数据过期方式:Lazy Expiration 和 LRU
通常,请求发过来,在web服务器上,Nginx交给php-fpm解析,在数据库中查询数据,最终有Nginx反馈给用户。在MySQL里面查询数据很慢,并发量很大,这是增加一个缓存memcached,先把查询到的数据缓存在内存里,再次查询的时候可以直接从缓存中去数据,不用再去MySQL内存中找了。降低了MySQL数据查询的次数。
Slab Allocation的原理
将分配的内存分割成各种尺寸的块(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
memcached数据过期时间
Lazy Expiration
Memcached 内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,Memcached不会在过期监视上耗费CPU时间。
LRU
Memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当内存空间不足时(无法从slab class获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想
memcached安装即可以yum安装又可以源码安装。可以官方下载源码包,进行编译安装。
memcache的yum安装:
[root@shuai-01 ~]# yum install -y memcached
memcache使用的是libeven事件处理机制,必须要有libevent包。
查看系统上有没有libevent包:
[root@shuai-01 ~]# rpm -qa libevent
libevent-2.0.21-4.el7.x86_64
启动memcached:
[root@shuai-01 ~]# systemctl start memcached
用命令行的形式启动memcached
[root@shuai-01 ~]# ps aux |grep memcache
memcach+ 3200 0.0 0.1 325568 1180 ? Ssl 10:42 0:00 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024
root 3207 0.0 0.0 112680 976 pts/0 R+ 10:43 0:00 grep --color=auto memcache
/usr/bin/memcached 命令行启动。在启动的过程中可以更改参数 :
-u 指定用户
-p 指定端口
-m 指定内存大小
-c 指定最大并发连接数
在memcache的配置文件中可以编辑配置文件,加上监听的IP,可以吧OPTIONS= “127.0.0.1”
[root@shuai-01 ~]# vi /etc/sysconfig/memcached
PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""
平时我们需要查看memcached的状态,如查看命中数
一般的,可以使用telnet 加端口号11211查看一些基本的。
memcached还是有自己的工具
[root@shuai-01 ~]# memcached-tool 127.0.0.1:11211 stats
会出来一堆东西和参数,主要关注的是 curr_items 存在memcached有多少个羡慕
get_hits 命中了多少。
或者可以使用echo stats |nc 127.0.0.1 11211
在这之前要安装nc工具
[root@shuai-01 ~]# yum install -y nc
[root@shuai-01 ~]# rpm -qf `which nc`
nmap-ncat-6.40-7.el7.x86_64
使用,注意IP和端口间是没有冒号的
[root@shuai-01 ~]# echo stats |nc 127.0.0.1 11211
STAT pid 3200
STAT uptime 3684
STAT time 1523936649
STAT version 1.4.15
STAT libevent 2.0.21-stable
STAT pointer_size 64
STAT rusage_user 0.084384
STAT rusage_system 0.152947
STAT curr_connections 10
STAT total_connections 13
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 39
STAT bytes_written 1081
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
也可以用memstat –servers=127.0.0.1:11211 查看memcached服务状态,这个要在安装libmemcached后,才能使用。
[root@shuai-01 ~]# yum install -y libmemcached
[root@shuai-01 ~]# memstat --servers=127.0.0.1:11211
memcache命令行操作,memcache创建数据
进入memcache用telnet命令找不到telnet命令就用yum安装一下。
[root@shuai-01 ~]# telnet 127.0.0.1 11211
-bash: telnet: 未找到命令
[root@shuai-01 ~]# yum intsall -y telnet
命令行进入memcache
[root@shuai-01 ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
memcache语法规则
\r\n \r\n
注:\r\n在windows下是Enter键
可以是set, add, replace
set表示按照相应的存储该数据,没有的时候增加,有的时候覆盖
add表示按照相应的添加该数据,但是如果该已经存在则会操作失败
replace表示按照相应的替换数据,但是如果该不存在则操作失败。
客户端需要保存数据的key
是一个16位的无符号的整数(以十进制的方式表示)。该标志将和需要存储的数据一起存储,并在客户端get数据时返回。客户端可以将此标志用做特殊用途,此标志对服务器来说是不透明的。
为过期的时间。若为0表示存储的数据永远不过期(但可被服务器算法:LRU 等替换)。如果非0(unix时间或者距离此时的秒数),当过期后,服务器可以保证用户得不到该数据(以服务器时间为标准)。
需要存储的字节数,当用户希望存储空数据时可以为0
需要存储的内容,输入完成后,最后客户端需要加上\r\n(直接点击Enter)作为结束标志。
[root@shuai-01 ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
##写入一个值
set key3 1 100 4
1234
STORED
##替换值
replace key3 1 0 5
abcde
STORED
##获取值
get key3 1 5
VALUE key3 1 5
abcde
END
##删除值
delete key3
DELETED
get key3
END
memcache退出:Ctrl+右方括号 输入quit
当你要把memcached服务重启的时候,你要把memcached服务重启一下,因为memcached是缓存,重启服务之后就数据没了。
memcached-tool是支持把数据导入和导出的。
[root@shuai-01 ~]# memcached-tool 127.0.0.1:11211 dump
Dumping memcache contents
Number of buckets: 1
Number of items : 3
Dumping bucket 1 - 3 total items
add k1 1 1523932965 5
12345
add name 1 1523932965 5
shuai
add age 1 1523932965 2
20
[root@shuai-01 ~]# 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@shuai-01 ~]# nc 127.0.0.1 11211 < data.txt
STORED
STORED
STORED
查看重新导入的数据:
[root@shuai-01 ~]# nc 127.0.0.1 11211
get k1
END
这里k1是没有值的。
查看导出的数据,里面有个时间戳。
[root@shuai-01 ~]# cat data.txt
add k1 1 1523932965 5
12345
add name 1 1523932965 5
shuai
add age 1 1523932965 2
20
查看这个时间戳的意思:
[root@shuai-01 ~]# date -d @1523932965
2018年 04月 17日 星期二 10:42:45 CST
在这个时间点将会过期
在当前时间上加上2小时,得到一个时间戳
[root@shuai-01 ~]# date -d "+2 hour" +%s
1523960063
将时间戳写入到data.txt中间去。
[root@shuai-01 ~]# vim data.txt
[root@shuai-01 ~]# nc 127.0.0.1 11211 < data.txt
STORED
STORED
STORED
再次导入,并查看
[root@shuai-01 ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get k1
VALUE k1 1 5
12345
END
get name
VALUE name 1 5
shuai
END
get age
VALUE age 1 2
20
END
^]
telnet> quit
Connection closed.
PHP连接memcached时候PHP中药有有个memcache模块的,或者说是中间件
首先,下载一个包到/usr/local/src目录下
[root@shuai-01 src]# wget http://www.apelearn.com/bbs/data/attachment/forum/memcache-2.2.3.tgz
解压:
[root@shuai-01 src]# tar zxvf memcache-2.2.3.tgz
进去看:没有configure文件的
[root@shuai-01 memcache-2.2.3]# ls
config9.m4 memcache.c memcache_session.c
config.m4 memcache_consistent_hash.c memcache_standard_hash.c
config.w32 memcache.dsp php_memcache.h
CREDITS memcache_queue.c README
example.php memcache_queue.h
使用/usr/local/php-fpm//bin/phpize 生成文件
[root@shuai-01 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
问题1:生成configure文件时可能会遇到报错
# /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文件
安装autoconf
yum install -y autoconf
在编译,产生了configure文件
[root@shuai-01 memcache-2.2.3]# ls
acinclude.m4 config.sub Makefile.global missing
aclocal.m4 configure memcache.c mkinstalldirs
autom4te.cache configure.in memcache_consistent_hash.c php_memcache.h
build config.w32 memcache.dsp README
config9.m4 CREDITS memcache_queue.c run-tests.php
config.guess example.php memcache_queue.h
config.h.in install-sh memcache_session.c
config.m4 ltmain.sh memcache_standard_hash.c
编译:
[root@shuai-01 memcache-2.2.3]# ./configure --with-php-config=/usr/local/php-fpm/bin/php-config
[root@shuai-01 memcache-2.2.3]# echo $?
0
make&&make install完了之后
[root@shuai-01 memcache-2.2.3]# make install
Installing shared extensions: /usr/local/php-fpm/lib/php/extensions/no-debug-non-zts-20131226/
查看,生成了一个memcache.so文件
然后编辑php.ini文件,在其中加上memcache.so文件
[root@shuai-01 memcache-2.2.3]# vi /usr/local/php-fpm/etc/php.ini
加入这个参数
extension=memcache.so
这时候在查看就会有memcache这个模块了。
[root@shuai-01 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
mysql
mysqli
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
Reflection
session
SimpleXML
soap
SPL
sqlite3
standard
tokenizer
xml
xmlreader
xmlwriter
zlib
[Zend Modules]
下载脚本进行测试
[root@shuai-01 ~]# curl www.apelearn.com/study_v2/.memcache.txt> 1.php 2>/dev/null
查看下载的PHP脚本
[root@shuai-01 ~]# cat 1.php
connect("localhost", 11211);
//保存数据
$mem->set('key1', 'This is first value', 0, 60);
$val = $mem->get('key1');
echo "Get key1 value: " . $val ."
";
//替换数据
$mem->replace('key1', 'This is replace value', 0, 60);
$val = $mem->get('key1');
echo "Get key1 value: " . $val . "
";
//保存数组数据
$arr = array('aaa', 'bbb', 'ccc', 'ddd');
$mem->set('key2', $arr, 0, 60);
$val2 = $mem->get('key2');
echo "Get key2 value: ";
print_r($val2);
echo "
";
//删除数据
$mem->delete('key1');
$val = $mem->get('key1');
echo "Get key1 value: " . $val . "
";
//清除所有数据
$mem->flush();
$val2 = $mem->get('key2');
echo "Get key2 value: ";
print_r($val2);
echo "
";
//关闭连接
$mem->close();
?>
测试:
[root@shuai-01 ~]# /usr/local/php-fpm/bin/php 1.php
Get key1 value: This is first value
Get key1 value: This is replace value
Get key2 value: Array
(
[0] => aaa
[1] => bbb
[2] => ccc
[3] => ddd
)
Get key1 value:
Get key2 value:
[root@shuai-01 ~]#
有时候做负载均衡,使用的是lvs做,lvs 不想Nginx有ip_hash,可以·让用户登录保持在一台服务器上。这时候将session存储在memcached里面去,就可以解决这个问题。
有三种方式可以设置吧session存储到memcached服务里面去。
第一种:编辑php.ini添加两行
#指定存储类型
session.save_handler = memcache
#指定memcached服务器IP和端口
session.save_path ="tcp://192.168.176.135:11211"
第二种:httpd.conf中对应的虚拟主机中添加
php_value session.save_handler "memcache"
php_value session.save_path "tcp://192.168.176.135:11211"
第三种:php-fpm.conf对应的pool中添加
php_value[session.save_handler] = memcache
php_value[session.save_path] = " tcp://192.168.176.135:11211 "
打开php.ini查看session默认保存为文件,保存在本地磁盘里/tmp下
[Session]
; Handler used to store/retrieve data.
; http://php.net/session.save-handler
session.save_handler = files
先做测试,下载一个PHP文件
[root@shuai-01 ~]# wget http://study.lishiming.net/.mem_se.txt
将文件移动并重命名到Nginx默认的localhost
[root@shuai-01 ~]# mv .mem_se.txt /data/wwwroot/default/1.php
curl几次PHP文件,/tmp下会生成相对应的文件
[root@shuai-01 ~]# curl localhost/1.php
1524018294
1524018294
34ncjq86kn1b5gokbs2dslt523
[root@shuai-01 ~]# curl localhost/1.php
1524018298
1524018298
mnptivcs3nv4g6cmnvufrdtbr7
[root@shuai-01 ~]# ls /tmp
mysql.sock
sess_34ncjq86kn1b5gokbs2dslt523
sess_mnptivcs3nv4g6cmnvufrdtbr7
shuai.sock
systemd-private-4ba958ea525547dc80752ca3bd49f2a6-vmtoolsd.service-cI9ikx
test.com.log
www.sock
这是没有配置前,session存在本地磁盘的/tmp目录下
可以配置,将session存在memcached上。上文将了三种方法。
[root@shuai-01 ~]# vim /usr/local/php-fpm/etc/php.ini
session.save_handler = memcache
session.save_path = "tcp://192.168.176.135:11211"
设置完成后,给php-fpm做重启,
[root@shuai-01 ~]# /etc/init.d/php-fpm restart
Gracefully shutting down php-fpm .... done
Starting php-fpm done
启动memcached服务
[root@shuai-01 ~]# systemctl start memcached.service
测试:
删掉/tmp、目录下的两个session文件,重新curl1.php,文件不产生在/tmp目录下了。
[root@shuai-01 ~]# rm -f /tmp/sess_*
[root@shuai-01 ~]# ls /tmp
mysql.sock
shuai.sock
systemd-private-4ba958ea525547dc80752ca3bd49f2a6-vmtoolsd.service-cI9ikx
test.com.log
www.sock
[root@shuai-01 ~]# !curl
curl localhost/1.php
1524019222
1524019222
arkkmiescbt7g02nq178cqltf2
[root@shuai-01 ~]# ls /tmp
mysql.sock
shuai.sock
systemd-private-4ba958ea525547dc80752ca3bd49f2a6-vmtoolsd.service-cI9ikx
test.com.log
www.sock
这时文件存在了memcached里面,将memcached里面的数据dump出来查看
[root@shuai-01 ~]# memcached-tool 127.0.0.1:11211 dump > data.txt
Dumping memcache contents
Number of buckets: 1
Number of items : 1
Dumping bucket 3 - 1 total items
[root@shuai-01 ~]# cat data.txt
add arkkmiescbt7g02nq178cqltf2 0 1524020663 37
TEST|i:1524019222;TEST3|i:1524019222;
其他两种方法也可以进行尝试。
session是PHP产生的,于memcached无关,只是在PHP中设置了session相关的配置,保存在memcached中,不设置,默认保存在/tmp中
几台服务器做负载均衡的时候,把session保存在memcached中实现共享,不用每台机器都安装memcached服务,只用在一台上安装memcached服务,每一台都安装memcached扩展。PHP和memcached通信就用这个扩展,然后三台机器都安装session存储,都指向一个memcached服务就行。