在研究redis的时候,
对linux进程内存的优化有了意外的收获。
overcommit_memory参数说明:
设置内存分配策略(可选,根据服务器的实际情况进行设置) /proc/sys/vm/overcommit_memory 可选值:0、1、2。 0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。 1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。 2, 表示内核允许分配超过所有物理内存和交换空间总和的内存
overcommit_memory
Controls overcommit of system memory, possibly allowing processes to allocate (but not use) more memory than is actually available.
- 0 - Heuristic overcommit handling. Obvious overcommits of address space are refused. Used for a typical system. It ensures a seriously wild allocation fails while allowing overcommit to reduce swap usage. root is allowed to allocate slighly more memory in this mode. This is the default.
- 1 - Always overcommit. Appropriate for some scientific applications.
- 2 - Don't overcommit. The total address space commit for the system is not permitted to exceed swap plus a configurable percentage (default is 50) of physical RAM. Depending on the percentage you use, in most situations this means a process will not be killed while attempting to use already-allocated memory but will receive errors on memory allocation as appropriate.
值得注意的一点是,redis在dump数据的时候,会fork出一个子进程,理论上child进程所占用的内存和parent是一样的,比如parent占用的内存为8G,这个时候也要同样分配8G的内存给child,如果内存无法负担,往往会造成redis服务器的down机或者IO负载过高,效率下降。所以这里比较优化的内存分配策略应该设置为 1(表示内核允许分配所有的物理内存,而不管当前的内存状态如何)
之前在java进程调用Runtime.getRuntime().exec(command)的时候,就遇到了类似的问题,当初解决方案有两个一个是有一个单独的java进程负责调用系统命令,这个两个进程通过rmi调用,还有一个方案是升级到jdk7,最后选的第一个方案,现在看来还有第三个更好的方案,就是本文所述。