我已经开始使用 increment() PHP Memcached 客户端的方法,并切换到二进制协议(protocol)。显然,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"
鉴于 key 在一开始递增之前不存在,并且 increment() 调用的初始值是 1,我希望返回的值是一个整数。相反,返回的字符串看起来像是遗留的垃圾,例如该字符串的 ants 部分没有相关性。
其他(可能)相关信息:
最佳答案
这是 PHP 扩展代码中的错误...
我深入研究了包装 libmemcached 的 PHP 扩展代码和 libmemcached API 代码本身,但我认为我已经找到了问题的可能根本原因...
如果您查看 PHP Memcached::increment() 实现,您会在 line 1858 of php_memcached.c 上看到
status = memcached_increment_with_initial(m_obj->memc, key, key_len, (unsigned int)offset, initial, expiry, &value);
这里的问题是 offset 可能是也可能不是 64 位宽。 libmemcached API告诉我们 memcached_increment_with_initial 函数签名需要 uint64_t 用于 offset 而这里 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
"
作为该脚本的输出。 请注意,这仅在该内存缓存服务器上尚不存在键 foo 时有效。还要注意该字符串的长度为 22 个字符,当显然它不应该接近那个。
如果您查看该字符串的十六进制表示....
var_dump(bin2hex($memcached->get('foo')));
最后的结果是清除垃圾...
string(44) "38353839393334353932000d0a000000000000000000"
正在存储的对象在两次转换之间明显损坏。因此,您最终可能会得到与我相同的结果,或者您最终可能会得到完全损坏的数据,正如您在上面所展示的那样。这取决于类型转换如何影响当时存储的内存块(此处属于未定义行为)。此外,唯一看似根本的原因是使用带有增量的初始值(随后使用 increment 并不能证明该问题或 key 是否已经存在)。
我猜这个问题源于 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 代码之间的 key 以某种方式被破坏。
关于带有二进制协议(protocol)的 PHP Memcached—— `increment()` 之后返回的垃圾数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33550880/
我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_
我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
使用rspec-rails3.0+,测试设置分为spec_helper和rails_helper我注意到生成的spec_helper不需要'rspec/rails'。这会导致zeus崩溃:spec_helper.rb:5:in`':undefinedmethod`configure'forRSpec:Module(NoMethodError)对thisissue最常见的回应是需要'rspec/rails'。但这是否会破坏仅使用spec_helper拆分rails规范和PORO规范的全部目的?或者这无关紧要,因为Zeus无论如何都会预加载Rails?我应该在我的spec_helper中做
假设我有一个类A,里面有一些方法。假设stringmethodName是这些方法之一,我已经知道我想给它什么参数。它们在散列中{'param1'=>value1,'param2'=>value2}所以我有:params={'param1'=>value1,'param2'=>value2}a=A.new()a.send(methodName,value1,value2)#callmethodnamewithbothparams我希望能够通过传递我的哈希以某种方式调用该方法。这可能吗? 最佳答案 确保methodName是一个符号,而
我正在开发一个Ruby脚本,需要在没有Ruby解释器的情况下部署到系统上。它将需要在使用ELF格式的FreeBSD系统上运行。我知道有一个ruby2exe项目可以编译在Windows上运行的ruby脚本,但是在其他操作系统上这样做容易吗?甚至可能吗? 最佳答案 您是否检查过Rubinius或JRuby是否允许您预编译您的代码? 关于ruby-ruby脚本可以预编译成二进制文件吗?,我们在StackOverflow上找到一个类似的问题: https://
当我进入Rails控制台时,我已将pry设置为加载代替irb。我找不到该页面或不记得如何将其恢复为默认行为,因为它似乎干扰了我的Rubymine调试器。有什么建议吗? 最佳答案 我刚发现问题,pry-railsgem。忘记了它的目的是让“railsconsole”打开pry。 关于ruby-on-rails-带有Pry的Rails控制台,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/question
我了解instance_eval和class_eval之间的基本区别。我在玩弄时发现的是一些涉及attr_accessor的奇怪东西。这是一个例子:A=Class.newA.class_eval{attr_accessor:x}a=A.newa.x="x"a.x=>"x"#...expectedA.instance_eval{attr_accessor:y}A.y="y"=>NoMethodError:undefinedmethod`y='forA:Classa.y="y"=>"y"#WHATTT?这是怎么回事:instance_eval没有访问我们的A类(对象)然后它实际上将它添加到
问题1:我无法通过以下方式找到将负整数转换为二进制的方法。我应该像这样转换它。-3=>"11111111111111111111111111111101"我在下面试过:sprintf('%b',-3)=>"..101"#..appearsanddoesnotshow111111bit.-3.to_s(2)=>"-11"#Thisjustadds-tothebinaryofthepositiveinteger3.问题2:有趣的是,如果我使用在线转换器,它告诉我-3的二进制是“0010110100110011”。"11111111111111111111111111111101"和"001
给定一个元素和一个数组,Ruby#index方法返回元素在数组中的位置。我使用二进制搜索实现了我自己的索引方法,期望我的方法会优于内置方法。令我惊讶的是,内置的在实验中的运行速度大约是我的三倍。有Rubyist知道原因吗? 最佳答案 内置#indexisnotabinarysearch,这只是一个简单的迭代搜索。但是,它是用C而不是Ruby实现的,因此自然可以快几个数量级。 关于Ruby#index方法VS二进制搜索,我们在StackOverflow上找到一个类似的问题: