背景
社内の多くのチームが最近 php7 をアップグレードしました。 現在、php7 の読み取り mc をサポートする唯一の拡張機能は memcached です。ただし、社内の多くのプロジェクトは、ユーザーのセッション データを保存および取得するために mc クラスターを共有します。保存する場合は、ログイン時に配列形式で書き込むために memcache 拡張機能が使用されます。読み取りの場合は、memcache を使用するのが自然です。配列形式で読み出すための拡張子です。 ただし、現在は memcached を使用してのみ読み取ることができます。しかし、私の知る限り、配列形式でデータを読み取る場合、この 2 つは互いに互換性がないため、その理由を調べたいと思います。
検証
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));
実行結果:
➜ ~ 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)
結果から判断すると、前に述べたことが確認されます。
理由を推測してください
文字列には問題がないので、問題は配列形式にあります。なので配列をmcに格納する際のシリアル化方法が違うのではないかと思います。そこで、さらなるテストを行いました: テスト スクリプトを作成します
<?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));
実行結果:
➜ ~ 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 と mc に書き込まれた memcached の結果が同じであることがわかります。つまり、私たちの推測は間違っているということです。 2 つの値のシリアル化処理はまったく同じですが、違いは値の異なるフラグにあります。 memcache が配列データを格納するとき、falg は 1 ですが、memcached は 4 です。mc の値のフラグはユーザーがカスタマイズできるように提供されており、これにより読み取り時のさまざまな処理が容易になることがわかります。しかし、なぜ 2 つのフラグの定義が異なるのでしょうか? この疑問を念頭に置いて、2 つの拡張機能のソース コードを読んで理由を見つけてみてください。
2つの拡張機能のソースコードを読む
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
ソースコードを読んだ後、memcacheは配列形式のフラグを1として定義していることがわかりました。一方、memcached は配列形式フラグを 1 として定義します。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 のキーを保存しましたが、それを読み取ると、それは文字列でした。 そして、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 拡張機能によって直接書き込まれたデータが相互に読み取れるようにするため、mc は文字列形式でのみ書き込むことができます。
この調査の後、memcache が memcache よりも優れている点がたくさんあることにも気づきました。php7 の普及により、memcache は加速度的に歴史から廃止されるだろうと信じています。