首页 > 数据库 >Redis内存回收与缓存问题

Redis内存回收与缓存问题

时间:2024-05-19 19:18:36浏览次数:25  
标签:缓存 删除 数据库 Redis 内存 key

内存回收:

1.过期key处理

通过expire命令给key设置ttl

Redis本身是KV型数据库,所有数据都存在RedisDB结构体中,其中有两张哈希表

  dict:用于存放KV(这里K是K,V是V)

  expires:保存Redis中所有的设置了过期时间的KEY以及到期时间TTL(这里K是K,V是TTL)

过期KEY有两种删除策略:

  1. 惰性删除,有命令需要操作key时,检测key是否还活着,过期则删除
  2. 周期删除,通过一个定时任务,周期性抽样带有TTL的key,过期则删除
    1. slow模式:默认频率10/s,每次执行时长不超过25ms,受server.hz参数影响
    2. fast模式:频率不固定,跟随内部IO事件循环执行。两次任务之间间隔不低于2ms,执行时长不超过1ms

2.内存淘汰策略

  当Redis内存使用达到阈值的时候,Redis会主动挑选一部分key进行删除

  什么时候检查是否达到阈值:在每次处理操作的时候都会进行

  推荐使用volatile-lfu,其中的lfu与lru都记录在RedisObject中的unsigned lru:LRU_BITS

 

缓存问题.

缓存一致性

  1. 数据库双写,具有侵入性。(常用)
  2. 缓存与数据库整合为一套服务,开发的时候直接调接口。
  3. CRUD直接基于缓存,然后异步实现数据持久化。性能好,但是流程复杂,而且没有强一致性

低一致性的最佳实践:设一下TTL

高一致性的最佳实践

Q:为什么增删改都只是删除Redis中的数据

A:为了方便,反正我们查询的时候也会重新把数据写入Redis

Q:为什么删除的时候要先操作数据库,再操作Redis?

A:如果先操作Redis会出现线程安全问题:我们首先删除了Redis中的data,接下来进行数据库的操作,这个操作往往被认为是比较慢的。如果这时候同时有别的线程执行了读操作,就会导致Redis中写入了旧的数据,产生了缓存不一致

Q:延迟双删是什么

A:上述操作仍有极低概率造成线程安全问题。我们为了解决这个问题引入了延迟双删:在删除Redis数据之后的一段时间,我们再进行一次删除,确保数据的一致性

 

 

缓存穿透

客户端请求的数据在数据库里根本不存在,导致请求穿透缓存直接打到数据库上

解决方案:

  1. 缓存空对象:给不存在的数据建立缓存null。会额外消耗内存

  2. 布隆过滤:基于过滤器判断数据是否存在,如果根本不存在,拒绝请求

什么是布隆过滤器:一种数据统计的算法,用于检索一个元素是否存在于集合中。并且布隆过滤器无需存储元素到集合,而是把元素映射在一个很长的二进制数位上。存在一定误差。

缓存雪崩

 同一时段Redis内大量key同时失效,或者Redis突然宕机。大量请求打到数据库,带来巨大压力

解决方案:

  • 给不同的key的ttl随机设值
  • 利用集群提高服务可用性
  • 给缓存业务添加降级限流策略
  • 给业务添加多级缓存:网页缓存/NGINX缓存/JVM缓存

缓存击穿

 

 也称热点key问题,一个被高并发访问且缓存重建业务较复杂的key突然失效了,无数请求访问会瞬间打在数据库上造成压力

解决方案:

  • 互斥锁:问题:性能比较差

     

  • 逻辑过期:

java如何实现互斥锁?

public synchronized void test() {
  // 通过关键字修饰方法或代码块
}
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 //通过Lock接口
private final Lock lock=new ReentrantLock();
    public void test() {
        lock.lock();
        try {

        }catch (){

        }finally {
            lock.unlock();
        }
    }

 

