php的memcache擴充和memcached擴充讀寫陣列不相容原因探究

高洛峰
發布: 2016-10-15 16:19:56
原創
1408 人瀏覽過

背景

最近公司許多團隊進行升級php7,目前支援php7讀取mc的擴充只有memcached。但是公司許多專案都會共用一個mc集群來訪問用戶session數據,存的時候是登陸時用memcache擴展以array的形式寫進去,讀的時候自然是用memcache擴展以array的形式讀出來。 但現在只能使用memcached進行讀取。但據我所知兩者讀取array形式的資料是互不相容的,因此想探究一下究竟是為什麼。

驗證

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

<?php 
echo "========== test string ============\n"; 
$mc = new memcache; 
$mc->addServer(&#39;10.199.189.129&#39;, 11511); 
$key = &#39;testString&#39;; 
$mc->set($key, &#39;test success&#39;); 
var_dump($mc->get($key)); 
$mc2 = new memcached; 
$mc2->addServer(&#39;10.199.189.129&#39;, 11511); 
var_dump($mc2->get($key)); 
echo "========== test array ============\n"; 
$key2 = &#39;testArray&#39;; 
$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時的序列化方法不同。於是乎進行進一步的測試:編寫測試腳本

<?php 
echo "========== test array ============\n"; 
$mc = new memcache; 
$mc->addServer(&#39;10.199.189.129&#39;, 11511); 
$mc2 = new memcached; 
$mc2->addServer(&#39;10.199.189.129&#39;, 11511); 
$key2 = &#39;testArray1&#39;; 
$key3 = &#39;testArray2&#39;; 
$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 &#39;^]&#39;. 
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.cache

reee

reee

碼,發現數字php存進mc中的值進行詳細的型別區分,將資料型別定義了string,long,double等等的資料型別。也就是說,當你使用memcache的時候,運行

#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
登入後複製

執行結果是:

<?php
$mc = new memcache; 
$mc->addServer(&#39;10.199.189.129&#39;, 11511); 
$mc->set(&#39;123&#39;,1); 
var_dump($mc->get(&#39;123&#39;));
登入後複製

你明明存了一個值為數字1的key,但是讀取的時候卻為字符串。 而當你使用memcached的時候,運行

string(1) "1"
登入後複製

執行結果是:

<?php$mc = new memcached; 
$mc->addServer(&#39;10.199.189.129&#39;, 11511); 
$mc->set(&#39;123&#39;,1); 
var_dump($mc->get(&#39;123&#39;));
登入後複製
結論🎜

memcache擴展和memcached擴展讀寫數組資料不相容的原因是,memcached為了詳細地區分資料類型,定義了各種資料類型的標識,而其中數組的標識與memcache定義的數組標識不一致導致。
為了確保memcache擴充和memcached擴充直接寫的資料可以互相讀取,只能用string的格式寫入mc。
經過這次探究,也讓我認識到許多memcached比memcache更優秀的地方,相信隨著php7的普及,memcache會加速地被歷史所淘汰。


來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板