• Redis内存管理中的LRU算法


    在讨论Redis内存管理中的LRU算法之前,先简单说一下LRU算法:

    LRU算法:即Least Recently Used,表示最近最少使用页面置换算法。是为虚拟页式存储管理服务的,是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU算法就是将最近最久未使用的页面予以淘汰,类似于末尾淘汰制。

    比如:

    如输入以下序列时:4,7,0,7,1,0,1,2,1,2,6

    可以用一个特殊的栈来保存当前正在使用的各个页面的页面号。当一个新的进程访问某页面时,便将该页面号压入栈顶,其他的页面号往栈底移,如果内存不够,则将栈底的页面号移除。这样,栈顶始终是最新被访问的页面的编号,而栈底则是最近最久未访问的页面的页面号。

       用java代码实现LRU算法如下:

      1 import java.util.ArrayList;
      2 import java.util.List;
      3  
      4  
      5 public class LRU {
      6     /**
      7      * 内存块的个数
      8      */
      9     public static final int N = 5;
     10     /**
     11      * 内存块数组
     12      */
     13     Object[] array = new Object[N];
     14     private int size;
     15     
     16     public LRU() {
     17     }
     18     /**
     19      * 判断内存区是否为空
     20      * @return
     21      */
     22     public boolean isEmpty() {
     23         if(size == 0) {
     24             return true;
     25         } else {
     26             return false;
     27         }
     28     }
     29     /**
     30      * 判断内存区是否达到最大值
     31      * @return
     32      */
     33     public boolean isOutOfBoundary() {
     34         if(size >=N) {
     35             return true;
     36         } else {
     37             return false;
     38         }
     39     }
     40     /**
     41      * 查找元素o在数组中的位置
     42      * @param o
     43      * @return
     44      */
     45     public int indexOfElement(Object o) {
     46         for(int i=0; i<N; i++) { 
     47             if(o == array[i]) {
     48                 return i;
     49             }
     50         }
     51         return -1;
     52     }    
     53     /**
     54      * 有新的数据o需要申请内存
     55      * @param o
     56      * @return 移出内存区的数据
     57      */
     58     public Object push(Object o) {
     59         int t = -1;
     60         if(!isOutOfBoundary() && indexOfElement(o) == -1){
     61             array[size] = o;
     62             size ++;
     63         } else if(isOutOfBoundary() && indexOfElement(o) == -1){
     64             for(int i=0; i<size-1; i++) {
     65                 array[i] = array[i+1];                
     66             }
     67             array[size-1] = o;
     68         } else {
     69             t = indexOfElement(o);
     70             for(int i=t; i<size-1; i++) {
     71                 array[i] = array[i+1];
     72             }
     73             array[size-1] = o;
     74         }
     75         if( -1 == t) {
     76             return null;
     77         } else {
     78             return array[t];
     79         }
     80     }
     81     /**
     82      * 输出内存区中的各数据
     83      */
     84     public void showMemoryBlock() {
     85         for(int i=0; i<size; i++) {
     86             System.out.print(array[i] + "	");
     87         }
     88     }
     89  
     90     /**
     91      * @param args
     92      */
     93     public static void main(String[] args) {
     94         Integer iter[] = {4,7,0,7,1,0,1,2,1,2,6};
     95         LRU lru = new LRU();
     96         for(int i=0; i<iter.length; i++) {
     97             lru.push(iter[i]);
     98             lru.showMemoryBlock();
     99             System.out.println();
    100         }
    101     }
    102  
    103 }

    LRU算法也可以用于一些实际的应用中,如你要做一个浏览器,或类似于淘宝客户端的应用的就要用到这个原理。大家都知道浏览器在浏览网页的时候会把下载的图片临时保存在本机的一个文件夹里,下次再访问时就会,直接从本机临时文件夹里读取。但保存图片的临时文件夹是有一定容量限制的,如果你浏览的网页太多,就会一些你最不常使用的图像删除掉,只保留最近最久使用的一些图片。这时就可以用到LRU算法 了,这时上面算法里的这个特殊的栈就不是保存页面的序号了,而是每个图片的序号或大小;所以上面这个栈的元素都用Object类来表示,这样的话这个栈就可以保存的对象了。

    Redis的数据淘汰机制

    Redis提供了5种数据淘汰策略:

    • volatile-lru:使用LRU算法进行数据淘汰(淘汰上次使用时间最早的,且使用次数最少的key),只淘汰设定了有效期的key
    • allkeys-lru:使用LRU算法进行数据淘汰,所有的key都可以被淘汰
    • volatile-random:随机淘汰数据,只淘汰设定了有效期的key
    • allkeys-random:随机淘汰数据,所有的key都可以被淘汰
    • volatile-ttl:淘汰剩余有效期最短的key
      一般来说,推荐使用的策略是volatile-lru,并辨识Redis中保存的数据的重要性。
    对于那些重要的,绝对不能丢弃的数据(如配置类数据等),应不设置有效期,这样Redis就永远不会淘汰这些数据。
    对于那些相对不是那么重要的,并且能够热加载的数据(比如缓存最近登录的用户信息,当在Redis中找不到时,程序会去DB中读取),可以设置上有效期,这样在内存不够时Redis就会淘汰这部分数据。
    配置方法: maxmemory-policy volatile-lru #默认是noeviction,即不进行数据淘汰 
     
    Over...
     
    参考:
  • 相关阅读:
    计算机一些常见名词解释
    [MSF]server/capture/http_javascript_keylogger键盘记录
    .net(C#)访问Oracle数据库的几种免安装组件的对比
    C# UserControl 判断是否是设计模式中
    Python_cmd的各种实现方法及优劣(subprocess.Popen, os.system和commands.getstatusoutput)
    python 怎么启动一个外部命令程序, 并且不阻塞当前进程
    创建注记图层C# IFeatureWorkspaceAnno
    VisualSVN Server 导入已存在的库
    带您了解Oracle层次查询
    win7系统使用engine进行开发报错,“未能加载文件或程序集”
  • 原文地址:https://www.cnblogs.com/gjmhome/p/11376138.html
Copyright © 2020-2023  润新知