Redis的内存淘汰策略

news/2024/11/8 22:49:59/

Redis的高性能网络IO模型

Redis的高性能网络IO模型_Lucifer Zhao的博客-CSDN博客

Redis的持久化机制

Redis的持久化机制_Lucifer Zhao的博客-CSDN博客

Redis的过期策略

为了保证内存利用率,会把设置了过期时间并且过期的数据进行删除

惰性过期(被动过期): 通过key拿取数据时才判断是否过期

定期过期: 定期扫描,删除过期的数据

Redis的内存淘汰策略

数据全放在内存中,内存的容量是有限的,有可能存在一些无效的缓存(就是长时间不使用的缓存),如果没有设置过期时间,这些无效的缓存不光会占用内存,导致物理内存不够,还会降低IO性能,时间复杂度增加,所以针对这些问题,Redis一般通过以下方案解决:

  1. 设置过期时间
  2. 增加内存
  3. 设置内存淘汰策略

Redis安装好之后默认64位,内存没有最大限制,如果是32位系统,默认3GB

当内存达到上限时,设置值会报OOM错误,如下所示:

// 获取最大内存设置,如果返回0则代表没有限制,单位是byte
config get maxmemory
// 通过下面命令设置最大内存,如4G
config set maxmemory 4294967296

当内存达到上限时,可以设置LRU算法来释放无效的key

从设置了过期时间的key里扫描,以hash桶为维度扫描,最多扫20个key,一旦扫到某个hash桶必须扫完这个桶里的所有key,如果删除比例超过10%,会继续扫描并删除过期的key,但是最多扫描16次

Redis中提供了8种内存淘汰策略:

  • volatile-lru:针对设置了过期时间的key,使用LRU算法进行淘汰
  • allkeys-lru:针对所有key使用LRU算法进行淘汰
  • volatile-lfu:针对设置了过期时间的key,使用LFU算法进行淘汰
  • allkeys-lfu:针对所有key使用LFU算法进行淘汰
  • volatile-random: 从设置了过期时间的key中随机删除
  • allkeys-random: 从所有key中随机删除
  • volatile-ttl:删除生存时间最近的一个键
  • noeviction(默认策略):不删除键,返回错误OOM,只能读取不能写入

通过修改 maxmemory-policy 配置来设置淘汰策略,默认noeviction

核心本质:选择哪些数据进行清理,选择什么方式去清理数据 

LRU算法

Least Recently Used(最近很少使用)

LRU算法简单逻辑图

双向链表存放很久没有使用的key,hashmap定位某个节点,用来做索引方便查询;随机采集5个key,将5个key加入到双向链表中,链表不停滚动,根据key的使用频率进行排序,最少使用的key就会被移动到队尾从而移除。

LRU算法简单实现

public class LRUCache {private Node head = new Node();;private Node tail = new Node();;private HashMap<String, Node> nodeHashMap = new HashMap<>();;private final int capacity;//容量public LRUCache(int capacity) {this.capacity = capacity;head.next = tail;tail.prev = head;}public String get(String key) {Node node = nodeHashMap.get(key);if (null == node) {return null;}// 刷新当前key的位置,尾部是将被移除的很少使用的,头部是热点访问数据moveNodeToHead(node);return node.value;}// 在链表中移动node节点,可以先删除节点,然后重新添加private void moveNodeToHead(Node node) {removeNode(node);addNodeToHead(node);}private void removeNode(Node node) {if (node == tail) {tail = tail.prev;tail.next = null;} else if (node == head) {head = head.next;head.prev = null;} else {node.prev.next = node.next;node.next.prev = node.prev;}}private void addNodeToHead(Node node) {head.prev = node;node.next = head;node.prev = null;head = node;}public void put(String key, String value) {Node node = nodeHashMap.get(key);if (null == node) { //如果node不存在,则添加到链表if (nodeHashMap.size() >= capacity) { //如果hashmap已存数据长度大于容量,则移除尾部不常访问数据removeNode(tail); //移除尾部节点nodeHashMap.remove(tail.key); //将key从hashmap中移除}// 添加新的节点到头部node = new Node(key, value);nodeHashMap.put(key, node);addNodeToHead(node);} else { //如果存在,更新数据,并将热点数据移动到链表头部node.value = value;moveNodeToHead(node);}}class Node {private String key;private String value;Node prev;Node next;public Node() {}public Node(String key, String value) {this.key = key;this.value = value;}}
}

