• 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 数据库增量日志解析,提供增量数据订阅和消费)
  • 相关阅读:
    积分球检测水质的原理是什么?
    详解设计模式:享元模式
    Tailscale 的 TLS 证书过期,网站挂了 90 分钟!
    ai批量剪辑矩阵无人直播一站式托管系统源头技术开发
    一、C语言[指针]
    apt-get 指令格式以及常用指令
    关于这个问题解决的一个纠正
    有哪些国产的SSL品牌?国产的SSL值得信任吗?
    为什么算法这么重要?四面字节拿offer后我终于明白了
    2.2.3 顺序表应用举例
  • 原文地址:https://blog.csdn.net/weixin_61430914/article/details/132815218