缘起
PHP连接Memcached一般有两个模块可以使用: libmemcached和memcache;
libmemcached是不支持PHP的长连接的,但是这个模块对各种错误的处理支持的比较好,如果不要求长连接的话,一般使用该模块。
memcache模块自从我开始使用(3年前)用的是2.2.4版本,到现在stable才到2.2.6; 开发极慢,而且最为让人诟病的一个bug就是: get($key)的返回值对于连接失败和NOT FOUND都是返回false的,以至于我无法知道究竟是哪种错误;如果我不关心二者的区别也就算了,对于必须(或者非常有必要)区别二者的话,只好选择使用libmemcached了。
现在遇到的问题是: 我既要区分连接失败和NOT FOUND,我有需要使用长连接,只好去看memcache的源码了。
解决办法
【可直接参看: http://phpor.net/blog/post/888 】
对于memcache的get方法有第二个参数,这个很少使用(而且用的时候也很是不爽的),就是flag参数,该参数为引用传递,旨在回传memcache中的存储标识,而且比较常用的标识就只有几个(如:压缩);看了一下源码,不妨通过该参数来回传失败的类型,如果是NOT FOUND,则可以将该参数设置一个特殊的标识,具体修改代码如下:
==== memcache.c ===
- int mmc_exec_retrieval_cmd(mmc_pool_t *pool, const char *key, int key_len,
- zval **return_value, zval *return_flags TSRMLS_DC) /* {{{ */
- {
- …
- mmc_t *mmc;
- char *command, *value;
- /* not found */
- if (result == 0) {
- flags |= 1<<30;
- ZVAL_FALSE(*return_value);
- }
- …
- }
下面是一个测试脚本:
- <?php
- $m = new Memcache();
- $m->addServer(“127.0.0.1”, 11211); // this is available
- //$m->addServer(“127.0.0.1”, 11219); //this is unavailable
- define(“E_MC_NO_FOUND”, 1<<30);
- $flag=0; // 这个一定要有值,否则是不会回传$flag的,大概这是一个bug吧
- $result = $m->get(“noexists”,$flag);
- if($result === false) {
- if ($flag & E_MC_NO_FOUND) {
- echo “not found\n”;
- } else {
- echo “connect error\n”;
- }
- }
- echo “flag:”.decbin($flag);
遗留问题:
为什么$flag 不设置一个值就不能回传内部的值,究竟源码错在了何处?