Background
Many teams in the company have recently upgraded php7. Currently, the only extension that supports php7 reading mc is memcached. However, many projects in the company will share a mc cluster to store and retrieve user session data. When saving, the memcache extension is used to write it in the form of array when logging in. When reading, naturally, the memcache extension is used to read it out in the form of array. But now it can only be read using memcached. But as far as I know, the two are incompatible with each other when reading data in array form, so I want to find out why.
Verification
Verify whether the memcache extension and memcached extension read and write array data are incompatible Test script:
<?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));
Execution result:
➜ ~ 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)
Judging from the results, it confirms our previous statement.
Guess the reason
Since there is no problem with the string, the problem is in the array format. So I suspect that the serialization method when the array is stored in mc is different. So we conducted further testing: Write a test script
<?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));
Execution results:
➜ ~ 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) }
Next, directly connect to mc to view
➜ ~ 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
From the results, we can find that the results of memcache and memcached written to mc are the same , which means our guess is wrong. The serialization processing of the two values is exactly the same, the difference lies in the different flags of the values. When memcache stores array data, falg is 1, while memcached is 4. We know that the flag of the value of mc is provided for users to customize, which facilitates different processing when reading. But why are the flag definitions of the two different? With this question in mind, try to find the reason by reading the source code of the two extensions.
Read the source code of two extensions
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
After reading the source code, I found that memcache defines the flag of the array format as 1, while memcached defines the array format flag as 1. The values stored in mc by php are distinguished in detail, and the data types are defined as string, long, double, etc. In other words, when you use memcache, the execution result of running
<?php $mc = new memcache; $mc->addServer('10.199.189.129', 11511); $mc->set('123',1); var_dump($mc->get('123'));
is:
string(1) "1"
You obviously saved a key with the value 1, but when you read it, it was a string. And when you use memcached, the execution result of running
<?php$mc = new memcached; $mc->addServer('10.199.189.129', 11511); $mc->set('123',1); var_dump($mc->get('123'));
is:
int(1)
Conclusion
The reason why memcache extension and memcached extension are not compatible with reading and writing array data is that memcached defines identifiers of various data types in order to distinguish data types in detail, and the array identifier is inconsistent with the array identifier defined by memcache.
In order to ensure that the data written directly by memcache extension and memcached extension can read each other, mc can only be written in string format.
After this exploration, I also realized that there are many ways that memcached is better than memcache. I believe that with the popularity of php7, memcache will be eliminated by history at an accelerated pace.