PHP环境中Memcache的安装和使用


Posted in PHP onNovember 05, 2015

Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力。它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。Memcache官方网站:http://www.danga.com/memcached,更多详细的信息可以来这里了解。

为什么会有Memcache和memcached两种名称?其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名,知道我的意思了把~~~~。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。

Memcache的安装

分为两个过程:memcache服务器端的安装和memcached客户端的安装。
所谓服务器端的安装就是在服务器(一般都是linux系统)上安装Memcache实现数据的存储。
所谓客户端的安装就是指php(或者其他程序,Memcache还有其他不错的api接口提供)去使用服务器端的Memcache提供的函数,需要php添加扩展。

PHP的Memcache

<?php
  //连接
  $mem = new Memcache;
  $mem->connect("db.nowamagic.net", );
  //保存数据
  $mem->set('key', 'This is first value', , );
  $val = $mem->get('key');
  echo "Get key value: " . $val ."<br />";
  //替换数据
  $mem->replace('key', 'This is replace value', , );
  $val = $mem->get('key');
  echo "Get key value: " . $val . "<br />";
  //保存数组
  $arr = array('aaa', 'bbb', 'ccc', 'ddd');
  $mem->set('key', $arr, , );
  $val = $mem->get('key');
  echo "Get key value: ";
  print_r($val);
  echo "<br />";
  //删除数据
  $mem->delete('key');
  $val = $mem->get('key');
  echo "Get key value: " . $val . "<br />";
  //清除所有数据
  $mem->flush();
  $val = $mem->get('key');
  echo "Get key value: ";
  print_r($val);
  echo "<br />";
  //关闭连接
  $mem->close();
?>

如果正常的话,浏览器将输出:

Get key value: This is first value
Get key value: This is replace value
Get key value: Array ( [] => aaa [] => bbb [] => ccc [] => ddd )
Get key value:
Get key value:

程序代码分析

初始化一个Memcache的对象:$mem = new Memcache;
连接到我们的Memcache服务器端,第一个参数是服务器的IP地址,也可以是主机名,第二个参数是Memcache的开放的端口:$mem->connect("192.168.0.200", 12000);

