如何做淘宝店网站/百度seo系统
文章目录
- Redis缓存淘汰算法
- 1. Redis缓存淘汰策略分类
- 2. 会进行淘汰的7种策略
- 2.1 基于过期时间的淘汰策略
- 2.2 基于所有数据范围的淘汰策略
- 3. LRU与LFU算法详解
- 4. 配置与调整
- 5. 实际应用场景
- LRU算法以及实现样例
- LFU算法实现
- 1. 数据结构选择
- 2. 访问频率更新
- 3. 缓存淘汰
- 4. 缓存插入
- 5. 优化和变种
- 6. 注意事项
- 7. 算法的python实现
Redis缓存淘汰算法
Redis缓存淘汰算法是Redis内存管理机制中的重要组成部分,用于在Redis达到内存使用上限时,通过不同的策略选择部分数据进行删除,以腾出内存空间。Redis提供了多种缓存淘汰策略,这些策略可以根据业务需求和数据特点进行灵活配置。以下是对Redis缓存淘汰算法的详细解析:
1. Redis缓存淘汰策略分类
Redis的缓存淘汰策略可以分为两大类:
- 不进行数据淘汰的策略:仅有一种,即
noeviction
。当缓存数据满了,有新的写请求进来时,Redis不再提供服务,而是直接返回错误。 - 会进行淘汰的策略:共有7种,包括基于数据是否设置过期时间的两类策略。
2. 会进行淘汰的7种策略
2.1 基于过期时间的淘汰策略
- volatile-random:在设置了过期时间的键值对中,进行随机删除。
- volatile-ttl:根据过期时间的先后进行删除,越早过期的越先被删除。
- volatile-lru:使用LRU(Least Recently Used,最近最少使用)算法筛选设置了过期时间的键值对。
- volatile-lfu:使用LFU(Least Frequently Used,最近最少使用)算法选择设置了过期时间的键值对(Redis 4.0后新增)。
2.2 基于所有数据范围的淘汰策略
- allkeys-random:从所有键值对中随机选择并删除数据。
- allkeys-lru:使用LRU算法在所有数据中进行筛选。
- allkeys-lfu:使用LFU算法在所有数据中进行筛选(Redis 4.0后新增)。
3. LRU与LFU算法详解
- LRU(Least Recently Used):最近最少使用算法,它的基本思想是淘汰最近最少访问的数据。Redis实现的LRU算法是近似LRU,通过随机选择一定数量的键,并从中选择最不常使用的键进行淘汰。这种方式避免了遍历所有键的开销,但可能会牺牲一定的精确度。
- LFU(Least Frequently Used):最近最少使用频率算法,它基于数据的访问频率进行淘汰。Redis使用近似计数器为每个键记录访问次数,当内存达到上限时,会优先淘汰访问次数较少的键。LFU算法通过log-log计数器实现,能够以较低的内存开销记录键的访问次数。
4. 配置与调整
- 设置内存使用上限:通过
maxmemory
参数来设定Redis的内存使用上限。 - 配置淘汰策略:通过
maxmemory-policy
参数来配置淘汰策略。 - 调整采样数量:对于LRU和LFU算法,可以通过
maxmemory-samples
参数来控制每次随机选择的键的数量,以提高算法的精确度,但也会增加CPU开销。 - 监控与评估:通过定期监控Redis的内存使用情况和命中率,可以评估当前的淘汰策略是否合适,并根据需要进行调整。
5. 实际应用场景
- 缓存数据的重要性较高:适合使用LRU或LFU策略,以保留访问频繁的数据。
- 数据具有明确的过期时间:适合使用volatile-ttl、volatile-random、volatile-lru或volatile-lfu策略。
- 数据访问频率不均:适合使用allkeys-lfu或volatile-lfu策略,以提升缓存的命中率。
- 对数据一致性要求非常高:适合使用noeviction策略,以确保不会随意删除数据。
综上所述,Redis的缓存淘汰算法为Redis的内存管理提供了灵活且强大的支持,通过合理的配置和调整,可以显著提高缓存的效率和性能。
LRU算法以及实现样例
LRU(Least Recently Used,最近最少使用)缓存淘汰算法是一种常用的页面置换算法,用于管理缓存中的数据,确保最近最少使用的数据被优先淘汰。在双向链表中实现LRU缓存是一种高效的方式,因为双向链表可以让我们在O(1)时间复杂度内完成节点的插入和删除操作。
下面是一个使用Python实现的基于双向链表的LRU缓存的简单示例:
class ListNode:def __init__(self, key=0, value=0):self.key = keyself.value = valueself.prev = Noneself.next = Noneclass LRUCache:def __init__(self, capacity: int):self.capacity = capacity# 初始化头尾节点self.head = ListNode()self.tail = ListNode()self.head.next = self.tailself.tail.prev = self.headself.cache = {}def get(self, key: int) -> int:if key not in self.cache:return -1node = self.cache[key]# 将节点移动到链表头部self._move_to_head(node)return node.valuedef put(self, key: int, value: int) -> None:if key in self.cache:# 如果key已存在,更新值并移动到头部node = self.cache[key]node.value = valueself._move_to_head(node)else:# 如果key不存在,创建新节点newNode = ListNode(key, value)# 添加到哈希表中self.cache[key] = newNode# 添加到链表头部self._add_node(newNode)# 如果超出容量,删除链表尾部节点if len(self.cache) > self.capacity:tail = self.pop_tail()del self.cache[tail.key]def _move_to_head(self, node):# 移除节点self._remove_node(node)# 添加到头部self._add_node(node)def _remove_node(self, node):prev = node.prevnext_node = node.nextprev.next = next_nodenext_node.prev = prevdef _add_node(self, node):node.prev = self.headnode.next = self.head.nextself.head.next.prev = nodeself.head.next = nodedef pop_tail(self):res = self.tail.prevself._remove_node(res)return res# 使用示例
lru_cache = LRUCache(2)
lru_cache.put(1, 1)
lru_cache.put(2, 2)
print(lru_cache.get(1)) # 返回 1
lru_cache.put(3, 3) # 淘汰 key 2
print(lru_cache.get(2)) # 返回 -1 (未找到)
lru_cache.put(4, 4) # 淘汰 key 1
print(lru_cache.get(1)) # 返回 -1 (未找到)
print(lru_cache.get(3)) # 返回 3
print(lru_cache.get(4)) # 返回 4
这个实现中,LRUCache
类维护了一个双向链表和一个哈希表。哈希表用于快速查找节点,而双向链表则用于维护节点的使用顺序。每次访问或添加节点时,都会将其移动到链表的头部,表示最近使用过。当缓存达到容量上限时,会删除链表尾部的节点,即最近最少使用的节点。
LFU算法实现
LFU(Least Frequently Used)算法是一种基于访问频率的缓存淘汰算法,其核心思想是优先淘汰那些访问频率最低的数据项。以下是LFU算法实现的基本步骤和关键点:
1. 数据结构选择
LFU算法的实现通常需要结合多种数据结构来高效地管理缓存项及其访问频率。常见的组合包括哈希表(HashMap)和双向链表(Doubly Linked List)或优先队列(如最小堆Min-Heap):
- 哈希表:用于存储缓存项及其对应的访问频率信息。键为缓存项的键,值为指向双向链表节点或堆中元素的指针,以及访问频率计数器。
- 双向链表或优先队列:用于按访问频率排序缓存项。在双向链表中,相同访问频率的节点可以通过额外的链表组织在一起;在优先队列中,则可以直接根据频率进行排序。
2. 访问频率更新
每次缓存项被访问时,需要更新其访问频率:
- 在哈希表中查找缓存项,获取其当前的访问频率和对应的双向链表节点或堆元素。
- 将访问频率加1,并更新哈希表中的记录。
- 如果使用双向链表,可能需要将节点从当前频率的链表中移除,并插入到更高频率的链表中(如果频率增加)。
- 如果使用优先队列,则可能需要重新调整队列中的位置。
3. 缓存淘汰
当缓存达到容量上限且需要插入新数据时,执行缓存淘汰:
- 如果使用双向链表,遍历最低频率的链表,找到最久未被访问或访问频率最低的节点进行淘汰。
- 如果使用优先队列,则直接从队列中取出最小频率的节点进行淘汰。
- 从哈希表中删除被淘汰的缓存项,并释放相应的内存。
4. 缓存插入
新数据插入时,首先检查缓存是否已满:
- 如果未满,直接在哈希表中添加新项,并初始化其访问频率为1。如果使用双向链表,将其添加到最低频率的链表中;如果使用优先队列,则将其插入到适当的位置。
- 如果已满,则执行缓存淘汰操作,然后插入新数据。
5. 优化和变种
- LFU-Aging:在LFU的基础上增加“老化”机制,即定期降低所有缓存项的访问频率,以便更快地适应访问模式的变化。
- Window-LFU:只记录过去一段时间内的访问历史,而不是所有数据的历史访问记录,以减少内存消耗和提高效率。
- LFU*:只淘汰访问次数为1的缓存项,以减少缓存污染问题。
6. 注意事项
- LFU算法在访问模式稳定时表现良好,但在访问模式频繁变化时可能会出现缓存污染问题。
- 相比LRU算法,LFU算法需要更多的内存来记录访问频率信息,并且在访问频率更新和排序时可能会有更高的性能开销。
7. 算法的python实现
在Python中实现LFU(Least Frequently Used)缓存算法,我们可以使用collections
模块中的OrderedDict
来模拟双向链表的功能(虽然它实际上是一个有序字典),以及一个哈希表来记录每个键的访问频率。不过,为了更准确地实现LFU算法,特别是当需要频繁地根据访问频率进行排序时,我们可能需要一个更复杂的结构,比如使用heapq
(最小堆)来优化查找最小频率项的过程。
然而,为了简化说明,这里我将提供一个基于OrderedDict
和额外哈希表的LFU缓存实现,该实现将模拟LFU的行为,但可能不是最高效的(特别是在处理大量数据和频繁更新时)。
from collections import OrderedDict, defaultdictclass LFUCache:def __init__(self, capacity: int):self.capacity = capacityself.cache = OrderedDict() # 存储键和对应的值以及频率self.frequency = defaultdict(OrderedDict) # 存储每个频率对应的键的集合def get(self, key: int) -> int:if key not in self.cache:return -1# 更新访问频率freq = self.cache[key][1]self.frequency[freq].pop(key)if not self.frequency[freq]:del self.frequency[freq]freq += 1self.cache[key] = (self.cache[key][0], freq)if freq not in self.frequency:self.frequency[freq] = OrderedDict()self.frequency[freq][key] = None# 将键移到OrderedDict的末尾,模拟最近访问self.cache.move_to_end(key)return self.cache[key][0]def put(self, key: int, value: int) -> None:if self.capacity <= 0:returnif key in self.cache:# 更新现有键的值和频率self.cache[key] = (value, self.cache[key][1] + 1)freq = self.cache[key][1]self.frequency[self.cache[key][1] - 1].pop(key)if not self.frequency[self.cache[key][1] - 1]:del self.frequency[self.cache[key][1] - 1]if freq not in self.frequency:self.frequency[freq] = OrderedDict()self.frequency[freq][key] = Noneself.cache.move_to_end(key)else:# 插入新键if len(self.cache) >= self.capacity:# 淘汰最少使用的项min_freq = min(self.frequency.keys())oldest_key = next(iter(self.frequency[min_freq]))del self.cache[oldest_key]del self.frequency[min_freq][oldest_key]if not self.frequency[min_freq]:del self.frequency[min_freq]# 插入新项self.cache[key] = (value, 1)if 1 not in self.frequency:self.frequency[1] = OrderedDict()self.frequency[1][key] = None# 示例用法
lfu = LFUCache(2)
lfu.put(1, 1)
lfu.put(2, 2)
print(lfu.get(1)) # 返回 1
lfu.put(3, 3) # 淘汰键 2
print(lfu.get(2)) # 返回 -1 (未找到)
lfu.put(4, 4) # 淘汰键 1
print(lfu.get(1)) # 返回 -1 (未找到)
print(lfu.get(3)) # 返回 3
print(lfu.get(4)) # 返回 4
注意:这个实现虽然模拟了LFU的行为,但在处理大量数据和频繁更新时可能不是最高效的。特别是,它使用OrderedDict
来模拟双向链表的行为,这在每次更新频率时都需要进行字典的插入和删除操作,这些操作的时间复杂度都是O(1)平均情况下,但在最坏情况下(即哈希冲突严重时)可能会退化。
为了获得更好的性能,特别是在需要频繁更新频率和根据频率进行排序时,可以考虑使用更复杂的数据结构,如平衡树或自定义的双向链表与哈希表的组合。然而,这些实现将更加复杂,并且可能需要更多的内存和代码来实现。
相关文章:

