说说Redis的持久化策略

  • RDB
    是主线程fork出一个子线程异步来进行数据的存储,因为是异步执行所以不会对主进程造成性能影响、并且所写的文件都是压缩后的二进制文件,占空间较小。并且因为是直接对数据的存储而非AOF那样对命令的记录,所以恢复数据也更快。具体的流程就是主进程和子进程共享一个页表来对物理内存进行读写操作,当读写完成后将磁盘中旧的RDB文件替换成新的RDB文件。缺点有两个:一个就是在子进程读内存时主进程的写操作不能直接操作内存,而是将要操作的数据拷贝出来,操作拷贝的数据,这样就会导致占用额外的内存,极端情况下是原来的两倍;第二个是虽然持久化操作是由子进程做的,但fork出子进程的这段时间也会消耗大量资源、压缩、写入RDB文件也需要耗费不少时间
  • AOF
    不是直接持久化数据,而是将命令记录下来。因此所存储的文件比AOF会更大(因为一个key只会有一个数据,但一个key可能会有多次操作)。当文件过大时就需要重写。重写是将记录所有操作变成只记录对单个key的最后一次写操作。AOF的恢复速度较慢(原因上面说了),但是数据完整性更好,因为AOF时间间隔一般很短。

综上所述:相比于数据完整性更看重恢复速度可以选择RDB,反之选择AOF。

如何利用Redis实现一个分布式锁

  • 首先使用setnx,为了避免造成死锁所以要加上过期时间(注意 这两个操作一定要是原子性的)。锁释放的时候不能直接删除,因为可能会造成误删,举个例子:A线程执行时遇到了阻塞,任务没有完成且锁时间到了,那么锁过期线程B进来加上自己的锁执行任务,但此时A线程不在阻塞并且执行自己的任务,然后直接释放锁的话就会将B线程的锁给删除。所以我们可以在加锁的时候将线程id做为key的一部分存进去,解锁时必须要验证该锁的key与自己的线程相符。但需要保证判断和删除操作是原子性的,这时就需要lua脚本来完成。

当然写代码的时候还是推荐用Redisson,可以看下面这篇文章了解
分布式锁的王者方案Redisson

说说缓存穿透、击穿、雪崩的区别

  • 缓存穿透指所请求的数据既不在缓存中也不在数据库中,大量这样的请求会对数据库造成极大的压力。解决方法有两个,第一个是缓存空值,加上过期时间,但不能根治。第二个方法就是布隆过滤器,虽然有一定的误差但效果还是不错的。其原理就是将数据用几个不同的哈希函数得出的结果变成一存储起来。当有数据经过布隆过滤器时,再用刚才的哈希函数对其进行计算,如果所在位置全是1则数据存在,反之直接返回。
  • 缓存击穿是指当某个热点key突然过期时,大量的请求涌入数据库导致数据库崩溃
    解决方案第一个是加互斥锁,当发现缓存失效后便尝试获取互斥锁,获取成功则从数据库获取数据并写回缓存中,其他线程则不断自旋如果获取锁后缓存中有值则返回数据,没有则获取数据库。优点是数据一致性强,没有额外的内存消耗。缺点是性能降低,且有死锁风险。
    第二个方案是逻辑过期,即不真正的设置过期时间,而是将过期时间作为value存入数据中,每次去的时候看一下时间是否过期,如果过期则尝试获取互斥锁,如果成功则另开一个线程从数据库获取数据并写回缓存,自己则会返回旧数据。其他线程尝试获取锁失败后也会直接返回旧数据。优点是性能高,缺点就是数据一致性不高,且过期时间的存储占额外内存。
  • 缓存雪崩是指大量热点key同时过期或者是某个redis节点宕机造成的缓存失效导致大量的请求涌入数据库中,造成数据库崩溃。第一个解决办法是加随机的时间,避免大量key同时过期。二是采用熔断机制,若访问的不是核心数据则直接返回空值或错误信息。第三种是构建高可用的redis服务,采用哨兵或集群模式,即使单个节点宕机整体依然高可用。

Redis主从同步机制

  • 全量复制: slave节点向master节点请求连接,并携带自己的replication id和offset。如果其repliID与master节点不一致则需要全量同步。master节点开始RDB持久化自己的数据,并在生成RDB文件后同步到slvae节点上。在master生成RDB文件过程中所执行的命令就被记录在缓冲区中。等待RDB同步完成后再将这期间缓冲区剩余的命令传给slave节点进行同步。
  • 增量复制:如果repliID一致则证明之前已经当前slave是自己的从节点,通过自己与其offset值的差值来从缓冲区中取命令进行数据同步。但缓冲区内存有上限,如果超过则会覆盖自己之前的命令,导致slvae节点不得不进行全量复制。
  • 增量复制避免变成全量的改进方法
  • 1.在配置文件中开启RDB文件不进行磁盘存储而是直接向网络中传输文件,可以加快传输速度。
  • 2.单个slave节点占用的内存不要太大。减少RDB过多的磁盘IO
  • 3.提高缓冲区的大小。
  • 4.采取链式的主从复制,即从节点也有从节点,可以避免大量数据同步请求堆积到主节点导致主节点性能下降。

