面试官问我:Redis 内存满了怎么办

转载自 想不到!面试官问我:Redis 内存满了怎么办

  • Redis占用内存大小

  • Redis的内存淘汰

  • LRU算法

  • LRU在Redis中的实现

  • LFU算法

  • 问题


Redis占用内存大小

我们知道Redis是基于内存的key-value数据库,因为系统的内存大小有限,所以我们在使用Redis的时候可以配置Redis能使用的最大的内存大小。

1、通过配置文件配置

通过在Redis安装目录下面的redis.conf配置文件中添加以下配置设置内存大小

//设置Redis最大占用内存大小为100M
maxmemory 100mb

redis的配置文件不一定使用的是安装目录下面的redis.conf文件,启动redis服务的时候是可以传一个参数指定redis的配置文件的

2、通过命令修改

Redis支持运行时通过命令动态修改内存大小

//设置Redis最大占用内存大小为100M
127.0.0.1:6379> config set maxmemory 100mb
//获取设置的Redis能使用的最大内存大小
127.0.0.1:6379> config get maxmemory

如果不设置最大内存大小或者设置最大内存大小为0,在64位操作系统下不限制内存大小,在32位操作系统下最多使用3GB内存

Redis的内存淘汰

既然可以设置Redis最大占用内存大小,那么配置的内存就有用完的时候。那在内存用完的时候,还继续往Redis里面添加数据不就没内存可用了吗?

实际上Redis定义了几种策略用来处理这种情况:

noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)

allkeys-lru:从所有key中使用LRU算法进行淘汰

volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰

allkeys-random:从所有key中随机淘汰数据

volatile-random:从设置了过期时间的key中随机淘汰

volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰

当使用volatile-lruvolatile-randomvolatile-ttl这三种策略时,如果没有key可以被淘汰,则和noeviction一样返回错误

如何获取及设置内存淘汰策略

获取当前内存淘汰策略:

127.0.0.1:6379> config get maxmemory-policy

通过配置文件设置淘汰策略(修改redis.conf文件):

maxmemory-policy allkeys-lru

通过命令修改淘汰策略:

127.0.0.1:6379> config set maxmemory-policy allkeys-lru

LRU算法

什么是LRU?

上面说到了Redis可使用最大内存使用完了,是可以使用LRU算法进行内存淘汰的,那么什么是LRU算法呢?

LRU(Least Recently Used),即最近最少使用,是一种缓存置换算法。在使用内存作为缓存的时候,缓存的大小一般是固定的。当缓存被占满,这个时候继续往缓存里面添加数据,就需要淘汰一部分老的数据,释放内存空间用来存储新的数据。这个时候就可以使用LRU算法了。其核心思想是:如果一个数据在最近一段时间没有被用到,那么将来被使用到的可能性也很小,所以就可以被淘汰掉。

使用java实现一个简单的LRU算法

public class LRUCache<k, v> {//容量private int capacity;//当前有多少节点的统计private int count;//缓存节点private Map<k, Node<k, v>> nodeMap;private Node<k, v> head;private Node<k, v> tail;public LRUCache(int capacity) {if (capacity < 1) {throw new IllegalArgumentException(String.valueOf(capacity));}this.capacity = capacity;this.nodeMap = new HashMap<>();//初始化头节点和尾节点,利用哨兵模式减少判断头结点和尾节点为空的代码Node headNode = new Node(null, null);Node tailNode = new Node(null, null);headNode.next = tailNode;tailNode.pre = headNode;this.head = headNode;this.tail = tailNode;}public void put(k key, v value) {Node<k, v> node = nodeMap.get(key);if (node == null) {if (count >= capacity) {//先移除一个节点removeNode();}node = new Node<>(key, value);//添加节点addNode(node);} else {//移动节点到头节点moveNodeToHead(node);}}public Node<k, v> get(k key) {Node<k, v> node = nodeMap.get(key);if (node != null) {moveNodeToHead(node);}return node;}private void removeNode() {Node node = tail.pre;//从链表里面移除removeFromList(node);nodeMap.remove(node.key);count--;}private void removeFromList(Node<k, v> node) {Node pre = node.pre;Node next = node.next;pre.next = next;next.pre = pre;node.next = null;node.pre = null;}private void addNode(Node<k, v> node) {//添加节点到头部addToHead(node);nodeMap.put(node.key, node);count++;}private void addToHead(Node<k, v> node) {Node next = head.next;next.pre = node;node.next = next;node.pre = head;head.next = node;}public void moveNodeToHead(Node<k, v> node) {//从链表里面移除removeFromList(node);//添加节点到头部addToHead(node);}class Node<k, v> {k key;v value;Node pre;Node next;public Node(k key, v value) {this.key = key;this.value = value;}}
}

