首页 > 数据库 >Redis(四) -- 缓存

Redis(四) -- 缓存

时间:2023-06-05 19:11:45浏览次数:49  
标签:缓存 删除 -- Redis 更新 过期 数据

缓存

缓存更新方式

这是决定在使用缓存时就该考虑的问题。

  • 设置缓存数据的TTL,当缓存数据失效后,如果有系统要请求,则会查询数据库并插入缓存(被动更新) 不友好
  • 在各类会往mysql写入数据的系统中,植入更新缓存的逻辑(判断哪些表的数据是热点数据,那么就可以在这些表数据的更新操作逻辑中植入缓存刷新逻辑)
    (严重弊端:将缓存更新逻辑与系统的业务逻辑高度耦合)后期维护很麻烦
  • 异步更新:开发一个异步任务,定期从mysql数据库中读取“热门表”的数据更新缓存(时效性低)
  • 利用canal监听mysql的binlog写入kafka,开发一个更新程序,消费kafka中的binlog信息,并根据“热度方案”进行缓存数据的更新;
    (时效性强!对业务系统的mysql数据库几乎不带来任何压力!跟业务系统完全没有耦合,修改扩展维护都很方便)

数据不一致

第二个问题是数据不一致的问题,可以说只要使用缓存,就要考虑如何面对这个问题。缓存不一致产生的原因一般是主动更新失败,例如更新 DB 后,更新 Redis 因为网络原因请求超时;或者是异步更新失败导致。
解决的办法是,如果服务对耗时不是特别敏感可以增加重试;如果服务对耗时敏感可以通过异步补偿任务来处理失败的更新,或者短期的数据不一致不会影响业务,那么只要下次更新时可以成功,能保证最终一致性就可以。

缓存穿透

有人、系统,频繁查询数据库中不存在的数据;那么,缓存相当于不存在!

产生这个问题的原因可·能是外部的恶意攻击,例如,对用户信息进行了缓存,但恶意攻击者使用不存在的用户id频繁请求接口,导致查询缓存不命中,然后穿透 DB 查询依然不命中。这时会有大量请求穿透缓存访问到 DB。

解决的办法如下:
对不存在的数据,在缓存中保存一个空对象进行标记,防止相同 ID 再次访问 DB。不过有时这个方法并不能很好解决问题,可能导致缓存中存储大量无用数据
使用 BloomFilter 过滤器,BloomFilter 的特点是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在。非常适合解决这类的问题

缓存击穿

就是某个热点数据失效时,大量针对这个数据的同时请求会穿透到数据源
解决这个问题有如下办法

  • 可以使用互斥锁更新,保证同一个进程中的多个线程针对同一个数据不会并发请求到 DB,减小 DB 压力。但是查询的效率相对会低很多
  • 使用随机退避方式,失效时随机 sleep一个很短的时间,再次查询,如果失败再查询mysql并更新redis。

缓存淘汰机制

TTL删除策略

可以为数据设置TTL(存活时长),时长一到,数据就会被删除
缓存数据TTL的删除策略可分为三种

  • 定时删除(对内存友好,对CPU不友好)
    到时间点上就把所有过期的键删除了。
  • 惰性删除(对CPU极度友好,对内存极度不友好)
    每次取键的时候,判断一下该键是否过期了,如果过期了就删除。
  • 定期删除(折中)
    每隔一段时间去检查及删除过期键,限制删除的执行时长和频率。
    Redis的过期数据的删除策略:采用的是惰性删除+定期删除两种策略。所以说,在Redis里边如果过期键到了过期的时间了,未必被立马删除的!

LRU(least recently used)淘汰策略

Redis可以设置内存最大使用量,当内存使用量超出阈值时,会执行数据淘汰策略。
Redis的内存数据淘汰机制有以下几种:

  • volatile-lru: 从已设置过期时间的数据集中挑选最近最少使用的数据进行淘汰
  • volatile-ttl: 从已设置过期的时间数据集中挑选将要过期的数据淘汰
  • volatile-random: 从已设置过期时间的数据集中任意选择数据淘汰
  • allkeys-lru: 从所有数据集中挑选最近最少使用的数据淘汰
  • allkeys-random: 从所有数据集中任意选择数据进行淘汰
  • noeviction: 禁止驱逐数据
  • volatile-lfu: 从已设置过期时间的数据集中使用LFU策略淘汰

一般场景:
使用 Redis 缓存数据时,为了提高缓存命中率,尽量将所有热数据存在缓存中,可以将内存最大使用量设置为热点数据占用的内存量,然后启用allkeys-lru淘汰策略,将最近最少使用的数据淘汰