Redis缓存淘汰算法详解
文章目录 Redis缓存淘汰算法1. Redis缓存淘汰策略分类2. 会进行淘汰的7种策略2.1 基于过期时间的淘汰策略2.2 基于所有数据范围的淘汰策略 3. LRU与LFU算法详解4. 配置与调整5. 实际应用场景 LRU算法以及实现样例LFU算法实现1. 数据结构选择2. 访问频率更新3. 缓存淘汰4. 缓存插…...

Sklearn 与 TensorFlow 机器学习实用指南
Sklearn 与 TensorFlow 机器学习实用指南 Scikit-learn(Sklearn) 1. 简介 2. 特点 3. 基本用法 TensorFlow 1. 简介 2. 特点 3. 基本用法 选择指南 总结 🎈边走、边悟🎈迟早会好 关于使用 Scikit-learn(Sk…...

RabbitMQ 界面管理说明
1.RabbitMQ界面访问端口和后端代码连接端口不一样 界面端口是15672 http://localhost:15672/ 后端端口是 5672 默认账户密码登录 guest 2.总览图 3.RabbitMq数据存储位置 4.队列 4.客户端消费者连接状态 5.队列运行状态 6.整体运行状态...

设备管理与点巡检系统
在现代企业管理中,设备的高效运作至关重要。为此,我们推出了设备管理与点巡检系统,通过自动化管理提升设备使用效率,保障生产安全。 系统特点 设备全生命周期管理 系统涵盖设备的各个阶段,从设备管理、点检、巡检、保…...

计算机网络的整体认识---网络协议,网络传输过程
计算机网络背景 网络发展 独立模式: 计算机之间相互独立; 网络互联: 多台计算机连接在一起, 完成数据共享; 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起; 广域网WAN: 将远隔千里的计算机都连在一起;所谓 "局域网" 和 "广域网" 只是一个相…...

Battery management system (BMS)
电池管理系统(BMS)是一种专门用于监督电池组的技术,电池组由电池单元组成,在电气上按照行x列矩阵配置进行排列,以便在预期的负载场景下,在一段时间内提供目标范围的电压和电流。 文章目录 电池管理系统是如…...

和GPT讨论ZNS的问题(无修改)
主题:ZNS相关的疑问讨论,GPT逻辑回答,要是开高阶版本估计回答的更明智些。 ZNS的写和传统写的区别 ChatGPT 说: ChatGPT ZNS(Zoned Namespace)与传统写入方式的主要区别体现在以下几个方面: …...

6.8方框滤波
基本概念 方框滤波(Box Filter)是一种基本的图像处理技术,用于对图像进行平滑处理或模糊效果。它通过在图像上应用一个固定大小的方框核(通常是矩形),计算该区域内像素值的平均值来替换中心像素的值。这种…...

携手SelectDB,观测云实现性能与成本的双重飞跃
在刚刚落下帷幕的2024云栖大会上,观测云又一次迎来了全面革新。携手SelectDB,实现了技术的飞跃,这不仅彰显了观测云在监控观测领域的技术实力,也预示着我们可以为全球用户提供更加高效、稳定的数据监测与分析服务。这一技术升级&a…...

Redis 五大基本数据类型及其应用场景进阶(缓存预热、雪崩 、穿透 、击穿)
Redis 数据类型及其应用场景 Redis 是什么? Redis是一个使用C语言编写的高性能的基于内存的非关系型数据库,基于Key/Value结构存储数据,通常用来 缓解高并发场景下对某一资源的频繁请求 ,减轻数据库的压力。它支持多种数据类型,如字符串、…...

如何在ChatGPT的帮助下,使用“逻辑回归”技巧完成论文写作?
学境思源,一键生成论文初稿: AcademicIdeas - 学境思源AI论文写作 逻辑回归作为一种统计分析工具广泛应用,以解决研究中的分类问题。其主要作用在于探讨和量化自变量对因变量的影响,从而揭示潜在的因果关系。 在论文写作中&…...

MySQL 临时表
MySQL 临时表 引言 在数据库管理中,临时表是一种非常有用的工具,尤其是在进行复杂的数据处理和查询时。MySQL 作为一种流行的关系型数据库管理系统,提供了对临时表的支持。本文将详细介绍 MySQL 临时表的概念、用途、创建方法以及管理技巧。 什么是 MySQL 临时表? MySQ…...

个人文章汇总(算法原理算法题)
算法:算法概述 算法:浅谈常见的限流算法 算法:常见hash算法的原理 算法:二分查找法 算法:浅谈约瑟夫算法 算法:费波纳茨数列1 1 2 3 5 8 13 21 算法:快速排序 算法:插入排序 算法&am…...

基于Hive和Hadoop的图书分析系统
本项目是一个基于大数据技术的图书分析系统,旨在为用户提供全面的图书信息和深入的图书销售及阅读行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理,利用 MapReduce 进行数据分析和处理,通过 Sqoop 实现数据的导入导出,以…...

阿里rtc云端录制TypeScript版NODE运行
阿里云音视频服务云端录制typescript版本; 编译后可以使用 node index.js运行 package.json 版本 // npm install --save alicloud/rtc201801112.3.0 "alicloud/rtc20180111": "^2.3.0",引入 import Client, { StartCloudRecordRequest, StopCloudRecord…...

Web后端开发原理!!!什么是自动配置???什么是起动依赖???
引言: 当然,在我们学习的过程中,得知其然,还得知其所以然。So理解了其原理,更能让我们对其开发的理解,遇到问题,也更能快速找到解决办法!!! 1. SprngBoot-配…...

2-105 基于matlab的GA-WNN预测算法
基于matlab的GA-WNN预测算法。遗传算法优化小波神经网络的步骤:1设种群规模为M。随机生成初始种群N , 采用实数编码对个体Ni编码。2、用1中的种群N训练, WNN参数由初始化获得。3、计算种群N中个体适应度值。满足终止条件则跳至6, 不满足执行4。4、适应度大的个体, 选…...

GPT-o1模型实测:论文选题没思路,ChatGPT-o1带你飞!
我是娜姐 迪娜学姐 ,一个SCI医学期刊编辑,探索用AI工具提效论文写作和发表。 ChatGPT的最新版本GPT-o1模型,不少博主已经测评并展示了其在处理数学、物理以及代码生成等复杂任务时的独特优势。 和之前的版本相比,它在回答问题的时…...

OpenCV视频I/O(2)视频采集类VideoCapture之检索视频流的各种属性函数get()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 返回指定的 VideoCapture 属性。 VideoCapture 的 get() 函数用于检索视频流的各种属性。这个函数允许你查询视频源的状态和配置,例如…...

基于SpringBoot的学生宿舍管理系统【附源码】
基于SpringBoot的高校社团管理系统(源码L文说明文档) 4 系统设计 一个成功设计的系统在内容上必定是丰富的,在系统外观或系统功能上必定是对用户友好的。所以为了提升系统的价值,吸引更多的访问者访问系统…...

【开源免费】基于SpringBoot+Vue.JS新闻推荐系统(JAVA毕业设计)
本文项目编号 T 056 ,文末自助获取源码 \color{red}{T056,文末自助获取源码} T056,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…...

【每天学个新注解】Day 8 Lombok注解简解(七)—@Getter(lazy=true)
Getter(lazytrue) 生成懒加载的 getter 方法。 1、如何使用 Getter(lazytrue)注解加在一个被private final修饰的属性上,并且为其准备一个初始化方法。 2、代码示例 例: public class LazyGetterExample {Getter(lazy true)private final int exp…...

打造备份一体机,群晖科技平台化战略再进阶
数字经济时代,海量数据不断涌现,并成为核心生产要素,驱动着企业生产方式和商业模式发生深刻变革。 与其他生产要素不同,数据要素具有非稀缺性、非竞争性等特征,且只有在具体业务场景中才能充分释放其价值。尤其是近年…...

Sharding-JDBC笔记03-分库分表代码示例
文章目录 一、水平分库1. 将原有order_db库拆分为order_db_1、order_db_22. 分片规则修改分片策略standardcomplexinlinehintnone 3. 插入测试4. 查询测试5. 使用分库分片键查询测试总结 二、公共表1. 创建数据库2. 在Sharding-JDBC规则中修改3. 数据操作4. 字典操作测试5. 字典…...

气膜健身馆:提升运动体验与健康的理想选择—轻空间
近年来,气膜健身馆作为一种新兴的运动场所,正逐渐受到越来越多健身爱好者的青睐。这种独特的建筑形式不仅提供了良好的运动环境,更在健康和运动表现上展现出诸多优势。 优越的空气质量 气膜结构的核心技术通过内外气压差形成稳定的气膜&#…...

选择更轻松:山海鲸可视化与PowerBI的深度对比
在数据分析与可视化的时代,选择合适的报表工具显得尤为重要。山海鲸可视化和PowerBI是市场上颇受欢迎的两款免费报表软件,各有特色。接下来,我们将从功能、优缺点等方面进行对比,帮助你找到最适合的工具。 山海鲸可视化 山海鲸可…...

Python Daphne库:ASGI服务的高效Web服务器
更多Python学习内容:ipengtao.com 随着 Web 开发技术的不断发展,异步编程逐渐成为构建高性能 Web 应用的主流方式。传统的 WSGI 接口已经不能满足现代异步 Web 应用的需求。ASGI(Asynchronous Server Gateway Interface)作为 WSGI…...

如何保护自己电脑以及服务器的ip地址
保护你的电脑和服务器的IP地址,可以采取以下措施: 1. 使用代理服务器 HTTP/HTTPS代理:通过代理服务器访问网络,隐藏真实IP地址。SOCKS代理:提供更高级的网络流量转发,可以更好地处理各种网络协议。 2. 配…...

我的创作纪念日---256days
机缘 1.总结自己的学习过程面遇到的困难的解决方案; 2.总结自己日常学习过程中的知识,以及自己的理解和看法; 3.帮助需要的小伙伴在自己的文章里面找到想要的答案; 4.共同推进CSDN社区建设; 5.让自己每天都去写博…...

前端大模型入门:Transformer.js 和 Xenova-引领浏览器端的机器学习变革
除了调用别人的api接口使用transformer技术,你是否想过将大模型在浏览器中运行呢?尤其是WebGPU的出现,性能比WebGL高不少,很多小任务真的不再需要在一个中心运行了。 不少同学买课学python了,但我还是在坚持用js尝试&a…...