Redis是单线程吗

  1. 如果仅聊redis核心业务部分(命令处理),答案是单线程
  2. 如果是redis整体的话就是多线程

使用单线程有三个原因

  • redis是内存数据库,其性能瓶颈主要是网络IO,不用多线程也已经很快。
  • 多线程时的上下文切换,加锁解锁都会降低性能
  • 多线程需要考虑线程安全问题,会增大编码难度和运行效率。

网络IO使用IO多路复用

  • redis使用IO多路复用程序监听来自客户端的多个socket(套接字),并监听每个套接字的对应事件,当对应事件出现时就会调用文件事件处理器来处理。
  • 这样的好处非常明显: I/O 多路复用技术的使用让 Redis 不需要额外创建多余的线程来监听客户端的大量连接,降低了资源的消耗(和 NIO 中的 Selector 组件很像)。

相关文章推荐
redis是单线程的正确理解

Redis和数据库如何保持双写一致性

  • 首先考虑到的有四种方式:先更新数据库后更新缓存、先更新缓存后更新数据库、先更新数据库后删除缓存、先删除缓存后更新数据库。
  • 先排除更新缓存的方式。有两个原因,第一个是有可能更新缓存后并没有立即用到,立马更新缓存不仅降低缓存命中率也会占用内存。第二个原因就是当业务较复杂、取出的数据不能立即缓存时,就需要多余的计算造成了性能的浪费。
  • 那么就剩下先删除缓存后更新数据库和先更新数据库后删除缓存了。这里讨论下并发问题。

先删除缓存,后更新数据库

如果有 2 个线程要并发「读写」数据,可能会发生以下场景

  1. 线程 A 要更新 X = 2(原值 X = 1)
  2. 线程 A 先删除缓存
  3. 线程 B 读缓存,发现不存在,从数据库中读取到旧值(X = 1)
  4. 线程 A 将新值写入数据库(X = 2)
  5. 线程 B 将旧值写入缓存(X = 1)
  6. 最终 X 的值在缓存中是 1(旧值),在数据库中是 2(新值),发生不一致。

先更新数据库,后删除缓存

  1. 缓存中 X 不存在(数据库 X = 1)
  2. 线程 A 读取数据库,得到旧值(X = 1)
  3. 线程 B 更新数据库(X = 2)
  4. 线程 B 删除缓存
  5. 线程 A 将旧值写入缓存(X = 1)
    最终 X 的值在缓存中是 1(旧值),在数据库中是 2(新值),也发生不一致。

这种情况「理论」来说是可能发生的,但实际真的有可能发生吗?
其实概率「很低」,这是因为它必须满足 3 个条件:
1 缓存刚好已失效。
2 读请求 + 写请求并发。
3 更新数据库 + 删除缓存的时间(步骤 3-4),要比读数据库 + 写缓存时间短(步骤 2 和 5)。

仔细想一下,条件 3 发生的概率其实是非常低的。

因为写数据库一般会先「加锁」,所以写数据库,通常是要比读数据库的时间更长的。

这么来看,「先更新数据库 + 再删除缓存」的方案,是可以保证数据一致性的。

但还有个问题 就是第二个操作执行失败所引起的数据不一致

这个时候需要做的就是重试了,可以通过消息队列来进行重试

  • 消息队列保证可靠性:写到队列中的消息,成功消费之前不会丢失(重启项目也不担心)
  • 消息队列保证消息成功投递:下游从队列拉取消息,成功消费后才会删除消息,否则还会继续投递消息给消费者(符合我们重试的场景)

关于更详细的关于数据库和redis数据一致性的讲解可以看下面这篇文章,我也是从这篇文章中学习的
缓存和数据库一致性详解

Redis哨兵

redis提供了哨兵机制来实现主从集群的自动故障恢复。其具体结构如下:

  1. 监控:烧饼会不断监控主机和从机的工作状态
  2. 自动故障恢复:如果主机故障,哨兵会自动将从机提升为主机。
  3. 通知:当集群故障发生时哨兵会将最新消息推送给redis客户端。

服务状态监控

哨兵基于心跳机制来检测集群工作状态,美国一秒向其每个实例发送ping命令来判断对方是否下线。

  • 主观下线:单个哨兵发现其未对自己的ping进行回应,则认为其主观下线。
  • 客观下线:若超过指定数量的哨兵都认为该实例下线,则其变成客观下线。

选举

哨兵会在故障发生时在从机中选举出新的主机,规则如下:

  • 首先排除和主机断开时间过长的从机
  • 其次判断从机的优先级,越小优先级越高
  • 接着判断从机的offset值大小,大说明其数据和主机
    同步率高
  • 最后就是判断节点的运行id大小,越小优先级越高(最后这一步是因为如果前面三个都满足的话选哪个都一样了所以随便定个规则)。