上面这段代码实现了一个简单的LUR算法,代码很简单,也加了注释,仔细看一下很容易就看懂。

LRU在Redis中的实现

近似LRU算法

Redis使用的是近似LRU算法,它跟常规的LRU算法还不太一样。近似LRU算法通过随机采样法淘汰数据,每次随机出5(默认)个key,从里面淘汰掉最近最少使用的key。

可以通过maxmemory-samples参数修改采样数量:例:maxmemory-samples 10 maxmenory-samples配置的越大,淘汰的结果越接近于严格的LRU算法

Redis为了实现近似LRU算法,给每个key增加了一个额外增加了一个24bit的字段,用来存储该key最后一次被访问的时间。

Redis3.0对近似LRU的优化

Redis3.0对近似LRU算法进行了一些优化。新算法会维护一个候选池(大小为16),池中的数据根据访问时间进行排序,第一次随机选取的key都会放入池中,随后每次随机选取的key只有在访问时间小于池中最小的时间才会放入池中,直到候选池被放满。当放满后,如果有新的key需要放入,则将池中最后访问时间最大(最近被访问)的移除。

当需要淘汰的时候,则直接从池中选取最近访问时间最小(最久没被访问)的key淘汰掉就行。

LRU算法的对比

我们可以通过一个实验对比各LRU算法的准确率,先往Redis里面添加一定数量的数据n,使Redis可用内存用完,再往Redis里面添加n/2的新数据,这个时候就需要淘汰掉一部分的数据,如果按照严格的LRU算法,应该淘汰掉的是最先加入的n/2的数据。生成如下各LRU算法的对比图(图片来源):

你可以看到图中有三种不同颜色的点:

  • 浅灰色是被淘汰的数据

  • 灰色是没有被淘汰掉的老数据

  • 绿色是新加入的数据

我们能看到Redis3.0采样数是10生成的图最接近于严格的LRU。而同样使用5个采样数,Redis3.0也要优于Redis2.8。

LFU算法

LFU算法是Redis4.0里面新加的一种淘汰策略。它的全称是Least Frequently Used,它的核心思想是根据key的最近被访问的频率进行淘汰,很少被访问的优先被淘汰,被访问的多的则被留下来。

LFU算法能更好的表示一个key被访问的热度。假如你使用的是LRU算法,一个key很久没有被访问到,只刚刚是偶尔被访问了一次,那么它就被认为是热点数据,不会被淘汰,而有些key将来是很有可能被访问到的则被淘汰了。如果使用LFU算法则不会出现这种情况,因为使用一次并不会使一个key成为热点数据。

LFU一共有两种策略:

  • volatile-lfu:在设置了过期时间的key中使用LFU算法淘汰key

  • allkeys-lfu:在所有的key中使用LFU算法淘汰数据

设置使用这两种淘汰策略跟前面讲的一样,不过要注意的一点是这两周策略只能在Redis4.0及以上设置,如果在Redis4.0以下设置会报错

问题

最后留一个小问题,可能有的人注意到了,我在文中并没有解释为什么Redis使用近似LRU算法而不使用准确的LRU算法,可以在评论区给出你的答案,大家一起讨论学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322473.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源组件NanUI一周年 - 使用HTML/CSS/JS来构建.Net Winform应用程序界面

