1

我将大量日志数据存储在内存缓存中,以便稍后放入数据库。在对服务器的每个请求中,我使用 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() 从根本上不兼容?

4

1 回答 1

1

由于按原样igbinary存储二进制数据,因此不能保证任何字符都可以使用:您可以序列化包含任何字节、任何字符的字符串或整数。

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

在想到 SQL 查询之前,有两种方法可以将记录的数据保留在内存之外和内存缓存中:

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

预订可以这样进行:

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

这将确保每次\n在输出中有 a 时,它后面都会跟着 a0或 a 1

我不会替换\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);
于 2015-10-26T22:32:44.670 回答