保存一个数据到Memcache服务器上,第一个参数是数据的key,用来定位一个数据,第二个参数是需要保存的数据内容,这里是一个字符串,第三个参数是一个标记,一般设置为0或者MEMCACHE_COMPRESSED就行了,第四个参数是数据的有效期,就是说数据在这个时间内是有效的,如果过去这个时间,那么会被Memcache服务器端清除掉这个数据,单位是秒,如果设置为0,则是永远有效,我们这里设置了60,就是一分钟有效时间:$mem->set(‘key1‘, ‘This is first value', 0, 60);

从Memcache服务器端获取一条数据,它只有一个参数,就是需要获取数据的key,我们这里是上一步设置的key1,现在获取这个数据后输出输出:

$val = $mem->get('key′);
echo "Get key value: " . $val;

现在是使用replace方法来替换掉上面key1的值,replace方法的参数跟set是一样的,不过第一个参数key1是必须是要替换数据内容的key,最后输出了:

$mem->replace('key', 'This is replace value', , );
$val = $mem->get('key');
echo "Get key value: " . $val;

同样的,Memcache也是可以保存数组的,下面是在Memcache上面保存了一个数组,然后获取回来并输出:

$arr = array('aaa', 'bbb', 'ccc', 'ddd');
$mem->set('key', $arr, , );
$val = $mem->get('key');
print_r($val);

现在删除一个数据,使用delte接口,参数就是一个key,然后就能够把Memcache服务器这个key的数据删除,最后输出的时候没有结果:

$mem->delete('key');
$val = $mem->get('key');
echo "Get key value: " . $val . "<br />";

最后我们把所有的保存在Memcache服务器上的数据都清除,会发现数据都没有了,最后输出key2的数据为空,最后关闭连接:

$mem->flush();
$val = $mem->get('key');
echo "Get key value: ";
print_r($val);
echo "<br />";

Memcache的使用

使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让Memcache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。我这里简单提出我的个人看法,未经实践,权当参考。

分布式应用

Memcache本来支持分布式,我们客户端稍加改造,更好的支持。我们的key可以适当进行有规律的封装,比如以user为主的网站来说,每个用户都有User ID,那么可以按照固定的ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二胎Mecache服务器上,存取数据都先按照User ID来进行相应的转换和存取。

但是这个有缺点,就是需要对User ID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据自己的实际业务来进行考虑,或者去想更合适的方法。

减少数据库压力

这个算是比较重要的,所有的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,导致数据库性能极具下降,无法同时服务更多的用户,比如MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力吧。我们需要一种改动比较小,并且能够不会大规模改变前端的方式来进行改变目前的架构。

我考虑的一种简单方法:

后端的数据库操作模块,把所有的Select操作提取出来(update/delete/insert不管),然后把对应的SQL进行相应的hash算法计算得出一个hash数据key(比如MD5或者SHA),然后把这个key去Memcache中查找数据,如果这个数据不存在,说明还没写入到缓存中,那么从数据库把数据提取出来,一个是数组类格式,然后把数据在set到Memcache中,key就是这个SQL的hash值,然后相应的设置一个失效时间,比如一个小时,那么一个小时中的数据都是从缓存中提取的,有效减少数据库的压力。缺点是数据不实时,当数据做了修改以后,无法实时到前端显示,并且还有可能对内存占用比较大,毕竟每次select出来的数据数量可能比较巨大,这个是需要考虑的因素。

Memcache的安全

我们上面的Memcache服务器端都是直接通过客户端连接后直接操作,没有任何的验证过程,这样如果服务器是直接暴露在互联网上的话是比较危险,轻则数据泄露被其他无关人员查看,重则服务器被入侵,因为Mecache是以root权限运行的,况且里面可能存在一些我们未知的bug或者是缓冲区溢出的情况,这些都是我们未知的,所以危险性是可以预见的。为了安全起见,我做两点建议,能够稍微的防止黑客的入侵或者数据的泄露。

内网访问

最好把两台服务器之间的访问是内网形态的,一般是Web服务器跟Memcache服务器之间。普遍的服务器都是有两块网卡,一块指向互联网,一块指向内网,那么就让Web服务器通过内网的网卡来访问Memcache服务器,我们Memcache的服务器上启动的时候就监听内网的IP地址和端口,内网间的访问能够有效阻止其他非法的访问。

# memcached -d -m 1024 -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid

Memcache服务器端设置监听通过内网的192.168.0.200的ip的11211端口,占用1024MB内存,并且允许最大1024个并发连接。

设置防火墙

防火墙是简单有效的方式,如果却是两台服务器都是挂在网的,并且需要通过外网IP来访问Memcache的话,那么可以考虑使用防火墙或者代理程序来过滤非法访问。一般我们在Linux下可以使用iptables或者FreeBSD下的ipfw来指定一些规则防止一些非法的访问,比如我们可以设置只允许我们的Web服务器来访问我们Memcache服务器,同时阻止其他的访问。

# iptables -F
# iptables -P INPUT DROP
# iptables -A INPUT -p tcp -s ... ?dport  -j ACCEPT
# iptables -A INPUT -p udp -s ... ?dport  -j ACCEPT

上面的iptables规则就是只允许192.168.0.2这台Web服务器对Memcache服务器的访问,能够有效的阻止一些非法访问,相应的也可以增加一些其他的规则来加强安全性,这个可以根据自己的需要来做。

PHP 相关文章推荐
生成静态页面的PHP类
Jul 15 PHP
简体中文转换为繁体中文的PHP函数
Oct 09 PHP
php adodb操作mysql数据库
Mar 19 PHP
浅析PHP页面局部刷新功能的实现小结
Jun 21 PHP
php随机生成数字字母组合的方法
Mar 18 PHP
php强制下载文件函数
Aug 24 PHP
Mac版PhpStorm之XAMPP整合apache服务器配置的图文教程详解
Oct 13 PHP
php修改数组键名的方法示例
Apr 15 PHP
php接口实现拖拽排序功能
Apr 23 PHP
php实现数组重复数字统计实例
Sep 30 PHP
php设计模式之职责链模式定义与用法经典示例
Sep 19 PHP
PHP项目多语言配置平台实现过程解析
May 18 PHP
php生成gif动画的方法
Nov 05 #PHP
浅析PHP中call user func()函数及如何使用call user func调用自定义函数
Nov 05 #PHP
php无限分类使用concat如何实现
Nov 05 #PHP
PHP json_encode() 函数详解及中文乱码问题
Nov 05 #PHP
PHP explode()函数的几个应用和implode()函数有什么区别
Nov 05 #PHP
双冒号 ::在PHP中的使用情况
Nov 05 #PHP
php根据用户语言跳转相应网页
Nov 04 #PHP
You might like
PHP开发文件系统实例讲解
2006/10/09 PHP
php源码分析之DZX1.5字符串截断函数cutstr用法
2015/06/17 PHP
PHP Class SoapClient not found解决方法
2018/01/20 PHP
对laravel的csrf 防御机制详解,及form中csrf_token()的存在介绍
2019/10/24 PHP
phpstorm最新激活码分享亲测phpstorm2020.2.3版可用
2020/11/22 PHP
IE6/7 and IE8/9/10(IE7模式)依次隐藏具有absolute或relative的父元素和子元素后再显示父元素
2011/07/31 Javascript
js检测输入内容全为空格的方法
2014/05/03 Javascript
原生javascript实现获取指定元素下所有后代元素的方法
2014/10/28 Javascript
JavaScript设计模式之工厂方法模式介绍
2014/12/28 Javascript
js实现当复选框选择匿名登录时隐藏登录框效果
2015/08/14 Javascript
jquery实现多条件筛选特效代码分享
2015/08/28 Javascript
小巧强大的jquery layer弹窗弹层插件
2015/12/06 Javascript
ionic 上拉菜单(ActionSheet)实例代码
2016/06/06 Javascript
Angular脚手架开发的实现步骤
2019/04/09 Javascript
jquery操作checkbox的常用方法总结【附测试源码下载】
2019/06/10 jQuery
vue element upload组件 file-list的动态绑定实现
2019/10/11 Javascript
Selenium执行JavaScript脚本的方法示例
2020/12/31 Javascript
[05:49]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS 选手采访
2021/03/11 DOTA
python实现的二叉树算法和kmp算法实例
2014/04/25 Python
Python random模块(获取随机数)常用方法和使用例子
2014/05/13 Python
Ubuntu安装Jupyter Notebook教程
2017/10/18 Python
人脸识别经典算法一 特征脸方法(Eigenface)
2018/03/13 Python
基于 Django 的手机管理系统实现过程详解
2019/08/16 Python
python实现微信小程序用户登录、模板推送
2019/08/28 Python
Python : turtle色彩控制实例详解
2020/01/19 Python
CSS3制作缩略图的详细过程
2016/07/08 HTML / CSS
企业军训感言
2014/02/08 职场文书
高中毕业生的个人自我评价
2014/02/21 职场文书
环保建议书
2014/03/12 职场文书
党的群众路线教育实践活动心得体会(医院)
2014/11/03 职场文书
学术会议通知
2015/04/15 职场文书
煤矿百日安全活动总结
2015/05/07 职场文书
外科护士长工作总结
2015/08/12 职场文书
怎样写好演讲稿题目?
2019/08/21 职场文书
Golang ort 中的sortInts 方法
2022/04/24 Golang
MySQL 字符集 character
2022/05/04 MySQL