什么是写时复制内存

时间:2014-04-20 16:06:12

标签: redis jedis copy-on-write

随着我不断向redis写入数据,copy-on-write使用的内存不断增加。即使我把我的程序编写为足够长时间以便redis能够完成所有后台保存(最后一条内存消息是写入时写入时使用的内存为0 MB),下一次后台保存将会回到高位号。

实施例,

牛使用的1300MB内存

牛使用的1400MB内存

牛使用的0MB内存

牛使用的1500MB内存

这些意味着什么?据我所知,如果写时复制内存不断增加,那就没有足够的ram了。此外,对于每个使用高内存的后台保存,redis似乎不起作用。 Jedis总是遇到套接字超时异常。

2 个答案:

答案 0 :(得分:0)

来自Redis常见问题解答:

  

Redis后台保存模式依赖于现代操作系统中fork的copy-on-write语义:Redis forks(创建子进程),它是父进程的精确副本。子进程将数据库转储到磁盘上,最后退出。理论上,孩子应该使用尽可能多的内存作为副本,但实际上由于大多数现代操作系统实现的写时复制语义,父和子进程将共享公共内存页。仅当页面在子项或父项中发生更改时,页面才会重复。从理论上讲,所有页面都可能在子进程保存时发生变化。

保存过程中增加的内存使用量取决于由于写时复制(COW)机制而在转储过程中执行的写入次数。

您可以做的是,配置Redis slave并将持久性任务委派给它。

答案 1 :(得分:0)

在这里,我将解释一些事情:Copy-on-Write(CoW)是什么以及它如何消耗内存,为什么设置'vm.overcommit_memory = 1'不能解决内存使用和性能问题,最好备份Redis数据的实践。

写时复制及其内存使用情况

Redis的快照备份利用了现代操作系统提供的CoW语义来解决以下问题:在分叉进程时,将父进程的内存复制到子进程,从而使内存占用量增加一倍。在CoW中,分支的子进程将共享父进程的原始内存空间。仅当任一进程修改了该内存页面时,它才会复制该内存页面。这是数据修改之前和数据修改之后的存储空间的说明:

When the child process Q is forked, it shares the exact memory space as the parent process P When the parent process P modified memory page 3, it made a copy of it, instead of modifying the original page 当Redis的RDB备份正在进行时,父进程中将发生数据更改,父进程正在接受来自客户端的新请求并将其处理在内存中。如果QPS高,则父进程将在子进程的备份时间内复制大量的内存页面以进行新更改。因此,父进程将消耗额外的内存。在极端情况下,如果修改了所有内存页面,则Redis实例的内存占用量将增加一倍。是的,内存有可能翻倍,这个事实将解释Redis为什么提供“ overcommit_memory = 1”选项,以及它可以解决什么问题,它不能解决什么(减少内存使用)。

“ vm.overcommit_memory = 1”是什么,以及它可以解决什么问题

在RDB备份期间,您可能会看到这样的日志错误:

10202:M 13 Sep 11:34:16.535 # Can't save in background: fork: Cannot allocate memory

它表示没有足够的内存来派生子进程进行备份。如果Redis进程现在消耗了2GB内存,则在派生子进程时,操作系统将假定您具有ANOTHER 2GB内存,因此在CoW的极端情况下,有足够的内存来复制所有脏内存页。在派生子进程时,即使尚未使用额外的内存,它也会检查空闲内存,以避免以后出现内存不足错误。在Redis日志中,它提供了解决方案:

10202:M 13 Sep 11:33:09.943 # WARNING overcommit_memory is set to 0! Background
save may fail under low memory condition. To fix this issue add
'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the
command 'sysctl vm.overcommit_memory=1' for this to take effect.

因此,设置'vm.overcommit_memory = 1'将允许您在空闲内存不足时分叉子进程。如果您知道备份过程中的脏内存页面不会太多,就不会有任何实际问题,因为每次执行新的CoW操作时都会成功分配内存。

而且,'vm.overcommit_memory = 1'仅保证您可以派生子进程来备份Redis数据,但是如果在父进程中始终发生写入操作,则它无法减少内存使用。

>

Redis备份做法

persisting the Redis memory data共有三种方式:RDB(快照),AOF以及两者的混合方式。无论您如何配置设置,任何方法都会在一定程度上影响服务器响应时间。为了最大程度地减少持久化过程的影响,我们通常在从属实例上而不是在主实例上运行备份。但是,如果我们在奴隶上进行操作,则存在新的风险。当发生network partitions时,从站可能无法保持最新​​状态,因此备份从站将有丢失某些数据的风险。一种解决方案是拥有多个从属服务器,因此降低了使所有这些与主服务器实例不同步的机会。另一个预防措施是建立强大的监视系统,这样我们就可以更快地检测到网络问题并减少网络分区的时间跨度。

相关问题