Redis为了记忆而流产

时间:2015-07-20 20:38:20

标签: c# redis stackexchange.redis

我正在尝试将大文件(电影)以块的形式移动到redis缓存中。 我在Windows机器上使用stackexchange.redis。 redis配置为执行allkey-lru并每秒使用append。 Maxmemory配置为100mb。

ConnectionMultiplexer redis2 = ConnectionMultiplexer.Connect("localhost:6380, syncTimeout=100000");
IDatabase db2 = redis2.GetDatabase();

const int chunkSize = 4096;
string fileName = "D:\\movie.mp4";
using (var file = File.OpenRead(fileName))
{
    int bytesRead;
    int inCounter = 1;
    var buffer = new byte[chunkSize];
    while ((bytesRead = file.Read(buffer, 0, buffer.Length)) > 0)
    {
        db2.StringSet(file.Name + inCounter, buffer);
        inCounter++;
    }
}

当块大小为chunkSize = 4096时,一切都很好。 但是,当我将块大小更改为65536时,服务器崩溃时出现以下日志:

[2816] 20 Jul 23:06:42.300 * Starting automatic rewriting of AOF on 6766592700% growth
[2816] 20 Jul 23:06:42.331 * Background append only file rewriting started by pid 3672
[3672] 20 Jul 23:06:42.331 # Write error writing append only file on disk: Invalid argument
[3672] 20 Jul 23:06:42.331 # rewriteAppendOnlyFile failed in qfork: Invalid argument
[2816] 20 Jul 23:06:42.440 # fork operation complete
[2816] 20 Jul 23:06:42.440 # Background AOF rewrite terminated with error
[2816] 20 Jul 23:06:42.549 * Starting automatic rewriting of AOF on 7232582200% growth
[2816] 20 Jul 23:06:42.581 * Background append only file rewriting started by pid 1440
[2816] 20 Jul 23:06:42.581 # Out Of Memory allocating 10485768 bytes!
[2816] 20 Jul 23:06:42.581 #

=== REDIS BUG REPORT START: Cut & paste starting from here ===
[2816] 20 Jul 23:06:42.581 # ------------------------------------------------
[2816] 20 Jul 23:06:42.581 # !!! Software Failure. Press left mouse button to continue
[2816] 20 Jul 23:06:42.581 # Guru Meditation: "Redis aborting for OUT OF MEMORY" #..\src\redis.c:3467
[2816] 20 Jul 23:06:42.581 # ------------------------------------------------
[1440] 20 Jul 23:06:42.581 # Write error writing append only file on disk: Invalid argument
[1440] 20 Jul 23:06:42.581 # rewriteAppendOnlyFile failed in qfork: Invalid argument

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

变成了一个非常有趣且令人惊讶的问题!

真正的原因是他们正在使用的分配器中的内存碎片(dlmalloc)。 希望MSFT能够做得更好,但我希望这需要一些时间。

与此同时,解决方法。

解决此问题的正确方法(暂时)

配置maxmemorymaxheap个参数。使maxheap远大于maxmemory

因此,如果您需要maxmemory=100MB,请将maxheap提高5倍甚至10倍,例如maxheap=500MB甚至maxheap=1000MB。 我不认为有一个很好的经验法则需要更大maxheap,这就是为什么它是如此棘手的问题。

这样的效果:Redis仍会尝试将内存使用量保持在100MB之下,但实际使用的物理内存可能会 大于此值,可能高达maxheap值。多少完全取决于碎片的程度。希望 在现实生活中,这将保持在合理的水平。

我已经与团队记录了这个问题。 https://github.com/MSOpenTech/redis/issues/274

编辑:根据新知识,我完全重写了这个答案。请参阅编辑历史记录中的先前版本。

答案 1 :(得分:1)

使用此命令设置它将定义的最大堆大小

  

redis-server redis.windows.conf --maxheap 1gb