Redis中的LRU算法

Redis3.0之后优化了LRU算法,有以下四种情况:

  1. 回收池已满,新采集的key与回收池中的key相比,空闲时间最小,则不做任何处理
  2. 回收池未满,新采集的key空闲时间比回收池中部分元素大,则插入到对应位置,后面元素往后移动一个位置
  3. 回收池未满,新采集的key空闲时间最小,则插入到尾部
  4. 回收池已满,新采集的key空闲时间比回收池中部分元素大,则移除头部元素,将新采集key插入到对应位置,前面的元素往前移动一个位置

LFU算法

Least Frequently Used(最少使用),与LRU算法相比,引入了访问次数,但是存在时效性问题

上面的都是Hashmap,用来定位节点位置;下面是一个横向+纵向的双向链表,横向是根据key访问次数排序的双向链表,每个横向节点也是一个双向链表,用来保存相同访问次数的元素


http://www.ppmy.cn/news/335142.html

相关文章

windows for cuda cudnn

安装教程&#xff1a; https://blog.csdn.net/David_B/article/details/113576999?spm1001.2101.3001.6650.1&utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_default&depth_1-utm_sourcedistribute.pc_relevant.none…

cin和cout的使用

cin 1 cin的使用&#xff1a;2 cin>>a;3 cin和cout 都在std命名空间下4 cin使用“>>”右移运算符表示输入&#xff0c;将">>"右边的内容输入5 例如&#xff0c;6 void qq() {7 int b0;8 cin >> b0;9 …

cudnn cuda 网址

1cudnn cuDNN Archive | NVIDIA Developer 2. CUDA ToolKit的安装&#xff1a; CUDA的下载地址为&#xff1a;CUDA Toolkit Archive | NVIDIA Developer

TL431做比较器该如何理解?

TL431是由美国德州仪器公司&#xff08;TI&#xff09;和Motorola公司生产的2.50~36V可调精密并联稳压器&#xff0c;它是一种具有可调电流输出能力的基准电压源&#xff0c;TL431系列产品包括TL431C、TL431AC、TL431I、TL431AI、TL431M、TL431Y&#xff0c;共6种型号。它们的内…

pytorch使用DCN

pytorch使用DCN 前言正文 前言 关于DCN可形变卷积神经网络相信大家也都不陌生&#xff0c;使用额外的feature map区学习offset&#xff0c;以此达到可形变的效果。感觉和attention比较相似&#xff1f; 但是网络实现的代码版本各不相同&#xff0c;编译环境存在很多难以协调等…

C++语言cin和cout的详解

代码编译运行环境 QT creator 1.cin和cout简介 cin是C编程语言中的标准输入流对象&#xff0c;即istream类的对象。cin主要用于从标准输入读取数据&#xff0c;这里的标准输入&#xff0c;指的是终端的键盘。此外&#xff0c;cout是流的对象&#xff0c;即ostream类的对象&am…

DCGAN

转自&#xff1a;https://blog.csdn.net/liuxiao214/article/details/74502975 首先是各种参考博客、链接等&#xff0c;表示感谢。 1、参考博客1&#xff1a;地址 ——以下&#xff0c;开始正文。 2017/12/12 更新 解决训练不收敛的问题。 更新在最后面部分。 1、DCGAN的…

dilation conv 和 deconv

最近工作要用到dilation conv&#xff0c;在此总结一下空洞卷积&#xff0c;并和deconv进行对比。 dilation conv 首先空洞卷积的目的是为了在扩大感受野的同时&#xff0c;不降低图片分辨率和不引入额外参数及计算量&#xff08;一般在CNN中扩大感受野都需要使用s>1的con…