最近项目中,刚好配置一个新的服务器 memcache 环境。
项目中用到 memcache 缓存的时候,需要先在服务器上安装 memcache 环境,以及配置 PHP 的 memcache 拓展。
目前接触到使用 memcache 缓存的场景是,多终端登录,前后端分离,设置登录 session 值。

安装教程,可以参考阿里云官方文档。

https://help.aliyun.com/document_detail/48432.html?spm=a2c4g.11186623.6.564.4a1a7cc53z7YxM

注: 如果在生产环境的服务器,记得先做备份。

Centos 及 Aliyun Linux 6系列版本

1、确认是否安装了gcc-c++ 等组件(使用 gcc –v 查看版本是否为4.2及以上)。
如没有请执行 yum install gcc+ gcc-c++

2、执行 rpm -qa | grep php 查看系统中是否有 PHP 环境。
如果没有则执行 yum install php-devel,php-common,php-cli 安装包含源码编译的 PHP。

3、检测是否有已安装了 SASL 相关环境包,如没有,则执行 yum install cyrus-sasl-plain cyrus-sasl cyrus-sasl-devel cyrus-sasl-lib 安装 SASL 相关环境。

4、检测下是否有已安装了 libmemcached 源码包,若没有,则执行以下命令安装 libmemcached 源码包(推荐版本 libmemcached-1.0.18)。

wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz 

tar zxvf libmemcached-1.0.18.tar.gz

cd libmemcached-1.0.18

./configure --prefix=/usr/local/libmemcached --enable-sasl

make

make install

cd ..

5、执行 yum install zlib-devel 安装 memcached 源码包(推荐版本为 memcached-2.2.0)。
注意:
1、安装 memcached 前需要确认是否有 zlib-devel 包需要执行。

2、请先检测下是否已安装了 memcached 客户端包(包含源码包)。如有则不需要安装,但需要重新编译增加 -enable-memcached-sasl 这个扩展。

wget http://pecl.php.net/get/memcached-2.2.0.tgz

tar zxvf memcached-2.2.0.tgz

cd memcached-2.2.0

phpize(如果系统中有两套PHP环境,需绝对路径调用该命令/usr/bin/phpize,该路径为使用云数据库Memcache的PHP环境路径)

./configure --with-libmemcached-dir=/usr/local/libmemcached --enable-memcached-sasl(注意这个参数)

make

make install

6、修改 php.ini 文件(locate 找该文件,如果系统中有两套 PHP 环境,需找到使用云数据库 Memcache 的 PHP 环境路径,对应修改之),
末尾增加

extension=memcached.so
memcached.use_sasl = 1

7、使用该页面最后的测试代码测试下是否环境部署成功,请修改代码中相应的地址、端口、用户名及密码。
注:新版的阿里云 memcache 服务,账号为实例ID


【 PHP实例代码 】

示例1:基本的连接云数据库 Memcache 及 set/get 操作

$connect = new Memcached;  //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false); //关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true); //使用binary二进制协议
$connect->setOption(Memcached::OPT_TCP_NODELAY, true); //重要,php memcached有个bug,当get的值不存在,有固定40ms延迟,开启这个参数,可以避免这个bug
$connect->addServer('aaaaaaaaaa.m.yyyyyyyyyyy.ocs.aliyuncs.com', 11211); //添加OCS实例地址及端口号
$connect->setSaslAuthData('aaaaaaaaaa', 'password'); //设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤;新版OCS的username为实例id
$connect->set("hello", "world");
echo 'hello: ',$connect->get("hello");
$connect->quit();

示例2:在云数据库 Memcache 中缓存一个数组

$connect= new Memcached; //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false); //关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true);//使用binary二进制协议
$connect->setOption(Memcached::OPT_TCP_NODELAY, true); //重要,php memcached有个bug,当get的值不存在,有固定40ms延迟,开启这个参数,可以避免这个bug
$connect->addServer('xxxxxxxx.m.yyyyyyyy.ocs.aliyuncs.com', 11211);//添加OCS实例地址及端口号
$connect->setSaslAuthData('xxxxxxxx', 'bbbbbbbb');//设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤
$user = array(
"name" => "ocs",
"age" => 1,
"sex" => "male"
); //声明一组数组
$expire = 60; //设置过期时间
test($connect->set('your_name',$user,$expire), true, 'Set cache failed');
if($connect->get('your_name')){
$result =$connect->get('your_name');
}else{
echo "Return code:", $connect->getResultCode();
echo "Retucn Message:", $connect->getResultMessage (); //如出现错误,解析出返回码
$result=" ";
}
print_r($result);
$connect->quit();
function test($val, $expect, $msg)
{
if($val!= $expect) throw new Exception($msg);
}

示例3:云数据库 Memcache 与 MySQL 数据库结合使用

$connect = new Memcached; //声明一个新的memcached链接
$connect->setOption(Memcached::OPT_COMPRESSION, false);//关闭压缩功能
$connect->setOption(Memcached::OPT_BINARY_PROTOCOL, true);//使用binary二进制协议
$connect->setOption(Memcached::OPT_TCP_NODELAY, true); //重要,php memcached有个bug,当get的值不存在,有固定40ms延迟,开启这个参数,可以避免这个bug
$connect->addServer('xxxxxx.m.yyyyyyyy.ocs.aliyuncs.com', 11211);//添加实例地址 端口号
$connect->setSaslAuthData('xxxxxx', 'my_passwd');//设置OCS帐号密码进行鉴权,如已开启免密码功能,则无需此步骤
$user = array(
"name" => "ocs",
"age" => 1,
"sex" => "male"
); //定义一组数组
if($connect->get('your_name'))
{
$result =$connect->get('your_name');
print_r($result);
echo "Found in OCS, get data from OCS"; //如果获取到数据,则打印此数据来源于OCS
exit;
}
else
{
echo "Return code:", $connect->getResultCode();
echo "Retucn Message:", $connect->getResultMessage ();//抛出code返回码
$db_host='zzzzzz.mysql.rds.aliyuncs.com'; //数据库地址
$db_name='my_db'; //database name
$db_username='db_user'; //数据库用户名
$db_password='db_passwd';//数据库用户密码
$connection=mysql_connect($db_host,$db_username,$db_password);
if (!mysql_select_db($db_name, $connection))
{
echo 'Could not select database'; //数据库连接不成功则抛出错误信息
exit;
}
$sql = "SELECT name,age,sex FROM test1 WHERE name = 'ocs'";
$result = mysql_query($sql, $connection);
while ($row = mysql_fetch_assoc($result))
{
$user = array(
"name" => $row["name"],
"age" => $row["age"],
"sex" => $row["sex"],
);
$expire = 5; //设置数据在缓存中的过期时间
test($connect->set('your_name',$user,$expire), true, 'Set cache failed'); //写入OCS缓存
}
mysql_free_result($result);
mysql_close($connection);
}
print_r($connect->get('your_name')); //打印出 获取到的数据
echo "Not Found in OCS,get data from MySQL"; //确认从数据库获取的数据
$connect->quit();
function test($val, $expect, $msg)
{
if($val!= $expect) throw new Exception($msg);
}

【踩坑】

尝试配置的时候,设置好 阿里云 memcache 参数,发现返回一个错误:UNKNOWN READ FAILURE7

查了一晚上,也没什么结果,第二天一看发现,配置的IP白名单有问题。

因为购买 memcache 的时候,绑定了专有网络,但是我在绑定 IP 白名单的时候却用到了外网IP,所以导致了读错误。

后面修改白名单后,也是顺利解决了这个问题。