故障转移步骤

当选举成功后

  1. 哨兵给备选的从机发送"slave of no one",让其成为主机
  2. 哨兵会广播给其他从机,让其知道新的主机是谁并开始数据同步。
  3. 最后哨兵将故障节点标记为从机(修改其配置文件),这样就算醒来也是从机了

Redis常见面试题2022相关推荐

  1. Redis常见面试题总结

    Redis常见面试题 持久化方式有哪些?有什么区别? redis持久化方案分为RDB和AOF两种. RDB RDB持久化可以手动执行也可以根据配置定期执行,它的作用是将某个时间点上的数据库状态保存到R ...

  2. 七天玩转Redis 第七天打卡 Redis常见面试题及课程总结

    七天玩转Redis 第七天打卡 Redis常见面试题及课程总结 主要总结点: 截止到今天,七天玩转Redis课程就马上结束了,学以致用,那么学会了Redis,在找工作时会有哪些面试官爱问的问题呢? 一 ...

  3. Redis常见面试题(缓存击穿、穿透、雪崩)

    Redis常见面试题(缓存击穿.穿透.雪崩) 击穿 场景: 一般由于redis中的数据到期,同时并发用户特别多,此时大量请求压到数据库上. 解决思路: 根据redis是单进程单实例的特性,当高流量进入 ...

  4. 面经 | Redis常见面试题

    Redis 常见面试题 目录结构: 文章目录 Redis 常见面试题 数据结构 String 哈希 List Set Zset 有序集合 持久化机制 RDB快照 AOF 混合使用 Redis为什么要线 ...

  5. Redis常见面试题(2022)

    Redis基础 什么是 Redis? Redis 是一个开源(BSD 许可).基于内存.支持多种数据结构的存储系统,可以作为数据库.缓存和消息中间件.它支持的数据结构有字符串(strings).哈希( ...

  6. Redis常见面试题你都掌握了没

    前言 缓存知识点一键获取Redis面试题 缓存有哪些类型? 缓存是高并发场景下提高热点数据访问性能的一个有效手段,在开发项目时会经常使用到. 缓存的类型分为: 本地缓存.分布式缓存和多级缓存. 本地缓 ...

  7. Redis常见面试题及答案模板

    1.什么是redis? Redis 是一个基于内存的高性能key-value数据库,它常被称作是一款数据结构服务器(data structure server). 2.Reids的特点 Redis本质 ...

  8. Redis常见面试题详解

    文章目录 1. Redis 1.1 Redis可以用来做什么? 1.2 Redis和传统的关系型数据库有什么不同? 1.3 Redis有哪些数据类型? 1.4 Redis是单线程的,为什么还能这么快? ...

  9. redis常见面试题有哪些?redis集群面试题及答案整理

    下面要给大家带来的是一整套的redis集群面试题,包含了具体的面试题目和答案,想要来看这方面面试题的小伙伴可以来了解一下. 一.面试题及答案 1.Redis有哪些适合的场景? (1)Session共享 ...

最新文章

  1. 人人都有好工作:IT行业求职面试必读
  2. PHP获取当前页面的网址
  3. Android Monkey(转载)
  4. mysql数据库表空间最大值_mysql 数据库取最大值
  5. mysql create database to_MySQL中CREATE DATABASE和CREATE SCHEMA区别(转)
  6. P2617 Dynamic Rankings 动态主席树
  7. Noip 模拟练习9
  8. 创新工场李开复:漫延——中国移动互联网的2011年
  9. css获取屏幕分辨率
  10. 安卓前端开发!移动APP开发框架盘点,附带学习经验
  11. 卧槽!终于知道涛哥我为啥赚不到钱了
  12. 神策数据微信小程序 SDK 架构解析
  13. HTML失败怎么解决,CSS加载失败怎么处理?
  14. 饿了么ui elementui 浏览器日志报错的检查思路
  15. html5 标签位置设置,i标签教程
  16. python播放音乐同步歌词_linux 下 python 调用 mplayer 解析歌词同步播放显示
  17. C# 操作LDAP查找组或人员信息
  18. 日本太地町渔民大规模砍杀海豚手段极其残忍
  19. Chrome插件无法引用外部Vue等js
  20. 基于ssm水果销售管理系统

热门文章

  1. Nuwa框架的使用步骤以及demo演示
  2. iphone内存检查工具leak
  3. winform 浮动窗体图片毛边
  4. kali网络端口大全
  5. 缓存(cache)与缓冲(buffer)
  6. 据说,不懂编程的人未来将寸步难行!
  7. c3-31 case13简单算术计算器
  8. 仙易信息科技CEO母仙灵:将免费云虚拟主机进行到底
  9. 【自学计划系列03】使用Hugo等配置增添网站功能_使用GitHub中utterance程序
  10. 使用两个dateTimePicker 根据日期区间查询数据库中的数据