Redis的用法及面试题(删除策略、企业级解决方案)

目录

一、Redis删除策略

(1)过期数据

(2)数据删除策略 

1.定时删除 

2.惰性删除

(3)逐出算法

二、企业级解决方案 

(1)缓存预热

(2)缓存雪崩 

(3)缓存击穿 (解决热点key问题)

(4)缓存穿透

三、Redis面试题 

(1)Redis采用单线程,如何保证高并发?

(2) 这样做的好处是什么?

(3)Redis的持久化方案有哪些?

(4)Redis在项目中的哪些地方有用到?

 (5)Redis实现分布式锁

 (6)如何实现数据库与缓存数据一致


一、Redis删除策略

(1)过期数据

Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态

XX :具有时效性的数据

-1 :永久有效的数据

-2 :已经过期的数据或被删除的数据或未定义的数据

问:过期的数据真的删除了吗?

答:不是的

(2)数据删除策略 

数据删除策略的目标

在内存占用与CPU占用之间寻找一种平衡,顾此失彼都会造成整体redis性能的下降,甚至引发服务器宕 机或内存泄露

删除策略有:

  1. 定时删除
  2. 惰性删除
  3. 定期删除

1.定时删除 

创建一个定时器,到时间立即删除

属于拿时间换空间,对CPU性能要求比较高

2.惰性删除

数据到达过期时间不立即删除,当下次访问的时候才会删除

属于拿空间换时间,对空间的占用比较大

3.定期删除

数据达到过期时间,隔一会儿删除一部分、隔一会儿再删一部分

这样对CPU的性能和空间都会比较友好

定时删除节约内存,无占用不分时段占用CPU资源
惰性删除内存占用严重延时执行,CPU利用率高
定期删除内存定期随机清理每秒花费固定的CPU资源维护内存

(3)逐出算法

当新数据进入redis时,内存不足则就要用到逐出算法了

逐出算法有两种方式:

lru:挑选最近最少使用的数据淘汰

lfu:挑选最近使用次数最少的数据淘汰

二、企业级解决方案 

(1)缓存预热

就服务器重启后请求数据过大,会出现“宕机”问题,就可以使用缓存预热。就是在系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候先查询数据库,然后再将数据缓存的问题。

(2)缓存雪崩 

指在同一时间段大量的缓存key同时失效,或Redis服务宕机,导致大量请求到达数据库带来大量压力。

解决方案: 

  1. 给不同的key的TTL添加随机值
  2. 利用Redis集群提高服务的可用性
  3. 给缓存业务添加降级限流策略
  4. 给业务添加多级缓存

(3)缓存击穿 (解决热点key问题)

就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。

解决方案: 

  1. 互斥锁
    1. 因为锁能实现互斥性。假设线程过来,只能一个人一个人的来访问数据库,从而避免对于数据库访问压 力过大,但这也会影响查询的性能,因为此时会让查询的性能从并行变成了串行,我们可以采用tryLock方法 + double check来解决这样的问题。

  2. 逻辑过期
    1. 我们之所以会出现这个缓存击穿问题,主要原因是在于我们对key设置了过期时间,假设我 们不设置过期时间,其实就不会有缓存击穿的问题,但是不设置过期时间,这样数据不就一直占用我们 内存了吗,我们可以采用逻辑过期方案。我们把过期时间设置在 redis的value中,注意:这个过期时间并不会直接作用于redis,而是我们后续 通过逻辑去处理。假设线程1去查询缓存,然后从value中判断出来当前的数据已经过期了,此时线程1去获得互斥锁,那么其他线程会进行阻塞,获得了锁的线程他会开启一个 线程去进行 以前的重构数据 的逻辑,直到新开的线程完成这个逻辑后,才释放锁, 而线程1直接进行返回,假设现在线程3过来访 问,由于线程线程2持有着锁,所以线程3无法获得锁,线程3也直接返回数据,只有等到新开的线程2把 重建数据构建完后,其他线程才能走返回正确的数据。 这种方案巧妙在于,异步的构建缓存,缺点在于在构建完缓存之前,返回的都是脏数据。

(4)缓存穿透

客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。

如图所示请求先在Redis中查找,找不到就会穿透缓存,进入到数据库中去 ,这样就会导致资源的浪费;而且我们知道数据库能够承载的并发不如redis那么高,如果有大量的请求同时来访问这种不存在的数据,就有可能会出现错误。

解决方案: 

  1. 缓存空对象

缓存空对象就是哪怕这个数据在数据库中不存在,我们也把 这个数据存入到redis中去,这样下次用户来访问这个不存在的数据,那么在Redis中也能找到这个数据,就不会进入到数据库中去了,如图所示:

  • 优点:实现简单,维护方便
  • 缺点
  1. 额外的内存消耗
  2. 可能造成短期不一致

        2.布隆过滤 

如上图所示, 布隆过滤器其实采用的是哈希思想来解决这个问题,通过一个庞大的二进制数组,走哈希思 想去判断当前这个要查询的这个数据是否存在,如果布隆过滤器判断存在,则放行,这个请求会去访问redis,哪怕此时redis中的数据过期了,但是数据库中一定存在这个数据,在数据库中查询出来这个数 据后,再将其放入到redis中, 假设布隆过滤器判断这个数据不存在,则直接返回。

  • 优点:内存占用较少,没有多余key
  • 缺点:实现复杂,存在误判可能

三、Redis面试题 

(1)Redis采用单线程,如何保证高并发?

Redis快的主要原因是:

  1. 完全基于内存
  2. 数据结构简单,对数据操作也简单
  3. 使用多路 I/O 复用模型,充分利用CPU资源

(2) 这样做的好处是什么?

单线程优势有下面几点:

  • 代码更清晰,处理逻辑更简单
  • 不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为锁而导致的性能消耗
  • 不存在多进程或者多线程导致的CPU切换,充分利用CPU资源

(3)Redis的持久化方案有哪些?

(4)Redis在项目中的哪些地方有用到?

 (5)Redis实现分布式锁

为了避免“超卖“”问题与并发问题,我们引入了分布式锁

分布式锁是一种多节点共享的同步机制,通过在多个节点之间协调访问资源,确保在同一时间只有一个节点能够获取锁并执行关键操作。在电商网站中,可以将每个商品的库存作为共享资源,使用分布式锁来控制并发访问

分布式锁的目的是保证在分布式部署的应用集群中,多个服务在请求同一个方法或者同一个业务操作的情况下,对应业务逻辑只能被一台机器上的一个线程执行,避免出现并发问题 。

分布式锁要满足的条件:

  • 多进程互斥:同一时刻,只有一个进程可以获取锁
  • 保证锁可以释放:任务结束或出现异常,锁一定要释放,避免死锁
  • 阻塞锁(可选):获取锁失败时可否重试
  • 重入锁(可选):获取锁的代码递归调用时,依然可以获取锁

 (6)如何实现数据库与缓存数据一致

实现方案有下面几种:

  • 本地缓存同步:当前微服务的数据库数据与缓存数据同步,可以直接在数据库修改时加入对Redis的修改逻辑,保证一致。
  • 跨服务缓存同步:服务A调用了服务B,并对查询结果缓存。服务B数据库修改,可以通过MQ通知服务A,服务A修改Redis缓存数据
  • 通用方案:使用Canal框架,伪装成MySQL的salve节点,监听MySQL的binLog变化,然后修改Redis缓存数据(主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费)
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值