• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase
您的位置:首页 > 数据库 >Redis > 关于redis Key淘汰策略的实现方法

关于redis Key淘汰策略的实现方法

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-11

通过本文主要向大家介绍了redis key,redis删除key,redis key 长度,redis key数量,redis key大小等相关知识,希望本文的分享对您有所帮助

1 配置文件中的最大内存删除策略

在redis的配置文件中,可以设置redis内存使用的最大值,当redis使用内存达到最大值时(如何知道已达到最大值?),redis会根据配置文件中的策略选取要删除的key,并删除这些key-value的值。若根据配置的策略,没有符合策略的key,也就是说内存已经容不下新的key-value了,但此时有不能删除key,那么这时候写的话,将会出现写错误。


1.1 最大内存参数设置

若maxmemory参数设置为0,则分两种情况:

*在64位系统上,表示没有限制。
*在32为系统上,是3G,redis官方文档的说法是,32位系统最大内存是4G,预留1G给系统。而且策略会自动设置为noeviction。

也就是说在32位系统上,若maxmemory设置为0,则默认是3G,当到达3G,再往reidis中写入时,则会报错。


1.2 到达最大内存时的几种删除key的策略

*  volatile-lru -> remove the key with an expire set using an LRU algorithm
    按照LRU算法(最少最近没使用)来选取,并删除已经设置了expire时间的key。
*  allkeys-lru -> remove any key accordingly to the LRU algorithm
    根据LRU算法,删除任意的key。不论这个key是否设置了expire时间。
*  volatile-random -> remove a random key with an expire set
    随机删除一个设置了expire时间的key。
*  allkeys-random -> remove a random key, any key
    随机删除任意一个key,不论这个key是否设置了expire时间。
*  volatile-ttl -> remove the key with the nearest expire time (minor TTL)
    删除具有最近终止时间值(TTL)的key。
*  noeviction -> don't expire at all, just return an error on write operations
    若没有设置终止时间,返回一个错误。


1.3 配置内存最大值策略

以下这些命令的默认策略是:volatile-lru

 # At the date of writing this commands are: set setnx setex append
 # incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd
 # sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby
 # zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby
 # getset mset msetnx exec sort
 #
 # The default is:
 # maxmemory-policy volatile-lru


1.4 配置要删除key的检测样本个数

maxmemory-samples

由于LRU和最小TTL算法都是不是精确的算法。因此你可以选择要检测样本的个数。例如,默认情况下redis将会检查3个key,并从这3个key中选取一个最近没有使用的key。当然你可以修改检查样本的个数的值。

要修改这个值,可以通过在配置文件中设置参数:

maxmemory-samples 3

2 实现

这几种删除策略的实现都是在函数 freeMemoryIfNeeded(void) 中完成的。下面具体讲解每种策略是如何实现的。

2.1 什么时候去删除key-value

当设置了maxmemory-policy策略后,什么时候会去删除key呢?

实际上,当设置了maxmemory参数后,在处理每个命令的时候都会根据maxmemory-policy去删除对应的key值。

代码如下:

// 处理客户端的每个命令,都会调用这个函数
int processCommand(redisClient *c) {
  ... ...
  /* Handle the maxmemory directive.
   *
   * First we try to free some memory if possible (if there are volatile
   * keys in the dataset). If there are not the only thing we can do
   * is returning an error. */
  // 以上意思是:若存在可以删除的key,就释放一些内存,若不存在,给客户端返回一个错误。
  if (server.maxmemory) {               // 若maxmemory不为0,则调用以下函数,释放其中一些key
    int retval = freeMemoryIfNeeded();   // 根据配置策略删除key
    if ((c->cmd->flags & REDIS_CMD_DENYOOM) && retval == REDIS_ERR) {  // 若出错,就终止处理命令,把错误返回给客户端
      flagTransaction(c);
      addReply(c, shared.oomerr);
      return REDIS_OK;
    }
  }
  ... ...
}

</div>


实战1:若没有设置maxmemory变量,即使设置了maxmemory-policy,也不会起作用。

实战2:若没有设置maxmemory变量,在处理命令时将不会调用释放策略,会加速命令的处理过程。

2.2 删除key的总体流程

当内存达到最大值时需要按策略删除老的key,所有的删除操作和删除策略的实现都是在函数freeMemoryIfNeeded()中实现的。

在执行删除策略之前,先要选取db和查找key。

总体步骤如下:

