2015-10-26 99 views
1

我将大块日志数据存储在memcache中,以便稍后将其扔入数据库。在对服务器的每个请求中,我使用memcached :: append()保存一组数据,使用换行符来分隔块。一个简化的版本是这样的:分隔二进制数据块

$myCache->append('log', serialize($myArray)."\n"); 

后来,当我要建立可查询我拉所有行从数据库中和反序列化每一个:

$dataToInsert = explode("\n", $myCache->get('log')); 
$dataToInsert = array_map(function($row) { 
    return unserialize($row); 
}, $dataToInsert); 

也能正常工作与构建在serialize()和unserialize()中,但我想利用igbinary的明显优势 - 大小和速度。不幸的是,当我替换函数的igbinary版本时,出现错误。

看来,igbinary-序列化的数据可以包含“\ n”字符,所以当我爆炸存储的数据时,它会创建部分行,当然会失败。

除了换行符以外,我还可以使用分隔符来区分igbinary数据块,还是igbinary和append()从根本上不兼容?

+0

你可以尝试下划线'_',只是因为它自然不是一个分隔符,所以可能工作...没有测试过,但没有做过,但probs值得一试。 – AdamJeffers

+0

当我说二进制数据包含换行符时,我有点不确切;因为它是二进制的,它根本没有字符。但是explode()会将任何'0A'解释为换行符。我想我的问题归结为:'是否有任何字节组合不在我可以爆炸的二进制数据中?或者也许除了爆炸()用来检索离散数据块的方法? – Jerry

回答

1

由于igbinary存储binary data as-is,因此不能保证任何字符可供使用:您可以序列化包含任何字节的字符串或整数,任何字符。

memcached支持添加,删除和替换数据以及更新字符串。

两种方式,以保持记录的数据出来的记忆和memcached的,直到SQL查询浮现在脑海中:

  • 使用多个键:'log1',...,'logN'并跟踪N
  • 通过转义序列化的二进制输出(并在反序列化之前消除)保留一个字符。

预约可以做这样的:

str_replace("\n", "\n1", $data) . "\n0" 

这将确保有每一次的输出\n, 它后跟一个01

我不跟\n\n更换\n,因为这将无法正常工作,如果$data的开始或结束\n

所以:

$myCache->append('log', str_replace("\n", "\n1", igbinary_serialize($myArray)."\n0"); 

拆分然后将数据使用\n0做的,而\n1被转义回\n

$dataToInsert = explode("\n0", $myCache->get('log')); 
$dataToInsert = array_map(function($row) { 
    return igbinary_unserialize(str_replace("\n1", "\n", $row)); 
}, $dataToInsert); 
+0

完美。谢谢!我已经开始编写代码来对每个二进制数据块进行长度前缀,但是这样感觉更好。 – Jerry

+0

这可能会更快,更高效。我认为你的解决方案是最好的答案:-) – Kenney