• 技术文章 >类库下载 >PHP类库

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

    高洛峰高洛峰2016-10-15 16:19:56原创962

    背景

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

    验证

    验证memcache扩展和memcached扩展读写数组数据是否不相兼容测试脚本:

    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时的序列化方法不同。于是乎进行进一步的测试:编写测试脚本

    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 10.199.189.129
    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的时候,运行

    addServer('10.199.189.129', 11511); 
    $mc->set('123',1); 
    var_dump($mc->get('123'));

    执行结果是:

    string(1) "1"

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

    addServer('10.199.189.129', 11511); 
    $mc->set('123',1); 
    var_dump($mc->get('123'));

    执行结果是:

    int(1)

    结论

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


    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:Ueditor 1.4.3.3 PHP图片上传路径修改 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • 检查字符串中是否有外链• php几个不起眼儿的小技巧• 在php中防止SQL注入的方法• 对php一些服务器端特性配置,加强php的安全• 最近写php命令行程序的一些心得
    1/1

    PHP中文网