php的memcache擴展和memcached擴展讀寫數組不相兼容緣由探究

背景

最近公司許多團隊進行升級php7,目前支持php7讀取mc的擴展只有memcached。
可是公司許多項目都會共用一個mc集羣來存取用戶session數據,存的時候是登錄時用memcache擴展以array的形式寫進去,讀的時候天然是用memcache擴展以array的形式讀出來。 可是如今只能使用memcached進行讀取。可是據我所知二者讀取array形式的數據是互不兼容的,所以想探究一下到底是爲何。php

驗證

驗證memcache擴展和memcached擴展讀寫數組數據是否不相兼容
測試腳本:數組

<?php 
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));

執行結果:session

➜ ~ 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)

從結果來看,印證了咱們以前的說法。php7

猜想緣由

因爲string沒有問題,出問題是在array格式裏面。因此懷疑是array存進mc時的序列化方法不一樣。因而乎進行進一步的測試:
編寫測試腳本app

<?php 
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));

執行結果:memcached

➜ ~ 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定義會不相同呢。 抱着這個疑問,試着經過閱讀兩個擴展的源碼查找緣由。code

閱讀兩個擴展的源碼

memcache

php_memcache.h:字符串

#define MMC_SERIALIZED 1 
#define MMC_COMPRESSED 2

memcached

php_memcached.cget

#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的時候,運行

<?php
$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的時候,運行

<?php
$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定義的數組標識不一致致使。
爲了保證memcache擴展和memcached擴展直接寫的數據能夠相互讀取,只能用string的格式寫入mc。
通過此次探究,也讓我認識到許多memcached比memcache更優秀的地方,相信隨着php7的普及,memcache會加速地被歷史所淘汰。

轉載註明來源:
做者: Akay
本文地址: [http://www.akayzhang.com/arti...

相關文章
相關標籤/搜索