Redis 作者详谈 2.4 版本改进[转]

由于Redis集群可能在较长一段时间内还处理开发阶段,为了避免稳定版本由于这一原因被无限延后,于是从2.2版本fork出了一个2.4分支,这一分支目前进行了一些新的优化改进及bug修复,如果没有严重bug将会在近几个星期内发布稳定版本。

随后作者列出了2.4版本中的一大堆优化改进及Bug修复,主要有下面一些:

  • 对小数据量的sorted sets结构的内存使用做很大的优化
  • RDB文件的持久化速度也将会大大提高
  • 对目前的一些写操作命令进行了改进,支持批量写入功能
  • 启用新的内存分配模式 jemalloc.
  • 通过对copy on write机制使用的优化,数据持久化保存的子进程的内存占用将大大减少
  • INFO内容更加丰富
  • 新的OBJECT命令,提供对Redis存储value结构描述
  • 新的CLIENT命令,提供对Redis客户端连接的信息描述
  • 彻底将Slave对Master的连接改成非阻塞,之前connect(2)系统调用是会阻塞的
  • Redis-benchmark、Redis-cli 都进行了几个方面的改进
  • Make 改为彩色输出,更易读
  • VM机制彻底废弃
  • 总的来说2.4版本会在各方面有性能上的提升
  • Redis测试框架也有非常大的提升

后面又详细对其中的一些方面做了深入讲解

1.对Sorted Sets的内存优化

实际上在2.2版本中,Redis就对小数据量Value的情况做了性能优化,主要优化方式是将小数据量的Value值不再按具体的数据结构存储, 而是存在一块二进制的整块数据。而这一改进一直没能应用于Sorted Sets数据结构上来,而在2.4版本中,作者终于想到合适的办法把Sorted Sets在小数据量下也进行了此种优化。

2.RDB文件持久化提速

这块很大程度上依赖于上面第1点,由于小量数据被存为一个大的二进制数据块,所以在持久化的时候,就不需要再遍历数据了,只需要一个key进行一次持久化写入。

3.提供批量写入功能

下面是所有提供批量写入功能的命令

  • SADD set val1 val2 val3 … — 返回添加的元素个数
  • HDEL hash field2 field3 field3 … — 返回删除的元素个数
  • SREM set val1 val2 val3 … – 返回删除的元素个数
  • ZREM zset val1 val2 val3 … – 返回删除的元素个数
  • ZADD zset score1 val1 score2 val2 … – 返回添加的元素个数
  • LPUSH/RLPUSH list val1 val2 val3 … – 返回操作后的LIST的长度

提供批量命令的效果是显而易见的,网络往返的时间被大大节约了,在最理想的网络情况下,作者的测试结果是一次性写入200w个元素,仅仅花费了1.28秒,每秒超过100w元素的写入!

为何不为所有写入命令都加上批量功能呢?作者解释说,由于很多命令在返回值上需要携带信息,如果改成批量的,无法批量返回信息内容。不过相信上面的改进已经可以让很多应用场景得到大大改进了。

4.改用jemalloc的内存分配模式

Redis长期以来的思想就是尽量不产生外部依赖,比如网络事件库没有用传统的libevent库,而是自己单独抽离出几个文件组成的更简单且性能 更高的网络事件启动库,这一库目前在很多开源项目中也被采用。而此次引入jemalloc实在是由于作者认为Linux下的glibc的内存分配器实在是 太烂了,无法有效地防止碎片的产生。

虽然jemalloc是外部引入,你也不需要在安装Redis时先安装一堆东西,因为它已经包含在Redis源码里了,你还是像往常一样直接Make编译即可,还是那么方便贴心。

5.减少 copy-on-write 使用

Redis的RDB文件持久化和AOF日 志写入,都是通过调用fork()方法产生子进程来做的。由于主进程还是继续处理请求,当有数据写操作导致数据内容发生变化时,原来的内存段会被复制一 份,这就是我们熟知的copy-on-write机制。而采用这一机制的问题就是,在最坏的情况下,进行一次RDB文件写入,可能导致使用内存加倍。所以 在2.4版本中,作者对这一机制的使用进行了优化,大大减少了对copy-on-write的使用。

作者还坦言,自己在2.2版本中在这方面的一些修改是有问题的,这导致了2.2版本中的许多Bug。

6.INFO输出内容增强

2.4版本的INFO内容会有较大改变,其中比较重要的有下面两个

used_memory_peak:185680824
used_memory_peak_human:177.08M

你的实际物理内存使用(RSS)和内存碎片情况通常都与最高峰内存使用相关,而这参数就是用来描述这些情况。一个是以byte为单位(185680824),一个是自动智能单位(177.08M)。

7.测试框架的优化和提速

这一点在NoSQLFan之前的文章《Redis 测试引擎将升级提速》中有比较详细的描述。有兴趣的朋友可以查看之前的文章。