LRU概念
LRU(The Least Recently Used,最近最少未使用)是一种常见内存管理算法,最早应用于Linux操作系统,在Redis中也有广泛使用的。
LRU算法有这样一种假设:如果某个数据长期不被使用,在未来被用到的几率也不大;因此缓存容量达到上限时,应在写入新数据之前删除最久未使用的数据值,从而为新数据腾出空间。

LFU概念
LFU(The Least Frequently Used,最不经常使用)也是一种常见的缓存算法。
和LRU类似,LFU同样有这样的假设:如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰;当存在两个或者更多个键具有相同的使用频次时,应该淘汰最久未使用的数据。(类比LRU)

标签:缓存,删除,--,Redis,更新,过期,数据
From: https://www.cnblogs.com/paopaoT/p/17458729.html

相关文章

  • Locust用户手册
    Locust是一个基于Python语言的开源压力测试工具,通过模拟虚拟用户进行并发访问,测试目标站点的性能和稳定性。本手册详细介绍如何使用Locust进行压力测试,包括基础、高阶和拓展内容。一、基础使用1.安装Locust首先需要安装Python3,在命令行窗口输入以下命令:```pipinstalllocust......
  • 考研数学⭐每天几道题:偏微分和全微分(2023年5月21日)
    1️⃣用偏微分的定义计算全微分的特值问题(一)2️⃣用偏微分的定义计算全微分的特值问题(二)3️⃣由全微分反向积分求解原函数4️⃣对于有特值的题目一定要及时代入特值进行化简5️⃣对隐函数计算全微分6️⃣复合函数和隐函数联合求偏导:能代入的值先代入关注荒原之梦⭐考研数学的博客......
  • 实验5 文件应用编程
    实验任务6实验源码:1withopen('data6.csv','r',encoding='gbk')asf:2raw_data=f.read().split('\n')3title1=['原始数据']45data1=[float(i)foriinraw_data[1:]]6print(f'{title1[0]......
  • 让Flutter 应用程序性能提高 10 倍的 10 个技巧
    Flutter应用程序以其精美的设计和流畅的功能而闻名,但性能问题会很快破坏用户体验。借助这10个优化性能的专家技巧,将您的应用提升到一个新的水平。使用WidgetsBindingObserver跟踪应用程序的生命周期使用“WidgetsBindingObserver”来跟踪您的应用程序的生命周期。此观察器允许......
  • 龙蜥社区 5 月度运营大事件回顾
    各位龙蜥社区的朋友们,你们好!5月运营月报来啦!从龙蜥看点、龙蜥生态、龙蜥活动、龙蜥SIG月度动态、精彩内容推荐等几方面总结、回顾了5月发生的重要事件。以下是社区运营报告,也欢迎更多的开发者加入,与我们一起打造面向云时代的操作系统。......
  • 百度倾力出品|《神经网络机器翻译技术及产业应用》正式上线
    随着经济社会的国际交流合作日益密切,人们迫切需要高质量、高效率的跨语言信息获取和传播工具。《神经网络机器翻译技术及产业应用》以产业需求为牵引,分析了新时期机器翻译的产业需求特点和挑战,介绍了神经网络翻译的基本理论、前沿技术以及面向产业应用的实用系统开发方法。《神经网......
  • 凌志软件加入飞桨技术伙伴计划,共同探索“AI+金融”应用场景落地
    近日,苏州工业园区凌志软件股份有限公司正式加入飞桨技术伙伴计划,双方将探索人工智能、大数据、云计算、区块链等新兴技术在金融领域的应用和创新,推动“AI+金融”在垂直领域的应用场景落地。苏州工业园区凌志软件股份有限公司凌志软件是一家金融软件公司,主要业务为对日软件开发业务......
  • python时间和日期处理
    1.时间处理time相关操作:获取当前时间时间转字符串字符串转时间计算时间差importtimenow=time.time()#时间戳从1970年1月1日0点0分0秒到此刻的秒数print(f"{now=}")now_st=time.localtime(now)#标准时间年月日,时分秒print(f"{now_st}")now_str=time.strftim......
  • React学习时,自己拟定的一则小案例(table表格组件,含编辑)
    某次在Uniapp群看到有人问uniapp如何操作dom元素。他想对这张表标红的区域,做dom元素获取,因为产品想让红色色块点击时,成为可编辑,渲染1~4月份之间的行程安排。于是,有小伙伴说让他用position定位这里,点击时使红色色块层级抬高,弄个input上去。但提问的小伙伴并没有决定这么做,随后......
  • Python实验课5
    实验任务六实验源码:1withopen('data6.csv','r',encoding='gbk')asf:2data=f.readlines()3data1=[str(eval(data[i]))foriinrange(1,len(data))]4data2=[str(int(eval(data[i])+0.5))foriinrange(1,len(data))]5info=......