NanUI是什么NanUI基于ChromiumFX项目进行开发&#xff0c;它能让你在你的Winform应用程序中使用HTML5/CSS3/Javascript等网页技术来呈现用户界面&#xff08;类似Electron&#xff09;。同时NanUI提供了原生窗口和定制化的无标题栏无边框窗口&#xff0c;你能使用全部的网页技术…

ThreadPoolExecutor 八种拒绝策略,对的,不是4种

转载自 ThreadPoolExecutor 八种拒绝策略&#xff0c;对的&#xff0c;不是4种 前言 谈到 Java 的线程池最熟悉的莫过于 ExecutorService 接口了&#xff0c;jdk1.5 新增的 java.util.concurrent 包下的这个 api&#xff0c;大大的简化了多线程代码的开发。而不论你用 Fixed…

采用Opserver来监控你的ASP.NET项目系列(三、监控你的服务器状态)

前言之前有过2篇关于如何监控ASP.NET core项目的文章,有兴趣的也可以看看. ASP.NET Core之跨平台的实时性能监控ASP.NET Core之跨平台的实时性能监控(2.健康检查)今天我们主要来介绍一下,如何使用Opserver监控我们的服务器状态.Opserver的功能其实很强大,他可以用于连接任何支持…

Net Core中数据库事务隔离详解——以Dapper和Mysql为例

事务隔离级别.NET Core中的IDbConnection接口提供了BeginTransaction方法作为执行事务&#xff0c;BeginTransaction方法提供了两个重载&#xff0c;一个不需要参数BeginTransaction()默认事务隔离级别为RepeatableRead;另一个BeginTransaction(IsolationLevel il)可以根据业务…

2017年,我的身边发生了那些事?

不知不觉&#xff0c;运营独具.NET跨平台特色的微信公众号&#xff1a;dotNet跨平台至今已经整整三年光景了&#xff0c;这三年里微软开源.NET也满三周年了。三年时间说长不长&#xff0c;说短也不短了&#xff0c;然而我还是保持着每天三篇的更新 &#xff0c;或有感而原创&am…

ABP .Net Core Entity Framework迁移使用MySql数据库

一、迁移说明ABP模板项目Entity Framework Core默认使用的是Sql Server&#xff0c;也很容易将数据库迁移到MySQL&#xff0c;步骤如下。二、迁移MySQL步骤1、 下载项目请到 http://aspnetboilerplate.com/Templates 下载一个新的项目&#xff0c;选择ASP.NET Core 2.x标签&…

(四)十大经典排序算法(动画图解,代码完全)

排序算法是《数据结构与算法》中最基本的算法之一 1. 冒泡排序 1.1 算法步骤 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。 对每一对相邻元素作同样的工作&#xff0c;从开始第一对到结尾的最后一对。这步做完后&#xff0c;最后的元素会是最大的数。…

(五)SpringBoot 能挣钱的几个项目!!!

不得不佩服 Spring Boot 的生态如此强大&#xff0c;今天给大家推荐几款 Gitee 上优秀的后台开源版本的管理系统&#xff0c;小伙伴们再也不用从头到尾撸一个项目了&#xff0c;简直就是接私活&#xff0c;挣钱的利器啊。SmartAdmin我们开源一套漂亮的代码和一套整洁的代码规范…

手把手引进门之 ASP.NET Core Entity Framework Core(官方教程翻译版 版本3.2.5)

以下是手把手引进门教程&#xff0c;基于 ASP.NET Core&#xff0c; Entity Framework Core &#xff0c;ABP 框架 创建Web 应用&#xff0c; PS&#xff1a; 自带自动的测试模块哦。样例下载 &#xff08;上 github 的请自便&#xff09;介绍这是系列文章的第一部分&#xff1…

图像识别:微信跳一跳机器人

准备IDE&#xff1a;VisualStudioLanguage&#xff1a;VB.NET/C#GitHub&#xff1a;AutoJump.NET本文将向你介绍一种通过图像识别实现“跳一跳”机器人的方法。 第一节 图像识别文中提到的所有方法和步骤均仅涉及简单的向量计算。需要哪些计算&#xff1f;比较像素点的颜色求向…

(七)HTML和CSS 、JavaScript 和Java到底有什么区别,今天终于明白了!!!

