php的memcache扩展和memcached扩展读写数组数据不相兼容原因探究

出处:http://www.akayzhang.com/article/6

背景

最近公司许多团队进行升级php7,目前支持php7读取mc的扩展只有memcached。

但是公司许多项目都会共用一个mc集群来存取用户session数据,存的时候是登陆时用memcache扩展以array的形式写进去,读的时候自然是用memcache扩展以array的形式读出来。 但是现在只能使用memcached进行读取。但是据我所知两者读取array形式的数据是互不兼容的,因此想探究一下究竟是为什么。

验证

验证memcache扩展和memcached扩展读写数组数据是否不相兼容

测试脚本:

echo "========== test  string  ============\n";

$mc = new Memcache;

$mc->addServer('10.199.189.129', 11511);

$key = 'testString';

$mc->set($key, 'test success');

var_dump($mc->get($key));

$mc2 = new memcached;

$mc2->addServer('10.199.189.129', 11511);

var_dump($mc2->get($key));

echo "========== test  array  ============\n";

$key2 = 'testArray';

$mc->set($key2, [1,2,3]);

var_dump($mc->get($key2));

var_dump($mc2->get($key2));

执行结果:

➜  ~ php /apps/dat/test.php

========== test  string  ============

string(12) "test success"

string(12) "test success"

========== test  array  ============

array(3) {

    [0]=> int(1)

    [1]=> int(2)

    [2]=> int(3)

}

int(0)

从结果来看,印证了我们之前的说法。以字符串类型的数据

猜测原因

由于string没有问题,出问题是在array格式里面。所以怀疑是array存进mc时的序列化方法不同。于是乎进行进一步的测试:

编写测试脚本

echo "========== test  array  ============\n";

$mc = new Memcache;

$mc->addServer('10.199.189.129', 11511);

$mc2 = new memcached;

$mc2->addServer('10.199.189.129', 11511);

$key2 = 'testArray1';

$key3 = 'testArray2';

$mc->set($key2, [1,2,3]);

$mc2->set($key3, [1,2,3]);

var_dump($mc->get($key2));

var_dump($mc2->get($key3));

执行结果:

➜  ~ php /apps/dat/test.php

========== test  array  ============

array(3) {

    [0]=> int(1)

    [1]=> int(2)

    [2]=> int(3)

}

array(3) {

    [0]=> int(1)

    [1]=> int(2)

    [2]=> int(3)

}

接下来直接连接mc进行查看

➜  ~ telnet 10.199.189.129 11511

Trying 10.199.189.129...

Connected to msession.vip.vip.co.

Escape character is '^]'.

get testArray1

VALUE testArray1 1 30

a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}

END

get testArray2

VALUE testArray2 4 30

a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}

END

从结果来看,我们可以发现,memcache和memcached写到mc里面的结果是一样的,也就是说我们的猜测是错误的。两个值的序列化处理一模一样,区别在于值的flag不同。 memcache存储array数据的时候,falg为1,而memcached为4. 我们知道,mc中值的flag是提供给使用者自定义,方便再读取的时候做不同的处理。但是为什么两者的flag定义会不相同呢。 抱着这个疑问,试着通过阅读两个扩展的源码查找原因。

阅读源码

memcache

php_memcache.h:

#define MMC_SERIALIZED 1

#define MMC_COMPRESSED 2

memcached

php_memcached.c

#define MEMC_VAL_IS_STRING    0

#define MEMC_VAL_IS_LONG      1

#define MEMC_VAL_IS_DOUBLE    2

#define MEMC_VAL_IS_BOOL      3

#define MEMC_VAL_IS_SERIALIZED 4

#define MEMC_VAL_IS_IGBINARY  5

#define MEMC_VAL_IS_JSON      6

#define MEMC_VAL_IS_MSGPACK    7

经阅读源码,发现memcache将array的数组格式的flag定义为1,而memcached为了将php存进mc中的值进行详细的类型区分,将数据类型定义了string,long,double等等的数据类型。

也就是说,当你使用memcache的时候,运行

$mc = new memcache;

$mc->addServer('10.199.189.129', 11511);

$mc->set('123',1);

var_dump($mc->get('123'));

执行结果是:

string(1) "1"

你明明存了一个值为数字1的key,但是读取的时候却为字符串。 而当你使用memcached的时候,运行

$mc = new memcached;

$mc->addServer('10.199.189.129', 11511);

$mc->set('123',1);

var_dump($mc->get('123'));

执行结果是:

int(1)

结论

memcache扩展和memcached扩展读写数组数据不相兼容的原因是,memcached为了详细地区分数据类型,定义了各种数据类型的标示,而导致其中数组的标识与memcache定义的数组标识不一致导致。 经过这次探究,也让我认识到许多memcached比memcache更优秀的地方,相信随着php7的普及,memcache会加速地被历史所淘汰。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、memcache的概念? Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨...
    桖辶殇阅读 2,262评论 2 12
  • redis这个新产品在sns时很火,而memcache早就存在, 但redis提供出来的功能,好多网站均把它当me...
    常晓晓阅读 985评论 1 8
  • PHP7 已经出来1年了,PHP7.1也即将和大家见面,这么多好的特性,好的方法,为什么不使用呢,也希望PHP越来...
    梦幻_78af阅读 2,122评论 1 10
  • 1.为什么要使用memcache 由于网站的高并发读写需求,传统的关系型数据库开始出现瓶颈,例如: 1)对数据库的...
    苏文星阅读 1,806评论 0 5
  • 资讯类:人人 :http://www.woshipm.com/36氪:http://36kr.com/,看Next...
    斯瓦西里阅读 1,659评论 2 11