带有二进制协议的PHP Memcached – 在`increment()`之后返回的垃圾数据
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了带有二进制协议的PHP Memcached – 在`increment()`之后返回的垃圾数据,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2563字,纯文字阅读大概需要4分钟。
内容图文
![带有二进制协议的PHP Memcached – 在`increment()`之后返回的垃圾数据](/upload/InfoBanner/zyjiaocheng/726/ca3480759edd41c2955443e0f5d47b61.jpg)
我已经开始使用PHP Memcached客户端的increment()方法,并切换到二进制协议.显然,increment()is only supported on the binary protocol.偶尔,我看到垃圾结果从增量键返回.例如:
$memcached = new \Memcached();
$memcached->setOption(\Memcached::OPT_BINARY_PROTOCOL, TRUE);
…
$this->cache->increment($key,1,1);
…
$this->cache->get($key);
输出:
"1\u0000ants1 0 1\r\n1\r\n1\r\n25\r"
鉴于密钥在它首先递增之前不存在,并且初始值1被赋予increment()调用,我期望返回的值是整数.相反,返回的字符串看起来像左边的垃圾,例如该字符串的蚂蚁部分没有相关性.
其他(可能)相关信息:
>我在一系列不同的钥匙上看到了这一点
>我们的Memcached服务器是AWS Elasticache实例
>使用相同缓存节点的其他客户端未使用二进制协议.
>所有客户端都运行相同的操作系统(CentOS),PHP和Memcached版本.
解决方法:
TL;博士;
这是PHP扩展代码中的一个错误……
我挖掘了包含libmemcached和libmemcached API代码本身的PHP扩展代码,但我想我已经找到了问题的潜在根本原因……
如果你看一下你在line 1858 of php_memcached.c上看到的PHP Memcached :: increment()实现
status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value);
这里的问题是偏移可能是64位宽,也可能不是. libmemcached API告诉我们memcached_increment_with_initial函数签名期望uint64_t用于偏移,而这里offset被声明为long,然后转换为unsigned int.
所以,如果我们做这样的事……
$memcached = new memcached;
$memcached->addServer('127.0.0.1','11211');
$memcached->setOption(\Memcached::OPT_BINARY_PROTOCOL, TRUE);
$memcached->delete('foo'); // remove the key if it already exists
$memcached->increment('foo',1,1);
var_dump($memcached->get('foo'));
你会看到……
string(22) "8589934592
"
作为该脚本的输出.请注意,这仅在该memcached服务器上尚不存在密钥foo时才有效.还要注意该字符串的长度为22个字符,显然它不应该在那附近.
如果你看一下该字符串的十六进制表示….
var_dump(bin2hex($memcached->get('foo')));
结果是最后清除垃圾……
string(44) "38353839393334353932000d0a000000000000000000"
正在存储的对象在演员之间明显被破坏.因此,您可能最终得到与我相同的结果,或者您可能最终得到完全破碎的数据,如上所述.它取决于强制转换如何影响当时存储的内存块(这里将进入未定义的行为).此外,唯一看似根本原因是使用带增量的初始值(在此之后使用增量不会证明该问题或密钥已存在).
我猜这个问题源于这样一个事实,即libmemcached API对memcached_increment和memcached_increment_with_initial之间的offset参数有两个不同的大小要求.
memcached_increment(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value)
前者使用uint32_t,而后者使用uint64_t,PHP的扩展代码将两者都转换为unsigned int,这几乎等同于uint32_t.
offset参数宽度的这种差异可能是导致密钥在调用PHP扩展代码和API代码之间以某种方式被破坏的原因.
内容总结
以上是互联网集市为您收集整理的带有二进制协议的PHP Memcached – 在`increment()`之后返回的垃圾数据全部内容,希望文章能够帮你解决带有二进制协议的PHP Memcached – 在`increment()`之后返回的垃圾数据所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。