`
yiihsia
  • 浏览: 68231 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

redis的内存陷阱

阅读更多

redis是个对内存依赖性很强的NoSql数据库,在内存足够的情况下性能出色

如果只有一台机子去部署redis,一定要特别小心。

比如我有台24G的服务器,理所当然我会将大量内存分配给redis。

比如20G的内存, 问题来了, 当你对redis插入数据后,redis会异步将数据dump到硬盘中

想起来很完美,问题是它会fork一个进程,并占去同样大小的内存,你需要的内存瞬间便为 20G+20G =40G

这时内存超过了物理内存的限制,马上会启动虚拟内存,我的机子上是8G虚拟内存,重点是这个是linux的虚拟内存,并不是redis自己的虚拟内存。

linux的虚拟内存 page很大,IO剧增,dump速度会非常慢,整个服务器的性能降到冰点,服务请求都会堵塞。最严重到机子坏掉。

对于单台机子最好是降低redis虚拟内存设置,page可以根据配置修改,这个虚拟内存比linux的虚拟内存好很多,因为page小很多。

如果你的redis既有读又有写,那么最好不要让redis占去大半的内存。

可以设置它的虚拟内存到8G,这还要根据你的key值大小的衡量,因为key是必须在内存中的,这样一来就算启用了虚拟内存,redis占去的实际内存也会超出设想。

天哪, 就是说必须给redis留出他本身需要一倍以上的内存,平时在不插入数据的时候,内存空着不用,浪费。

此外官方文档中建议对key小,value很大的数据设置虚拟内存。

另外master/slave不是很成熟,目前只支持主从,Redismaster是非阻塞模式,也就是说在slave执行数据同步的时候,master是可以接受客户端的请求的,并不影响同步数据的一致性,然而在slave端是阻塞模式的,slave在同步master数据时,并不能够响应客户端的查询

可以根据master/slave的特点,master不dump,它只负责写数据,让slave去dump

 

分享到:
评论
8 楼 yiihsia 2010-12-16  
<p>http://code.google.com/p/redis/issues/detail?id=150  google上有讨论<br><br>前面有些不对的地方,这里比较全面 <a href="http://www.yiihsia.com/2011/04/%E5%AF%B9redis%E6%95%B0%E6%8D%AE%E6%8C%81%E4%B9%85%E5%8C%96%E7%9A%84%E4%B8%80%E4%BA%9B%E6%83%B3%E6%B3%95/" target="_blank">对redis数据持久化的一些想法 </a></p>
<p> </p>
7 楼 J-catTeam 2010-12-05  
<div class="quote_title">yiihsia 写道</div>
<div class="quote_div">
<p><span style="font-family: verdana, sans-serif; font-size: 14px; line-height: 21px;">
</span></p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">redis是个对内存依赖性很强的NoSql数据库,在内存足够的情况下性能出色</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">如果只有一台机子去部署redis,一定要特别小心。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">比如我有台24G的服务器,理所当然我会将大量内存分配给redis。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">比如20G的内存, 问题来了, 当你对redis插入数据后,redis会异步将数据dump到硬盘中</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;"><span style="color: #ff0000;">想起来很完美,问题是它会fork一个进程,并占去同样大小的内存,你需要的内存瞬间便为 20G+20G =40G</span></p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">这时内存超过了物理内存的限制,马上会启动虚拟内存,我的机子上是8G虚拟内存,重点是这个是linux的虚拟内存,并不是redis自己的虚拟内存。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">linux的虚拟内存 page很大,IO剧增,dump速度会非常慢,整个服务器的性能降到冰点,服务请求都会堵塞。最严重到机子坏掉。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">对于单台机子最好是降低redis虚拟内存设置,page可以根据配置修改,这个虚拟内存比linux的虚拟内存好很多,因为page小很多。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">如果你的redis既有读又有写,那么最好不要让redis占去大半的内存。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">可以设置它的虚拟内存到8G,这还要根据你的key值大小的衡量,因为key是必须在内存中的,这样一来就算启用了虚拟内存,redis占去的实际内存也会超出设想。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;"><strong><span style="color: #ff0000;">天哪, 就是说必须给redis留出他本身需要一倍以上的内存,平时在不插入数据的时候,内存空着不用,浪费。</span></strong></p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">此外官方文档中建议对key小,value很大的数据设置虚拟内存。</p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">另外master/slave不是很成熟,目前只支持主从,Redis<span>在</span>master<span>是非阻塞模式,也就是说在</span>slave<span>执行数据同步的时候,</span>master<span>是可以接受客户端的请求的,并不影响同步数据的一致性,然而在</span>slave<span>端是阻塞模式的,</span>slave<span>在同步</span>master<span>数据时,并不能够响应客户端的查询</span></p>
<p style="padding-top: 0.9em; padding-right: 0px; padding-bottom: 0.9em; padding-left: 0px; margin: 0px;">可以根据master/slave的特点,master不dump,它只负责写数据,让slave去dump</p>
<p> </p>
</div>
<p>虽然不清楚具体,不过作者应该不会这么傻的。</p>
6 楼 evolwave 2010-11-30  
裔帝,真是无处不在。
5 楼 Gallardot 2010-11-30  

楼主说:“想起来很完美,问题是它会fork一个进程,并占去同样大小的内存,你需要的内存瞬间便为 20G+20G =40G”


这个应该不对吧?fork子进程之后,子进程和父进程是共享内存的,并且是采用copy on write的方式处理被修改的内容。

如redis中,fork子进程之后,父进程的某一个key的内容被修改了,那么内核只是对当前key的内容复制一份然后再进行修改。。。
4 楼 yiihsia 2010-11-15  
agapple 写道
yiihsia 写道
agapple 写道
楼主,有没一些具体的数据做说明呢?比如你观测到linux系统状态数据,或者截图啥的

有2个疑问:
1. 它fork的子进程,为什么会使用相同的内存大小进行dump操作,作者不至于这么蠢吧。
2. 疑惑的是linux针对运行进程都有虚拟内存的概念,就像你准备开2G的内存,操作系统并不会立即给你那么大的实际内存,它只给你一个虚的内存地址,到真实用的时候才会去换入内存page页。所以即使fork子进程的时候,需要那么大的内存,系统也不会立马分配给你。不知你提的page是不是也是内存page页的概念?


http://yiihsia.iteye.com/admin/pictures  我截了图你可以看下。

第一个问题,主进程继续提供服务,同时fork出来的进程把数据dump到磁盘里,这样可以保证dump的时候数据不再变化的同时能够继续提供读写服务

第二个问题,redis有自己的虚拟内存,相对linux的VM更加轻量,但是在写密集的时候,redis的VM的性能不佳,linux的VM更加悲剧



第一个问题,大致明白了。不过那图片看不到。

第二个可能比较深,我自己再了解一下

非常感谢解答


关于linux的虚拟内存我也没有深入了解
3 楼 agapple 2010-11-15  
yiihsia 写道
agapple 写道
楼主,有没一些具体的数据做说明呢?比如你观测到linux系统状态数据,或者截图啥的

有2个疑问:
1. 它fork的子进程,为什么会使用相同的内存大小进行dump操作,作者不至于这么蠢吧。
2. 疑惑的是linux针对运行进程都有虚拟内存的概念,就像你准备开2G的内存,操作系统并不会立即给你那么大的实际内存,它只给你一个虚的内存地址,到真实用的时候才会去换入内存page页。所以即使fork子进程的时候,需要那么大的内存,系统也不会立马分配给你。不知你提的page是不是也是内存page页的概念?


http://yiihsia.iteye.com/admin/pictures  我截了图你可以看下。

第一个问题,主进程继续提供服务,同时fork出来的进程把数据dump到磁盘里,这样可以保证dump的时候数据不再变化的同时能够继续提供读写服务

第二个问题,redis有自己的虚拟内存,相对linux的VM更加轻量,但是在写密集的时候,redis的VM的性能不佳,linux的VM更加悲剧



第一个问题,大致明白了。不过那图片看不到。

第二个可能比较深,我自己再了解一下

非常感谢解答
2 楼 yiihsia 2010-11-15  
agapple 写道
楼主,有没一些具体的数据做说明呢?比如你观测到linux系统状态数据,或者截图啥的

有2个疑问:
1. 它fork的子进程,为什么会使用相同的内存大小进行dump操作,作者不至于这么蠢吧。
2. 疑惑的是linux针对运行进程都有虚拟内存的概念,就像你准备开2G的内存,操作系统并不会立即给你那么大的实际内存,它只给你一个虚的内存地址,到真实用的时候才会去换入内存page页。所以即使fork子进程的时候,需要那么大的内存,系统也不会立马分配给你。不知你提的page是不是也是内存page页的概念?


http://yiihsia.iteye.com/admin/pictures  我截了图你可以看下。

第一个问题,主进程继续提供服务,同时fork出来的进程把数据dump到磁盘里,这样可以保证dump的时候数据不再变化的同时能够继续提供读写服务

第二个问题,redis有自己的虚拟内存,相对linux的VM更加轻量,但是在写密集的时候,redis的VM的性能不佳,linux的VM更加悲剧
1 楼 agapple 2010-11-13  
楼主,有没一些具体的数据做说明呢?比如你观测到linux系统状态数据,或者截图啥的

有2个疑问:
1. 它fork的子进程,为什么会使用相同的内存大小进行dump操作,作者不至于这么蠢吧。
2. 疑惑的是linux针对运行进程都有虚拟内存的概念,就像你准备开2G的内存,操作系统并不会立即给你那么大的实际内存,它只给你一个虚的内存地址,到真实用的时候才会去换入内存page页。所以即使fork子进程的时候,需要那么大的内存,系统也不会立马分配给你。不知你提的page是不是也是内存page页的概念?

相关推荐

    Redis实战手册

    Redis,全称Remote Dictionary Server,是一款开源的、支持网络的、内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。其以丰富的数据结构(如字符串、哈希、列表、集合、有序集合)和高效的性能著称...

    Redis开发教程案例

    8. 最佳实践,如何优化Redis的性能,避免常见陷阱。 在“redis”这个压缩包子文件中,可能包含了与教程配套的测试代码,供你动手实践。通过运行这些代码,你将能更直观地感受Redis的实际操作,加深对Redis的理解。 ...

    java面试——Redis面试专题.zip

    - 当Redis内存不足时,如何配置LFU或LRU策略? - Redis的发布/订阅模式是如何工作的? 掌握以上知识点,并结合实际项目经验,将有助于你在Java面试中应对Redis相关的提问。在准备过程中,不仅要理解概念,还要关注...

    记Redis那坑人的HGETALL 1

    "Redis的HGETALL性能陷阱及解决方案" Redis作为一个高性能的NoSQL数据库,在很多场景下被广泛应用。但是,Redis的HGETALL命令却存在一些性能陷阱,本文将深入探讨HGETALL的性能问题及其解决方案。 一、HGETALL的...

    Redis命令实践教程.docx.docx

    - **Redis定义**:Redis是一种开源的内存数据结构存储系统,可以作为数据库、缓存和消息中间件使用。 - **安装启动**: - 启动Redis服务:`redis-server` - 连接到Redis服务:`redis-cli` #### 二、基础命令操作 ...

    Kedis:基于Jedis的Redis Kotlin包装器

    在IT行业中,Redis是一个广泛使用的高性能、内存中的数据结构存储系统,常被用作数据库、缓存和消息中间件。它支持丰富的数据类型,如字符串、哈希、列表、集合和有序集合。而Kedis则是针对Redis的一个Java库Jedis的...

    NoSQL误用和常见陷阱分析

    当数据量超出内存限制时,性能会明显下降。 - **Redis做缓存存储**:相比之下,Redis作为缓存使用时性能极佳,提供了丰富的数据结构和持久化机制,有助于避免缓存雪崩。 **3. 细节描述不清楚** 某些NoSQL产品的...

    java面试题集(非常好的资源)

    11. **数据库相关**:包括SQL语句的编写、事务处理、索引优化、JDBC操作等,对于NoSQL数据库如MongoDB、Redis也有基本认识。 12. **网络编程**:理解TCP/IP协议、HTTP协议,以及Socket编程的基本原理。 13. **并发...

    Mysql数据库优化总结-飞鸿无痕-ChinaUnix博客.rar_MYSQL_博客_博客数据库_面试

    创建合适的复合索引,理解索引覆盖(Index Covering)原则,以及避免索引失效的常见陷阱,如在索引列上使用NOT操作符,都是索引优化的关键。 3. **存储引擎选择**:MySQL提供了InnoDB、MyISAM、Memory等多种存储...

    OpenResty 最佳实践

    文档还详细介绍了Lua-resty库的使用,这些库被用于实现各种高级功能,比如Redis客户端库(Lua-resty-redis)、DNS请求库(Lua-resty-dns)、数据库连接池(Postgres Nginx Module)等。 在安全性方面,文档指导了...

    java-opensource-doc开源项目中文文档合集

    - **MongoDB和Redis**:非关系型数据库MongoDB适合处理结构不固定的数据,而Redis是高性能的键值存储系统,文档会介绍它们的使用场景和API。 6. **测试和持续集成** - **JUnit**:单元测试框架,帮助开发者确保...

    程序员应聘面试题大选

    2. **java面试题.rar**:Java是许多公司的首选开发语言,因此深入理解Java语法、异常处理、多线程、IO流、集合框架(如ArrayList、HashMap)以及Java内存模型等是必备的。此外,JVM(Java虚拟机)的工作原理,如垃圾...

    csdn等等各知名论坛收集的java好文章!经典

    6. **分布式与云计算**:学习如何使用Java实现分布式系统,包括分布式缓存(如Redis)、消息队列(如RabbitMQ或Kafka)、服务治理(如Dubbo或Spring Cloud)等。 7. **大数据处理**:Hadoop、Spark等大数据处理框架...

    2018面试宝典核心篇

    - **Redis**:作为一款基于内存的键值存储系统,Redis提供了极高的读写性能,非常适合用作缓存、会话存储等场景。通过使用Redis,可以显著减少对后端数据库的请求,从而提高整体系统的响应速度。 - **MongoDB**:...

    .Net中常见问题及解决方法归类

    1. **缓存机制**:合理利用内存缓存减少数据库访问次数,如使用ASP.NET内置缓存或第三方缓存服务如Redis。 2. **异步编程**:使用C#中的async/await关键字编写异步代码,提高程序响应能力。 3. **代码审查**:定期...

    准备进行技术面试:개발자개발자로서준비를위해식을식을식을식을하는하는:laptop_computer::laptop_computer::laptop_computer:

    - **内存管理**:了解虚拟内存、页表、内存分配与回收策略。 - **I/O模型**:掌握阻塞与非阻塞I/O,同步与异步I/O,以及I/O多路复用(如select、poll、epoll)。 4. **网络**: - **TCP/IP协议栈**:理解网络层...

    PHP高级面试题分享.pdf

    - **Memcache/Redis**:使用内存缓存系统存储Session,速度快,但数据非持久化,服务器崩溃可能导致Session丢失。 - **Cookie**:数据存储在客户端,体积有限,安全性较低,但访问速度较快。 9. **HTTP状态码含义...

    Node.js 开发实践

    最后,教程还会分享作者的个人心得,包括最佳实践、常见问题的解决方案以及如何避免陷阱。这些经验对于初学者来说尤其宝贵,可以帮助他们少走弯路,更快地成长为一名成熟的Node.js开发者。 总的来说,《Node.js ...

Global site tag (gtag.js) - Google Analytics