int freeMemoryIfNeeded(void) {
  size_t mem_used, mem_tofree, mem_freed;
  int slaves = listLength(server.slaves);
  mstime_t latency;


  /* Remove the size of slaves output buffers and AOF buffer from the
   * count of used memory. */
  mem_used = zmalloc_used_memory();
  if (slaves) {
    listIter li;
    listNode *ln;


    listRewind(server.slaves,&li);
    while((ln = listNext(&li))) {
      redisClient *slave = listNodeValue(ln);
      unsigned long obuf_bytes = getClientOutputBufferMemoryUsage(slave);
      if (obuf_bytes > mem_used)
        mem_used = 0;
      else
        mem_used -= obuf_bytes;
    }
  }
  if (server.aof_state != REDIS_AOF_OFF) {
    mem_used -= sdslen(server.aof_buf);
    mem_used -= aofRewriteBufferSize();
  }


  /* Check if we are over the memory limit. */
  // 检查目前系统是否超过内存的限制
  if (mem_used <= server.maxmemory) return REDIS_OK;


  if (server.maxmemory_policy == REDIS_MAXMEMORY_NO_EVICTION)
    return REDIS_ERR; /* We need to free memory, but policy forbids. */


  /* Compute how much memory we need to free. */
  mem_tofree = mem_used - server.maxmemory;
  mem_freed = 0;
  latencyStartMonitor(latency);
  while (mem_freed < mem_tofree) {
    int j, k, keys_freed = 0;
    // 遍历16个数据库


    for (j = 0; j < server.dbnum; j++) {
      long bestval = 0; /* just to prevent warning */
      sds bestkey = NULL;
      struct dictEntry *de;
      redisDb *db = server.db+j;
      dict *dict;


      // 这里要注意,若是ALLKEYS_xx策略,则直接在对应库结构的dict中查找key。
      // 若是非ALLKEYS_xx策略,也就是可能是 volatile-xxx等策略,操作的库结构将设置成expires结构。


      if (server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_LRU ||
        server.maxmemory_policy == REDIS_MAXMEMORY_ALLKEYS_RANDOM)
      {
        // 若设置了
        dict = server.db[j].dict;
      } else {
        dict = server.db[j].expires;
      }
      // 若数据库的大小为0,说明没有key存在,继续在下一个数据库中查找
      if (dictSize(dict) == 0) continue;


... ... 


}
</div>

2.2 volatile-lru机制和allkeys-lru的实现

2.2.1 redis中的LRU机制

对于LRU机制,redis的官方文档有这样的解释:

Redis LRU algorithm is not an exact implementation. This means that Redis is not able to pick the best candidate for eviction, that is, the access that was accessed the most in the past. Instead it will try to run an approximation of the LRU algorithm, by sampling a small number of keys, and evicting the one that is the best (with the oldest access time) among the sampled keys.
 
However since Redis 3.0 (that is currently in beta) the algorithm was improved to also take a pool of good candidates for eviction. This improved the performance of the algorithm, making it able to approximate more closely the behavior of a real LRU algori
  


 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 关于redis Key淘汰策略的实现方法
  • Redis中实现查找某个值的范围
  • Redis中统计各种数据大小的方法
  • redis key 模糊查询

相关文章

  • 2017-05-11在CentOS 7环境下安装Redis数据库详解
  • 2017-05-11详解redis大幅性能提升之使用管道(PipeLine)和批量(Batch)操作
  • 2017-05-11Redis中主键失效的原理及实现机制剖析
  • 2017-05-11redis中使用redis-dump导出、导入、还原数据实例
  • 2017-05-11在Redis数据库中实现分布式速率限制的方法
  • 2017-05-11win 7 安装redis服务【笔记】
  • 2017-05-11详解Redis用链表实现消息队列
  • 2017-05-11Redis 对比 Memcached 并在 CentOS 下进行安装配置详解
  • 2017-07-22Redis系列(三)--过期策略
  • 2017-09-08Redis4基于CentOS6集群搭建

文章分类

  • MsSql
  • Mysql
  • oracle
  • MariaDB
  • DB2
  • SQLite
  • PostgreSQL
  • MongoDB
  • Redis
  • Access
  • 数据库其它
  • sybase
  • HBase

最近更新的内容

    • Redis主从实现读写分离
    • Redis教程(十二):服务器管理命令总结
    • Redis数据库的应用场景介绍
    • Redis教程(八):事务详解
    • Redis 命令整理并说明如何使用
    • 分割超大Redis数据库例子
    • Redis教程(七):Key操作命令详解
    • Redis的LRU机制介绍
    • Redis中实现查找某个值的范围
    • 详解Redis中的双链表结构

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有