关于Redis你可能不知道的事...

188 阅读3分钟

1.在项目中,那些场景都使用了Redis?

缓存

  • 缓存三兄弟(穿透、击穿、雪崩)
  • 双写一致
  • 持久化
  • 数据过期策略
  • 数据淘汰策略

分布式锁

  • setnx、redisson 消息队列、延迟队列
  • 使用的数据类型: string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合);新版本类型:bitmap、GEO

2.如果发生缓存穿透、击穿、雪崩,该如何解决?

  • 穿透
    • 请求一个redis和db都不存在的数据,从而给数据库带来压力;
    • 解决1:缓存空数据,查询返回数据为空,将空数据进行缓存。(比较消耗内存,数据不一致问题
    • 解决2:布隆过滤器
      • bitmap
      • 作用:布隆过滤器可以用于检索一个元素是否在一个集合中。
  • 击穿
    • 热点key在某个时间过期了,这个时间会有大量的并发请求,db宕机;
    • 解决1:互斥锁(强一致性、性能差)
    • 解决2:设置热点数据永不过期
    • 解决3:逻辑过期(高可用、性能好、不能保证数据一致性)
  • 雪崩
    • 大量的数据过期时间一致,会导致db同时存在大量的访问,数据库可能会宕机;
    • 解决1:给不同的key的TTL添加随机值
    • 解决2:利用Redis集群
    • 解决3:缓存业务进行降级限流策略(nginx、gateway)
    • 解决4:多级缓存

redis作为缓存,Mysql的数据如何与redis进行同步呢?(双写一致)

允许延时一致的业务,采用异步通知

  • 使用MQ中间中间件,更新数据之后,通知缓存删除1
  • 利用canal中间件,不需要修改业务代码,伪装为mysql的一个从节点,canal通过读取binlog数据更新缓存

强一致性的,采用Redisson提供的读写锁

  • 共享锁: 读锁readLock,加锁之后,其他线程可以共享读操作
  • 排他锁:独占锁writeLock也叫,加锁之后,阻塞其他线程读写操作

redis作为缓存数据的持久化是怎么做的?

  • RDB
  • AOF

1691630200229.png


redis的key过期之后,会立即删除吗?

redis的过期删除策略

  • 惰性删除:访问key时判断是否过期,过期则删除;
  • 定期删除:定期检查一定量的key是否过期(SLOW+FAST模式)

redis的过期策略:惰性删除+定期删除两种策略配合使用


假如缓存过多,内存有限,内存被占满了怎么办?

当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。

  • noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略
  • volatile-ttl: 对设置了TTL(过期时间)的key,比较key的剩余TTL值,TTL越小越先被淘汰
  • allkeys-random:对全体key ,随机进行淘汰 key1是在3s之前访问的, key2是在9s之前访问的,删除的就是key2
  • volatile-random:对设置了TTL的key ,随机进行淘汰
  • allkeys-lru:对全体key,基于LRU算法进行淘汰
  • volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰
  • allkeys-lfu:对全体key,基于LFU算法进行淘汰
  • volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰

LRU(Least Recently Used) 最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。 LFU(Least Frequently Used)最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。

平时开发过程中使用allkeys-lru淘汰策略比较多(结合使用场景)