缓存服务器 Redis 作者详谈 2.4 版本改进
fmms 13年前
<div id="p_fullcontent" class="detail"> <p><span class="hilite1"><strong>Redis</strong> 是</span>一个高性能的key-value数据库。 <span class="hilite1">redis</span>的出现,很大程度补偿了memcached这类keyvalue存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Python,Ruby,Erlang,PHP客户端,使用很方便。</p> <p>性能测试结果:</p> <p>SET操作每秒钟 110000 次,GET操作每秒钟 81000 次,服务器配置如下:</p> <p><strong>Linux 2.6</strong>, <strong>Xeon X3320 2.5Ghz</strong>.</p> <p>stackoverflow 网站使用 Redis 做为缓存服务器。<br /> <span style="font-weight:bold;">项目地址</span>:<a href="/misc/goto?guid=4958185538616997143" target="_blank">http://redis.io/</a><br /> <img title="redis.png" border="0" alt="redis.png" src="https://simg.open-open.com/show/3c88605e89bd5c29c2bd09b022a193ed.png" width="93" height="30" /><br /> </p> </div> <p>由于Redis集群可能在较长一段时间内还处理开发阶段,为了避免稳定版本由于这一原因被无限延后,于是从2.2版本fork出了一个2.4分支,这一分支目前进行了一些新的优化改进及bug修复,如果没有严重bug将会在近几个星期内发布稳定版本。</p> <p>随后作者列出了2.4版本中的一大堆<span class="wp_keywordlink_affiliate">优化</span>改进及Bug修复,主要有下面一些:</p> <ul> <li>对小数据量的<span class="wp_keywordlink_affiliate">sorted sets</span>结构的内存使用做很大的优化</li> <li>RDB文件的持久化速度也将会大大提高</li> <li>对目前的一些写操作命令进行了改进,支持批量写入功能</li> <li>启用新的内存分配模式 <em><span class="wp_keywordlink_affiliate">jemalloc</span></em>.</li> <li>通过对copy on write机制使用的优化,数据持久化保存的子进程的内存占用将大大减少</li> <li><span class="wp_keywordlink_affiliate">INFO</span>内容更加丰富</li> <li>新的<span class="wp_keywordlink_affiliate">OBJECT</span>命令,提供对Redis存储value结构描述</li> <li>新的<span class="wp_keywordlink_affiliate">CLIENT</span>命令,提供对Redis客户端连接的信息描述</li> <li>彻底将Slave对Master的连接改成非阻塞,之前connect(2)系统调用是会阻塞的</li> <li>Redis-benchmark、Redis-cli 都进行了几个方面的改进</li> <li>Make 改为彩色输出,更易读</li> <li>VM机制彻底废弃</li> <li>总的来说2.4版本会在各方面有性能上的提升</li> <li>Redis测试框架也有非常大的提升</li> </ul> <p>后面又详细对其中的一些方面做了深入讲解</p> <h3>1.对Sorted Sets的内存优化</h3> <p>实际上在2.2版本中,Redis就对小数据量Value的情况做了性能优化,主要优化方式是将小数据量的Value值不再按具体的数据结构存储, 而是存在一块二进制的整块数据。而这一改进一直没能应用于Sorted Sets数据结构上来,而在2.4版本中,作者终于想到合适的办法把Sorted Sets在小数据量下也进行了此种优化。</p> <h3>2.RDB文件持久化提速</h3> <p>这块很大程度上依赖于上面第1点,由于小量数据被存为一个大的二进制数据块,所以在持久化的时候,就不需要再遍历数据了,只需要一个key进行一次持久化写入。</p> <h3>3.提供批量写入功能</h3> <p>下面是所有提供批量写入功能的命令</p> <ul> <li><strong>SADD set val1 val2 val3 …</strong> — 返回添加的元素个数</li> <li><strong>HDEL hash field2 field3 field3 …</strong> — 返回删除的元素个数</li> <li><strong>SREM set val1 val2 val3 … </strong>– 返回删除的元素个数</li> <li><strong>ZREM zset val1 val2 val3 … </strong>– 返回删除的元素个数</li> <li><strong>ZADD zset score1 val1 score2 val2 … </strong>– 返回添加的元素个数</li> <li><strong>LPUSH/RLPUSH list val1 val2 val3 … </strong>– 返回操作后的LIST的长度</li> </ul> <p>提供批量命令的效果是显而易见的,网络往返的时间被大大节约了,在最理想的网络情况下,作者的测试结果是<strong><span style="color:#ff0000;">一次性写入200w个元素,仅仅花费了1.28秒</span></strong>,每秒超过100w元素的写入!</p> <p>为何不为所有写入命令都加上批量功能呢?作者解释说,由于很多命令在返回值上需要携带信息,如果改成批量的,无法批量返回信息内容。不过相信上面的改进已经可以让很多应用场景得到大大改进了。</p> <h3>4.改用jemalloc的内存分配模式</h3> <p>Redis长期以来的思想就是尽量不产生外部依赖,比如网络事件库没有用传统的libevent库,而是自己单独抽离出几个文件组成的更简单且性能 更高的网络事件启动库,这一库目前在很多开源项目中也被采用。而此次引入jemalloc实在是由于作者认为Linux下的glibc的内存分配器实在是 太烂了,无法有效地防止碎片的产生。</p> <p>虽然jemalloc是外部引入,你也不需要在安装Redis时先安装一堆东西,因为它已经包含在Redis源码里了,你还是像往常一样直接Make编译即可,还是那么方便贴心。</p> <h3>5.减少 copy-on-write 使用</h3> <p>Redis的RDB文件持久化和<span class="wp_keywordlink_affiliate">AOF</span>日 志写入,都是通过调用fork()方法产生子进程来做的。由于主进程还是继续处理请求,当有数据写操作导致数据内容发生变化时,原来的内存段会被复制一 份,这就是我们熟知的copy-on-write机制。而采用这一机制的问题就是,在最坏的情况下,进行一次RDB文件写入,可能导致使用内存加倍。所以 在2.4版本中,作者对这一机制的使用进行了优化,大大减少了对copy-on-write的使用。</p> <p>作者还坦言,自己在2.2版本中在这方面的一些修改是有问题的,这导致了2.2版本中的许多Bug。</p> <h3>6.INFO输出内容增强</h3> <p>2.4版本的INFO内容会有较大改变,其中比较重要的有下面两个</p> <pre>used_memory_peak:185680824 used_memory_peak_human:177.08M</pre> <p>你的实际物理内存使用(RSS)和内存碎片情况通常都与最高峰内存使用相关,而这参数就是用来描述这些情况。一个是以byte为单位(185680824),一个是自动智能单位(177.08M)。</p> <h3>7.测试框架的优化和提速</h3> <p>这一点在NoSQLFan之前的文章《<a href="/misc/goto?guid=4958193594849558430">Redis 测试引擎将升级提速</a>》中有比较详细的描述。有兴趣的朋友可以查看之前的文章。</p> <p>来源:<a href="/misc/goto?guid=4958193595607567363">antirez.com</a></p> <p>原文出处:<a href="/misc/goto?guid=4958193596344028215" target="_blank">http://blog.nosqlfan.com/html/2620.html</a></p>