有人曾经问过&#xff0c;“HTML CSS 和 JavaScript 以及 Java有什么区别” TCP VS UDP Java VS C 功能先上了再说 高级开发人员作为一个团队进行编程 调试CSS 高级开发人员重构代码 能一个手指完成的绝不用两只手 看实习生编码的时候&#xff0c;我的表情…… 当我尝试进入B…

基于Accord.Audio和百度语言识别

目标需求使用录音形式&#xff0c;模拟微信语音聊天。按住录音&#xff0c;松开发送语音&#xff0c;并完成语音识别。ps&#xff1a;百度的语言识别有60秒长度限制&#xff0c;需要自己做好控制。实现方案采用C# winform 程序实现桌面版&#xff0c;采用Accord 实现语音录制停…

(八)Spring与MyBatis整合

持久层 目录 Mybatis 开发步骤回顾Mybatis 开发中存在的问题Spring 与 Mybatis 整合思路Spring 与 Mybatis 整合的开发步骤Spring 与 Mybatis 整合的编码搭建开发环境 pom.xmlSpring 配置文件的配置编码Spring 与 Mybatis 整合细节持久层整合总述 1、Spring 框架为什么要与持…

Git 企业开发者教程

为什么要写这样一个面向企业开发者的Git教程&#xff1f;这个问题也困扰我自己很久。其实我使用git的时间也不短了&#xff0c;但是就和正在阅读本文的每一位一样&#xff0c;常用的基本就是那么几个(git clone, git push)等等。然而git其实有着非常强大的功能&#xff0c;如果…

基于百度理解与交互技术实现机器问答

一、前言我们都知道现在聊天对话机器是一个很有意思的东西&#xff0c;比如说苹果siri&#xff0c;比如说微软的小冰。聊天对话机器的应用场景也很广泛&#xff0c;比如说&#xff1a;银行的自助办卡机器人、展会讲解解说等等。我们对机器人说句话&#xff0c;机器人从听取&…

(十)Spring 与 MVC 框架整合

Spring 整合 MVC 目录 MVC 框架整合思想为什么要整合 MVC 框架搭建 Web 运行环境Spring 整合 MVC 框架的核心思路1. 准备工厂2. 代码整合Spring 整合 Struts2MVC 框架整合思想 为什么要整合 MVC 框架 MVC 框架提供了控制器&#xff08;Controller&#xff09;调用 Servlet …

利用VSTS跟Kubernetes整合进行CI/CD

为什么VSTS要搭配Kubernetes&#xff1f;通常我们在开发管理软件项目的时候都会碰到一个很头痛的问题&#xff0c;就是开发、测试、生产环境不一致&#xff0c;导致开发人员和测试人员甚至和运维吵架。因为常见的物理环境甚至云环境中&#xff0c;这些部署环境都是由运维人员提…

(十一)Spring 基础注解(对象创建相关注解、注入相关注解)

注解编程 目录 注解基础概念注解的作用Spring 注解的发展历程Spring 基础注解&#xff08;Spring 2.x&#xff09;对象创建相关注解ComponentRepository、Service、ContollerScopeLazy生命周期注解 PostConstruct、PreDestroy注入相关注解用户自定义类型 AutowiredJDK 类型注…

使用 ASP.NET Core, Entity Framework Core 和 ABP 创建N层Web应用 第二篇

介绍这是“使用 ASP.NET Core &#xff0c;Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用”系列文章的第二篇。以下可以看其他篇目&#xff1a;使用 ASP.NET Core &#xff0c;Entity Framework Core 和 ASP.NET Boilerplate 创建N层 Web 应用 第一篇 &…

揭秘微软6万工程师DevOps成功转型的技术「武器」

在微软&#xff0c;通过其自身数年的 DevOps 转型&#xff0c; 6 万名工程师实现了更好的软件平台创新和快速迭代。微软有庞大的技术产品矩阵&#xff0c;同时也具有每天发布的能力&#xff0c;其中&#xff0c;微软研发云是支撑整个开发过程与运维最重要的基础平台。微软研发云…