Redis-八股文

  1. 什么是RDB和AOF?-√
  2. RDB:保存redis某个时刻快照的文件,可以用于redis全量同步,或者持久化
    
    优点:
    1.仅一个dump.rdb,方便持久化
    2.方便容灾备份
    3.恢复性能比AOF好
    
    缺点:
    1.由于是全量快照,因此,只能一段时间持久化一次。那就有可能存在,这段时间数据丢失的风险
    2.由于是全量快照,因此,如果数据量较大的时候,可能会比较耗时。
    
    AOF:保存redis一段时间内的操作日志,可以用于redis增量同步,或者持久化
    
    优点:
    1.AOF保存比RDB保存会更频繁,因此,就算丢失,丢失的改动也会少很多,甚至如果选择每修改同步的策略的话,那么最多就丢失一条操作指令
    
    缺点:
    1.恢复起来比RDB方式要慢,即性能是比不上RDB的
    2.AOF文件比RDB文件要大
    
  3. Redis的过期键删除策略?
  4. 定时过期:每隔一段时间,将redis所有过期键删除[CPU-难过 内存-友好]
    
    惰性过期:当且仅当用到的时候判断是否过期,过期就删除[CPU-友好 内存-难过]
    
    定期过期:另外两种策略的折中,每隔一段时间就触发一次,每次都去遍历过期键删除,但是,这个过程有限时,超过一定时间就恢复redis正常使用
    
  5. 简述redis的事务实现?
  6. 首先得从下面几个关键字开始说,
    multi、exec、discard、watch
    
    multi:开始一个事务
    
    命令入队列:这个阶段输入要执行的命令
    
    exec与discard命令输入,代表事务的结束,redis就开始执行整个事务或者抛弃整个事务
    
    watch:给整个事务加乐观锁 如果监听的数据被别人改动了,那么整体事务回滚
    
  7. redis主从复制的核心原理?-√
  8. 核心就是 主节点成功以后,就直接返回,然后才同步到从节点,因此,存在不一致的风险[ZK则是先保证一致性 再返回给调用方]
    
    两种复制同步内容:
    全量同步:
    1.将主节点上的所有数据保存一份快照,bgsave持久化RDB文件
    2.将文件传递给从节点,全量同步到从节点[阻塞]
    
    增量同步:
    1.增量同步的前提,需要维护一份偏移量和一个缓冲队列
    2.在缓冲队列没有满到溢出的情况下,从节点将同步请求发给主节点[里面带上运行ID]
    2.1 第一次连接[运行ID不相同],主节点将运行ID传回给从节点,并进行全量RDB同步,从节点保存当前主节点的运行ID
    2.2 非初次连接[运行ID相同],那么就只需要将缓冲队列中改动同步到从节点即可
    
    


  9. Redis有哪些数据结构?分别有哪些经典应用场景?
  10. 字符串:session共享;分布式ID;计数器
    哈希表:查询结果,条件为key
    列表:可以模拟栈、队列,用于缓存消息之类的流数据
    集合:由于集合可以进行交并差,因此,可以用于共同关注等功能[每个客户端特定标识对象 集合里面是目标 一个目标多个对象即共同关注]
    
  11. Redis分布式锁底层是如何实现的?-√
  12. 核心 就是利用lua脚本的原子性
    
    1.setnx 保证当且仅当 没有其他线程设置这个key的时候 才往里写数据上锁
    2.最后一定要将自己上的锁给释放掉
    3.用try保证出异常的时候,最后一定会释放锁
    4.确保释放的锁是自己加的
    5.每把锁都必须设置过期时间,以确保不会出现某个线程一直持有锁
    6.要额外一个线程进行锁续命
    
    服务端 向redis主节点请求锁
    主节点锁请求成功,返回给服务端
    然后将状态同步到从节点
    
  13. redis集群策略?
  14. redis共三种模式
    
    主从模式:主节点挂了可以访问从节点
    哨兵模式:增加部分节点,设为哨兵,监视主节点状态,主节点挂了以后,从节点重新选举出主节点[单主多从]
    集群模式:多主多从,同样会自动选举出新-主节点
    
  15. 缓存穿透、缓存刺穿、缓存雪崩
  16. 缓存雪崩: 多个key在redis中不存在,且有很多请求同时访问这些数据,导致数据库压力较大,常见于服务端刚起,缓存内无数据
    处理:
    1.缓存预热,请求访问之前,预先查询一遍,将部分key的内容保存至缓存
    2.互斥锁,执行SQL的部分上锁,同样的请求,仅放第一个执行SQL,后续全部走redis
    3.热点数据,缓存过期时间稍微设置偏差一点,防止一批数据同时过期失效
    
    缓存穿透:请求访问的是,缓存和数据库都没有的数据[有可能不是合法数据],当key没有的时候,就会去查询数据库,但同时,又没有合法数据会存入redis,导致如果利用这种请求,做重放攻击的话,就会导致数据库浪费很多性能
    处理:
    1.可以枚举所有情况的场景下,利用布隆过滤器可以筛选掉部分请求,就不让请求走到业务逻辑
    2.无法枚举的情况下,请求还是正常走业务逻辑,只是,查询数据库没有数据的情况下,直接往redis里面存放null等提前预设的空值,等下一次请求判断redis的时候,获取到该值即可直接判断,无需再查数据库。
    
    缓存刺穿:某个key过期了,导致请求一直走到数据库,且有很多请求同时访问这个数据[热点数据]
    处理:
    1.互斥锁,key过期以后,同一个key的查询请求,有且仅有一个请求能进入查询SQL的流程,SQL查询完毕就保存redis,其余都直接查询redis
    
    缓存雪崩:
    1.缓存预热
    2.互斥锁
    3.过期岔开
    
    缓存刺穿:
    1.缓存预热
    2.互斥锁
    
    缓存穿透:
    1.能枚举:布隆过滤器,做请求拦截
    2.不能枚举:互斥锁,设置Null,将后续请求拦截到数据库处理之外
    
    
  17. redis与MySQL如何保持数据一致?
  18. 1.删除redis缓存
    2.更新MySQL
    3.删除redis缓存
    
  19. redis的持久化机制
  20. 两种持久化命令:
    save:阻塞性持久化,会阻塞redis主进程,直到持久化完成
    bgsave:非阻塞性持久化,通过新建子线程专门持久化,从而不影响redis主进程
    
    手动就是上面两种命令
    自动就是save M N ,相当于设置一个定时器,定时备份持久化的感觉[非阻塞持久化]
    
    两种持久化格式
    RDB:redis某个时刻的快照
    优点:
    1.仅一个RDB文件,方便持久化与备份
    2.方便恢复,性能较好
    
    缺点:
    1.有可能丢数据,因为记录的是某个时刻的状态,因此,记录时刻与同步时刻之间的这段时间改动是有可能丢失的
    2.数据多的时候,持久化的速度会比AOF慢
    
    AOF:记录命令的操作日志
    优点:
    1.持久化可以设置每修改同步,即每次改动都记录操作日志,因此,最理想的情况,仅丢失一条改动
    2.持久化的速度会更快
    缺点:
    1.恢复性能不如RDB,会更慢,启动速度也会更慢
    2.文件整体会比RDB更大
    
  21. redis单线程为什么这么快-※
  22. 常见的缓存淘汰算法
  23. FIFO:先进先出
    LRU:最近最少使用
    LFU:一段时间,最少使用
    
  24. Redis 哈希槽为什么最大值是16384?
  25. Redis保存某个数据之前,会对key进行一个CRC16的计算,然后对16384取余
    CRC16,得到最大值是2^16=65536,对16384取余,每个哈希槽最多有4个key会哈希冲突
    之所以采取16384,一般阈值是通过实验优化过后确定下来的经验值
    1.由于心跳机制,每个节点都需要发送心跳消息,
    假定每个槽占1bit,那么16384=2^14=2^10*2^3*2=2KB,同理,65536=8KB,心跳包的实时性要求较高,减小包的大小,可以减小网络通信开销
    2.Redis集群模式下,一般节点不会超过1000个,没必要将slot分散到更大的区间,极限情况下,均等划分下,每个节点也能保证16-17个插槽可用,保证了集群的稳定性与高性能
    
  26. Redis 是否存在线程安全问题?
  27. 可以从客户端与服务端两个方面分析
    服务端:
    现况:执行指令都是单线程执行的,因此,不存在线程安全问题
    未来:CPU不是Redis的性能瓶颈,因此,它也没有必要引入多线程处理,反之,如果引入多线程以后,就要考虑加锁处理线程安全的问题,加锁会增加时间开销降低Redis的性能
    
    客户端:
    确实有多线程场景,可能在部分场景里面会有线程安全问题,一般可以通过
    1.加锁处理
    2.利用lua脚本的原子性,将多个指令封装成lua脚本来规避[redisson的分布式锁的处理方案]
    
  28. 大key怎么处理?(3)
  29. 首先明确问题 然后再明确处理思路
    
    问题:
    key越大
    1.占用内存空间越大
    2.网络传输压力越大
    3.持久化时间越长
    
    处理思路:
    1.拆分:单个大key拆分成若干小key,以及数据也能做拆分,可以降低网络传输压力
    2.分布式:将大key分布到不同hash slot上存储,可以提升持久化性能
    3.压缩:将数据采用无损压缩方式压缩,可以降低内存空间压力
    
    最后还能通过业务分析根因,优化存储结构,优化数据结构等等
    
  30. 如何进行缓存预热
  31. 启动时自动
    1.利用bean的生命周期-实例化-依赖注入-postConstrunct注解-initializingbean接口-生成代理对象
    2.AOP拦截器,直接在容器启动的代码切入一个切面,专门做缓存预热
    3.静态代码块-类加载的时候会执行
    4.CommandLineRunner接口(ApplicationRunner 接口)+order注解
    
    后续自动
    1.定时器,将时间与过期时间岔开,定期更新缓存
    
    手动更新:上线后手动触发
    
  32. redis主节点选举
  33. 1.哨兵节点将"失联"节点进行选举过滤,超时没有响应认定为"失联"
    2.实际选举:
            2.1.每个节点都有一个优先级,优先级更高更容易成为主节点
            2.2.偏移量更大的从节点更容易成为主节点[因为与原主节点同步得更多]
            2.3.runid更小的从节点更容易成为主节点
    3.写流量切换到新的主节点
    

      参考:
      1.https://www.jb51.net/article/280467.htm
      2.https://baijiahao.baidu.com/s?id=1767052815720228275&wfr=spider&for=pc
      3.https://blog.csdn.net/Leon_Jinhai_Sun/article/details/121412886
      4.http://www.manongjc.com/detail/62-bbbehzfmysyitoq.html

posted @ 2023-07-07 20:33  356a  阅读(22)  评论(0编辑  收藏  举报