您好,登錄后才能下訂單哦!
最近公司許多團隊進行升級php7,目前支持php7讀取mc的擴展只有memcached。
但是公司許多項目都會共用一個mc集群來存取用戶session數據,存的時候是登陸時用memcache擴展以array的形式寫進去,讀的時候自然是用memcache擴展以array的形式讀出來。 但是現在只能使用memcached進行讀取。但是據我所知兩者讀取array形式的數據是互不兼容的,因此想探究一下究竟是為什么。
測試腳本:
<?phpecho "========== test string ============\n";$mc = new memcache;$mc->addServer('10.199.189.129', 10002);$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時的序列化方法不同。于是乎進行進一步的測試:
編寫測試腳本
<?phpecho "========== 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定義會不相同呢。 抱著這個疑問,試著通過閱讀兩個擴展的源碼查找原因。
php_memcache.h:
#define MMC_SERIALIZED 1 #define MMC_COMPRESSED 2
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會加速地被歷史所淘汰。
作者: Akay
本文地址: http://www.akayzhang.com/article/6
轉載請注明出處
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。