Redis用作缓存服务器

转自:http://worldly.iteye.com/blog/2365070 

Redis用作缓存,在有的时候是非常方便地在添加新的数据时自动回收老数据。这种特性在开发者社区广为流传,因为这正是流行的memcached系统的默认特性。

        LRU事实上只是Redis支持的存储回收策略的一种方法。maxmemory指令可以使用之来限制内存大小,本文涵盖了更多的Redis中maxmemory指令的常规讨论,也深入地讨论了Redis采用的LRU这种算法,实际上Redis中的LRU只是LRU算法的近似算法。至于为什么,下文将会讨论。

       maxmemory指令的配置

       maxmomory指令的配置其实已经在《Redis数据库的配置》一文中做了讨论,本文将重新更深入地讨论。maxmemory指令是Redis实现用固定内存大小保存数据集的配置。正如我们已经讨论过的,该指令可以直接在redis.conf配置文件中或者使用新版本的Redis中使用config set命令在运行时配置。

        如为了配置Redis为100M大小的内存,如下的指令可以在redis.conf中使用:

 

Java代码 

 

  1. maxmemory 100MB  

        需要注意的是,若是将maxmemory设置为0将使得Redis无内存无限制,这是64位系统的默认配置,而32位的系统的默认配置是3GB。

        当达到指定的内存大小后,可以有多中的策略供Redis选择,这同样也是一个Redis指令。如仅仅是返回错误信息给客户端,或者回收部分老数据从而可以存储新的数据。

        回收策略

        maxmemory-policy指令是Redis的回收策略的配置命令。可以选择的值如下几种:

        1)noeviction:当内存限制达到配置大小后,客户端执行会占用更多内存的命令如sadd时,Redis仅仅向客户端返回错误信息。

        2)allkeys-lru:总是优先回收最近最少使用(LRU)的keys,一边释放内存以保证新的数据可以被保存下来。

        3)volatile-lru:总是优先回收哪些最新最少使用(LRU)并且设置了过期时间的keys。以确保新的数据可以保存下来。

       4)allkeys-random:随机回收足够的keys以确保新的数据可以保存下来。

       5)volatile-random:随机回收设置了过期时间的keys,yi确保新的数据可以正常保存。

       6)volatile-ttl:优先回收设置了过期时间并且剩余的存活时间更少的的keys(ttl用来测试key的过期时间的剩余量)。

       volatile-lru、volatile-random、volatile-ttl在没有先决条件时,和noeviction的表现是一样的,这个先决条件就是有足够的keys设置了过期时间。

       依据你的应用的访问方式选择合适的内存回收策略是非常重要的。然而,你仍然可以在不停机的情况下,重新配置maxmemory-policy,但是在设置的时候要监控输出信息以便调整设置。

       常见的几个设置的规则:

        1)如果不太确定,allkeys-lru是一个不错的选择。起码可以确保内存中keys的大部分被经常访问而不是被闲置,因为这可以提高客户端请求的命中率。

        2)如果期望所有的keys可以有相等大小的访问几率,或者所有的keys都被定期的扫描,使用allkeys-random是一个好的选择。

        3)如果想让Redis调整keys的过期时间的设置,volatile-ttl会是一个不错的选择。

        volatile-lru和volatile-random策略在非集群的场景下是非常有用的,无论是为了持久化数据还是仅仅是为了缓存之。但是,我们任然建议使用至少两个实例的Redis集群,因为这样可以最大的利用其优势。

        值得注意的是,为keys设置过期时间会消耗一定的内存,所以使用allkeys-lru这样的回收策略是很节省内存的并可以减少内存回收的压力。

       回收是如何实现的

       回收进程运行的先决条件是:

        1)客户端执行了一个新的命令,这个命令将会导致更多的数据被添加到数据库内存中;

        2)Redis检查maxmemory的设置和内存的使用情况,如果内存不足,将按照回收策略回收keys。

        3)新的命令被执行,数据被保存在数据库中。

       这样,数据库内存反复超过限制,紧接着按照回收策略回收部分keys,使得内存使用量下降到限制大小以下。

       如果某个命令将导致大量的内存被占用,内存限制将可能被突破。

       近似的LRU算法

       Redis的LRU算法并不是一个精确的算法实现。这意味着Redis并不能选择最好的候选者,换句话说,最好的候选者是在过去所有的对象中最少使用的,而Redis无法做到这一点(在巨大的键空间查找一个LRU对象是可能的,但是时空消耗角度来讲是不必要的,个人理解),而是采用了一个近似的LRU逻辑:那就是:取样一个小量的keys,在其中选择最好的LRU候选者。

        尽管如此,3.0版本的Redis对此进行了优化:保持一组最好的LRU候选者(理解为池的概念),这样提高了算法性能,使其性能更加接近真实的LRU算法的性能。

        不完美的LRU算法也提供给使用者一个好的调整算法精度的机会:改变算法取样的大小。从统计学的角度讲,当取样的大小无限大的时候,就基本接近了真实的LRU算法,但是内存消耗也相应的增长,这就需要使用者在两者之间选一个平衡点,这正是玩儿家的最大乐趣。

       如下是 redis.conf的取样大小的配置:

 

Java代码 

 

  1. maxmemory-samples  5  

       相关的证明显示,在取样大小为5时,Redis 3.0的表现优于Redis 2.8,但是后者保留了更多的最近使用过的keys。当取样大小为10的时候,Redis 3.0的性能基本非常接近真实的LRU算法性能了。

       在实际情况中,如果使用的是Redis 3.0,可以将取样大小提升至10,以牺牲些许的CPU为代价是之更接近真实的LRU算法性能,然后观察错误率的不同。

       最后, config set命令设置取样大小的命令格式是:

 

Java代码 

 

  1. config set maxmemory-samples    

你可能感兴趣的:(redis)