目录
一些概念
缓存:
将数据存储到内存中,只有当磁盘胜任不了的时候,才会启用缓存
缺点:断电数据丢失(双电),用缓存存储数据的目的只是为了应付大并发的业务。
数据库:
mysql(关系型数据库,能够保证数据一致性,保证数据不丢失,当因为功能太多,导致性能不高) ===数据参考
缓存数据库:
memcache redis(非关系型数据库,性能极高,但不保证数据完整性) === 业务的数据提供者
memcachedb 会将内存的数据写入到磁盘中
redis 主要工作场所是内存中,但是定期备份内存数据到硬盘
数据库的选择
数据存储,数据仓库选择mysql这种磁盘的数据库
高并发,业务大的应用选择memcache这种内存数据库
数据库分类
关系型数据库 mysql
非关系型数据库(NOSQL) memcached redis MongoDB
memcached介绍
Memcached是一款开源的、高性能的纯内存缓存服务软件。Mem是内存的意思,cache是缓存的意思,d是daemon的意思。
memcache 是项目名称,也是一款软件,其架构是C/S架构。
memcached官网:http://memcached.org/
memcached工作原理
基本概念:slab,page,chunk。
slab,是一个逻辑概念。它是在启动memcached实例的时候预处理好的,每个slab对应一个chunk size,也就是说不同slab有不同的chunk size。具体分配多少个slab由参数 -f (增长因子)和 -n (chunk最小尺寸)决定的。
page,可以理解为内存页。大小固定为1m。slab会在存储请求时向系统申请page,并将page按chunk size进行切割。
chunk,是保存用户数据的最小单位。用户数据item(包括key,value)最终会保存到chunk内。chunk规格是固定的,如果用户数据放进来后还有剩余则这剩余部分不能做其他用途。
memcached工作流程
memcahed实例启动,根据 -f 和 -n 进行预分配slab。以 -n 为最小值开始,以 -f 为比值生成等比数列,直到1m为止(每个slab的chunk size都要按8的倍数进行补全,比如:如果按比值算是556的话,会再加4到560成为8的整倍数)。然后每个slab分配一个page。当用户发来存储请求时(key,value),memcached会计算key+value的大小,看看属于哪个slab。确定slab后看里面的是否有空闲chunk放key+value,如果不够就再向系统申请一个page(如果此时已经达到 -m 参数设置的内存使用上限,则看是否设置了 -M 。如果设置了 -M 则返回错误提示,否则按LRU算法删除数据)。申请后将该page按本slab的chunk size 进行切割,然后分配一个来存放用户数据。
注意:
1)chunk是在page里面划分的,而page固定为1m,所以chunk最大不能超过1m。
2)chunk实际占用内存要加48B,因为chunk数据结构本身需要占用48B。
3)如果用户数据大于1m,则memcached会将其切割,放到多个chunk内。
4)已分配出去的page不能回收。
memcache优点
① 对于用户来讲,用户访问网站更快了,体验更好了。
②对网站来说,数据库压力降低了。只有当内存没有数据时才会去请求数据库。第一次写入的数据也会请求数据库。一般公司没有预热,只有当用户读取过数据库才会放到Memcached中。
② 提升了网站的并发访问,减少服务器数量。
优化建议
1)-n 参数的设置,注意将此参数设置为1024可以整除的数(还要考虑48B的差值),否则余下来的部分就浪费了。
2)不要存储超过1m的数据。因为要拆成多个chunk,计算和时间成本都成倍增加。
3)善用stats命令查看memcached状态。
4)消灭eviction(被删除的数据)。
造成eviction是因为内存不够,有三个思路:
(1)在CPU有余力的情况下开启压缩(PHP扩展);
(2)增加内存;
(3)调整-f参数,减少内存浪费。
5)调整业务代码,提高命中率。
6)缓存小数据。省带宽,省网络I/O时间,省内存。
7)根据业务特点,为数据尺寸区间小的业务分配专用的memcached实例。这样可以调小 -f 参数,使数据集中存在少数几个slab上,内存浪费较少。
启动时最重要的参数:
-m 整个memcached最大内存
-f chunk大小增长因子
-n chunk最小分配空间
-C 禁用CAS
-vvv 打印详细信息
我们通过计算可以看出,每个slab的chunk size大小都是上一个大小的1.25倍,1.25就是memcached启动时制定的-f的值,所以,要根据不同的业务场景调整,既要尽可能少的减少内存浪费,又要存得下我们业务中的数据,再举个例子,加入我们的业务很BT,大小都是200kb,我们该怎么做?那当然是要保证我们申请的chunk大小都是200kb了,虽然memcached并不支持这么做。假如创建了38个slabs,最后数据全都落到了第20-25个slab中,那0-19和26-38的内存就被浪费了,这只是能评估出来的,还有一种情况,加入我们的chunk大小是500kb,数据才200kb,因为每个chunk都只能存储一个,所以一个chunk就会有500kb-200kb的空间浪费,如果有一千万个chunk要存,那将会浪费多少空间?所以,在使用memcached之前,先要评估你的数据,根据它去调整-f因子。
参数介绍
memcached参数使用介绍(Win7用户要以管理员身份启动命令窗口哦!)
-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
memcached使用
服务端
环境
[root@db06 ~]# uname -r
2.6.32-696.el6.x86_64
[root@db06 ~]# uname -m
x86_64
[root@db06 ~]# cat /etc/redhat-release
CentOS release 6.10 (Final)
[root@db06 ~]# getenforce
Disabled
[root@db06 ~]# /etc/init.d/iptables status
iptables:未运行防火墙。
第一个里程碑:安装依赖关系
Memcache用到了libevent这个库用于Socket的处理。
[root@db07 ~]# yum install libevent libevent-devel nc -y
第二个里程碑:安装memcache
[root@db07 ~]# yum install memcached -y
[root@db07 ~]# which memcached3 /usr/bin/memcached
第三个里程碑:启动memcached服务
[root@db07 ~]# memcached -m 16m -p 11211 -d -u root -c 8192
[root@db07 ~]# lsof -i :11211
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
memcached 2279 memcached 26u IPv4 14384 0t0 TCP *:memcache (LISTEN)
memcached 2279 memcached 27u IPv6 14385 0t0 TCP *:memcache (LISTEN)
memcached 2279 memcached 28u IPv4 14388 0t0 UDP *:memcache
memcached 2279 memcached 29u IPv6 14389 0t0 UDP *:memcache
[root@db07 ~]# netstat -lntup |grep memca
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 2279/memcached
tcp 0 0 :::11211 :::* LISTEN 2279/memcached
udp 0 0 0.0.0.0:11211 0.0.0.0:* 2279/memcached
udp 0 0 :::11211 :::* 2279/memcached
注:memcached可以同时启动多个实例,端口不一致即可。
[root@nfs01 ~]# memcached -m 16m -p 11212 -d -u root -c 8192
参数说明:
参数 |
参数说明 |
-m |
max memory to use for items in megabytes (default: 64 MB) |
-p |
TCP port number to listen on (default: 11211) |
-d |
run as a daemon |
-u |
assume identity of <username> (only when run as root) |
-c |
max simultaneous connections (default: 1024) |
第四个里程碑:写入开机自启动
[root@db07 ~]# echo 'memcached -m 16m -p 11211 -d -u root -c 8192' >>/etc/rc.local
客户端部署(web服务器)
第一个里程碑:安装PHP memcache 扩展插件
命令集如下:
cd /server/tools2
wget http://pecl.php.net/get/memcache-2.2.7.tgz3
tar xf memcache-2.2.7.tgz4
cd memcache-2.2.75
/application/php/bin/phpize6
./configure -enable-memcache --with-php-config=/application/php/bin/php-config7 make && make install
查看是否安装成功
[[email protected]]#ls-l /application/php/lib/php/extensions/no-debug-non-zts-20121212/2
total 2523
-rwxr-xr-x 1 root root 258048 Nov 7 10:03 memcache.so
memcache.so表示插件安装成功。
第二个里程碑:配置memcache客户端使其生效
[root@web01 memcache-2.2.7]# cd /application/php/lib/
[root@web01 lib]# vim php.ini #添加
extension_dir = "/application/php/lib/php/extensions/no-debug-non-zts-20121212/"6 extension = memcache.so
第三个里程碑:检测语法,重启服务
[root@web01 lib]# /application/php/sbin/php-fpm -t
[15-Aug-2018 15:53:22] NOTICE: configuration file /application/php5.5.32/etc/php-fpm.conf test is successful
#重启服务
killall php-fpm
killall php-fpm
/application/php/sbin/php-fpm
浏览器访问phpinfo页面出现memcache信息表示配置成功。
第四个里程碑:编写测试memcache文件
[root@web01 bbs]# cat test_memcache.php
<?php
$memcache = new memcache;
$memcache->connect('172.168.1.57', 11211) or die ("Could not connect NFS server");
$memcache->set('key', 'Memcache connect OK');
$get = $memcache->get('key');
echo $get;
?>
测试出现Memcache connect OK 表示连接成功
[root@web01 blog]# /application/php/bin/php test_memcache.php
Memcache connect OK
第五个里程碑:修改php配置(设置session共享)
[root@web01 ~]# vim /application/php/lib/php.ini
原配置
session.save_handler = files
session.save_path = "/tmp"
修改为:
session.save_handler = memcache
session.save_path = "tcp://172.16.1.31:11211"
修改完成之后要重启php服务
killall php-fpm
killall php-fpm
/application/php/sbin/php-fpm
修改之前phpinfo信息
修改之后phpinfo信息
到此企业级memcache(session共享)部署完毕
memcached程序端口监控脚本
线上memcached服务器启动了很多实例,端口很多,需要对这些端口进行监控,并在端口关闭的情况下自启动。监控脚本如下:
ps -ef|grep /usr/bin/memcached|grep -v grep|awk -F" " '{print $13}' > /root/memcache_port.list
cat memcache_port.sh
#!/bin/bash
for i in `cat /root/memcache_port.list`
do
NUM=$(/usr/sbin/lsof -i:$i|wc -l)
if [ $NUM -eq 0 ];then
/usr/bin/memcached -d -m 512 -p $i -u root -c 4096 -P /var/lib/memcache/logs/memcached_$i.pid
else
echo "$i is ok"
fi
done
crontab -l
* * * * * /bin/bash -x /root/memcache_port.sh > /dev/null 2>&1