出處:http://www.akayzhang.com/article/6
背景
最近公司許多團(tuán)隊(duì)進(jìn)行升級(jí)php7婆殿,目前支持php7讀取mc的擴(kuò)展只有memcached。
但是公司許多項(xiàng)目都會(huì)共用一個(gè)mc集群來存取用戶session數(shù)據(jù),存的時(shí)候是登陸時(shí)用memcache擴(kuò)展以array的形式寫進(jìn)去莉炉,讀的時(shí)候自然是用memcache擴(kuò)展以array的形式讀出來庶骄。 但是現(xiàn)在只能使用memcached進(jìn)行讀取。但是據(jù)我所知兩者讀取array形式的數(shù)據(jù)是互不兼容的灌诅,因此想探究一下究竟是為什么芳来。
驗(yàn)證
驗(yàn)證memcache擴(kuò)展和memcached擴(kuò)展讀寫數(shù)組數(shù)據(jù)是否不相兼容
測(cè)試腳本:
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));
執(zhí)行結(jié)果:
?? ~ 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)
從結(jié)果來看,印證了我們之前的說法猜拾。以字符串類型的數(shù)據(jù)
猜測(cè)原因
由于string沒有問題即舌,出問題是在array格式里面。所以懷疑是array存進(jìn)mc時(shí)的序列化方法不同挎袜。于是乎進(jìn)行進(jìn)一步的測(cè)試:
編寫測(cè)試腳本
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));
執(zhí)行結(jié)果:
?? ~ 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進(jìn)行查看
?? ~ 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
從結(jié)果來看顽聂,我們可以發(fā)現(xiàn),memcache和memcached寫到mc里面的結(jié)果是一樣的盯仪,也就是說我們的猜測(cè)是錯(cuò)誤的紊搪。兩個(gè)值的序列化處理一模一樣,區(qū)別在于值的flag不同全景。 memcache存儲(chǔ)array數(shù)據(jù)的時(shí)候耀石,falg為1,而memcached為4. 我們知道爸黄,mc中值的flag是提供給使用者自定義滞伟,方便再讀取的時(shí)候做不同的處理。但是為什么兩者的flag定義會(huì)不相同呢炕贵。 抱著這個(gè)疑問梆奈,試著通過閱讀兩個(gè)擴(kuò)展的源碼查找原因。
閱讀源碼
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
經(jīng)閱讀源碼称开,發(fā)現(xiàn)memcache將array的數(shù)組格式的flag定義為1亩钟,而memcached為了將php存進(jìn)mc中的值進(jìn)行詳細(xì)的類型區(qū)分,將數(shù)據(jù)類型定義了string鳖轰,long清酥,double等等的數(shù)據(jù)類型。
也就是說脆霎,當(dāng)你使用memcache的時(shí)候总处,運(yùn)行
$mc = new memcache;
$mc->addServer('10.199.189.129', 11511);
$mc->set('123',1);
var_dump($mc->get('123'));
執(zhí)行結(jié)果是:
string(1) "1"
你明明存了一個(gè)值為數(shù)字1的key,但是讀取的時(shí)候卻為字符串睛蛛。 而當(dāng)你使用memcached的時(shí)候鹦马,運(yùn)行
$mc = new memcached;
$mc->addServer('10.199.189.129', 11511);
$mc->set('123',1);
var_dump($mc->get('123'));
執(zhí)行結(jié)果是:
int(1)
結(jié)論
memcache擴(kuò)展和memcached擴(kuò)展讀寫數(shù)組數(shù)據(jù)不相兼容的原因是胧谈,memcached為了詳細(xì)地區(qū)分?jǐn)?shù)據(jù)類型,定義了各種數(shù)據(jù)類型的標(biāo)示荸频,而導(dǎo)致其中數(shù)組的標(biāo)識(shí)與memcache定義的數(shù)組標(biāo)識(shí)不一致導(dǎo)致菱肖。 經(jīng)過這次探究,也讓我認(rèn)識(shí)到許多memcached比memcache更優(yōu)秀的地方旭从,相信隨著php7的普及稳强,memcache會(huì)加速地被歷史所淘汰。