标签:缓存,删除,数据库,Redis,内存,key
From: https://www.cnblogs.com/kun1790051360/p/18200539

相关文章

  • Redis的缓存雪崩、击穿、穿透问题,小小缓存问题,拿捏
    前言来整理一下缓存雪崩、击穿和穿透的问题,这个问题在面试中常出现,不是瞎说,我已经遇到几次了一、缓存雪崩1.雪崩什么是雪崩,某度给出的解释雪崩当山坡积雪内部的内聚力抗拒不了它所受到的重力拉引时,便向下滑动,引起大量雪体崩塌,人们把这种自然现象称作雪崩。说白了就......
  • redis数据结构:RedisObject,SkipList,SortedSet
    1.RedisObject对象redis中任何KV都会被封装为RedisObject对象,也叫做Redis对象 2.SkipList跳表元素按照升序排列存储,是有序的双向链表节点可以有多个指针,并且跨度不同。指针个数根据节点数自动生成,1~32性能和红黑树;二分查找差不多。实现简单,但是空间复杂度高样例:1——2......
  • redis实现分片集群
     为什么要使用分片集群?主从和哨兵可以解决高可用、高并发读的问题。但是仍存在海量数据存储、高并发写问题分片集群特征:集群中有多个master,每个master保存不同数据。为master置备了后备隐藏能源:多个slave节点优化了sentinel,master互相ping检测彼此状态结构复杂,难弄 ......
  • ptrace attach 修改进程内存
    #include<stdio.h>#include<stdlib.h>#include<sys/ptrace.h>#include<stdint.h>#include<errno.h>#include<sys/wait.h>intmain(intargc,char*argv[]){ void*addr1; void*addr2; pid_tattack_pid=-1; if(......
  • [20240510]SQL语句存在问题与共享池内存分配.txt
    [20240510]SQL语句存在问题与共享池内存分配.txt--//五一前遇到的问题,生产系统应用程序升级,但是3个表忘记建立,而编写的程序可能存在问题,导致频繁调用这些根本不可能执行的sql--//语句.很奇怪的是应用前台根本不报错,真不知道开发如何写代码,难道没做例外处理以及记录吗?--//测......
  • 驱动内存加载[理论]
    07驱动内存加载驱动加载介绍内存驱动加载不需要签名当双击一个PE程序的时候发生了什么1.通过explorer.exe(资源管理器)定位到双击的文件2.资源管理器通过CreatProcess创建进程3.创建进程的时候开辟一块空间此时在R3(PEB)和R0(填充基址)需要的地方挂上R3的物理页4.通过文......
  • 驱动内存加载[实战]
    08驱动内存加载[项目]目标:实现一个加载器,让驱动不落地加载DOS头和NT头DOS头kd>dt_IMAGE_DOS_HEADER-r3ntdll!_IMAGE_DOS_HEADER+0x000e_magic:Uint2B+0x002e_cblp:Uint2B+0x004e_cp:Uint2B+0x006e_crlc......
  • [SWPUCTF 2016]Web7 利用ssrf攻击redis
    今天做了一道攻击redis的相关题目,以前没接触过。初始界面有输入框,随便输入看看。是urllib2相关库报错,去搜了搜发现是Python2的Urllib2头部注入(CVE-2016-5699)。那就看看这个cve。说是Python2.x3.x的urllib/urllib2从数据解析到发包的整个流程中,均未对URL提供安全性过滤或检查......
  • 在spring boot中使用redis
    第一步,引入依赖```<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>```第二步,配置redisspring:redis:host:loc......
  • Docker启动 Redis提示:Can't initialize Background Jobg
     今天使用docker启动redis失败,但是查看容器日志,除了提示Fatal:Can'tinitializeBackgroundJobg,没有其他错误信息。经过长时间查找资料及试错,现记录下可能的产生原因及解决方案,以便以后参考。产生原因:宿主机安装的docker版本太低,同镜像所需的版本不匹配解决方案: 方案1、......