Dark Side of Redis —— redis使用的坑

最近一个月一直处于知识爆炸的状态,今天开始一点一点总结。

之前项目使用redis,当作高写入速度的持久化storage来用,遇到了几个问题:

  • redis rdb模式fork子进程进行dump,占用大量CPU,影响主进程的吞吐。
  • aof模式在bgrewrite的时候严重影响服务,并且从aof恢复数据非常慢。
  • 由于dump过于影响服务,不得不将dump间隔拉长至半小时左右,如果crash或宕机,会丢半小时数据。
  • slave每次和master断开连接,重新连接后必须做全数据同步。
  • 读写大型value或者hgetall大量key耗时较长,由于redis单个实例是单线程,会阻塞后续操作,导致redis性能抖动。

问题集中在复制和持久化上。这两天和同事聊天,了解到目前百度和微博都通过修改redis实现绕过了这些坑:

  • 使用rdb和aof结合的方式进行持久化。
  • 主从复制采用基于aof文件的增量同步。
  • 实现proxy层,方便做HA/Cluster,使得redis实例变化(扩容和迁移等操作)对client透明。

简单说一下持久化。所谓rdb和aof结合,其实就是模仿mysql的binlog,定时备份+一段时间的binlog,保证数据不丢失。首先从配置上保证redis的实例大小不超过2G,这样可以保证dump的效率。同时启用rdb和aof,dump间隔时间可以设置的稍长,大于aof文件保留的时间,aof文件根据操作频率定期清理。数据恢复时,先load dump文件,在顺序执行aof文件记录的操作就行了。这种方案避免了aof模式的性能低下的bgrewrite,是一个相对靠谱的持久化方案。

另外redis实现了一种VM机制,在存储数据超过最大内存限制时,将冷数据swap到disk上(逻辑和操作系统虚拟内存类似),这个模式虽然比操作系统的虚拟内存块,但是的性能仍然很烂,所以还是断了用redis存储超过内存大小的数据集的想法。通过容量规划,保证数据量不超过最大内存或者及时扩容。

最近的工作,有一点感触比较深:在大型成熟项目中,可运维性时技术选型的重要考量之一,这一点之前的体会很少。向一个大型项目中引入一项新的技术工具,比如现在的redis、mongodb这样的存储方案,需要考虑:

  • 是否有成熟的运维方案和工具,包括搭建、配置、备份、扩容、迁移、监控等等。
  • 是否足够成熟,坑是不是被踩的差不多了。否则需要项目中有人有源码级别的了解程度,这样出现问题才能快速定位。
  • 是否能完全满足要求,是否需要自己做二次开发,之后是否需要和社区同步,需要多大成本。

要解决上面的问题,必须在新技术引入前,做详细的调研和学习,站在运维性的视角来评估。否则盲目的引入新技术,可能会带来稳定性不达标、运维成本高等各种问题。

This entry was posted in 技术学习 and tagged , . Bookmark the permalink.

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据