缓存中间件Redis常考知识点

作者:逍遥Sean
简介:一个主修Java的Web网站\游戏服务器后端开发者
主页:https://blog.csdn.net/Ureliable
觉得博主文章不错的话,可以三连支持一下~ 如有需要我的支持,请私信或评论留言!

前言:
如果需要在linux环境中搭建一个redis服务参考:
Linux环境下搭建使用缓存中间件Redis
如果需要掌握redis的常考知识点参考:
缓存中间件Redis必知必会

1 什么是RDB和AOF

RDB:Redis DataBase,在指定的时间间隔内将内存中的数据集快照写⼊磁盘,实际操作过程是fork⼀个⼦进程,先将数据集写⼊临时⽂件,写⼊成功后,再替换之前的⽂件,⽤⼆进制压缩存储。

优点:

  1. 整个Redis数据库将只包含⼀个⽂件 dump.rdb,⽅便持久化。
  2. 容灾性好,⽅便备份
  3. 性能最⼤化,fork ⼦进程来完成写操作,让主进程继续处理命令,所以是 IO 最⼤化。使⽤单独⼦ 进程来进⾏持久化,主进程不会进⾏任何 IO 操作,保证了 redis 的⾼性能
  4. 相对于数据集⼤时,⽐ AOF 的启动效率更⾼

缺点:

  1. 数据安全性低。RDB 是间隔⼀段时间进⾏持久化,如果持久化之间 redis 发⽣故障,会发⽣数据丢 失。所以这种⽅式更适合数据要求不严谨的时候)
  2. 由于RDB是通过fork⼦进程来协助完成数据持久化⼯作的,因此,如果当数据集较⼤时,可能会导致整个服务器停⽌服务⼏百毫秒,甚⾄是1秒钟。

AOF:Append Only File,以⽇志的形式记录服务器所处理的每⼀个写、删除操作,查询操作不会记录,以⽂本的⽅式记录,可以打开⽂件看到详细的操作记录

优点:

  1. 数据安全,Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也 是异步完成的,其效率也是⾮常⾼的,所差的是⼀旦系统出现宕机现象,那么这⼀秒钟之内修改的数据将会丢失。⽽每修改同步,我们可以将其视为同步持久化,即每次发⽣的数据变化都会被⽴即 记录到磁盘中。。
  2. 通过 append 模式写⽂件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redischeck-aof ⼯具解决数据⼀致性问题。
  3. AOF 机制的 rewrite 模式。定期对AOF⽂件进⾏重写,以达到压缩的⽬的

缺点:

  1. AOF ⽂件⽐ RDB ⽂件⼤,且恢复速度慢
  2. 数据集⼤的时候,⽐ rdb 启动效率低。
  3. 运⾏效率没有RDB⾼

AOF⽂件⽐RDB更新频率⾼,优先使⽤AOF还原数据,AOF⽐RDB更安全也更⼤,RDB性能⽐AOF好,如果两个都配了优先加载AOF

2 Redis的过期键的删除策略

Redis是key-value数据库,我们可以设置Redis中缓存的key的过期时间。Redis的过期策略就是指当Redis中缓存的key过期了,Redis如何处理。

惰性过期:只有当访问⼀个key时,才会判断该key是否已过期,过期则清除。该策略可以最⼤化地节省CPU资源,却对内存⾮常不友好。极端情况可能出现⼤量的过期key没有再次被访问,从⽽不 会被清除,占⽤⼤量内存。
定期过期每隔⼀定的时间,会扫描⼀定数量的数据库的expires字典中⼀定数量的key,并清除其中已过期的key。该策略是⼀个折中⽅案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有 键。)

Redis中同时使⽤了惰性过期和定期过期两种过期策略。

3 简述Redis事务实现

1、事务开始 MULTI命令的执⾏,标识着⼀个事务的开始。MULTI命令会将客户端状态的 flags 属性中打开 REDIS_MULTI标识来完成的。

2、命令⼊队
当⼀个客户端切换到事务状态之后,服务器会根据这个客户端发送来的命令来执⾏不同的操作。如果客户端发送的命令为MULTI、EXEC、WATCH、DISCARD中的⼀个,⽴即执⾏这个命令,否则将命令放⼊⼀个事务队列⾥⾯,然后向客户端返回QUEUED 回复

  • 如果客户端发送的命令为 EXEC、DISCARD、WATCH、MULTI 四个命令的其中⼀个,那么服务 器⽴即执⾏这个命令。
  • 如果客户端发送的是四个命令以外的其他命令,那么服务器并不⽴即执⾏这个命令。⾸先检查此命令的格式是否正确,如果不正确,服务器会在客户端状态(redisClient)的flags 属性关闭 REDIS_MULTI 标识,并且返回错误信息给客户端。如果正确,将这个命令放⼊⼀个事务队列⾥⾯,然后向客户端返回QUEUED 回复

事务队列是按照FIFO的⽅式保存⼊队的命令

3、事务执⾏ 客户端发送 EXEC 命令,服务器执⾏ EXEC 命令逻辑。

  • 如果客户端状态的 flags 属性不包含 REDIS_MULTI 标识,或者包含 REDIS_DIRTY_CAS 或者 REDIS_DIRTY_EXEC 标识,那么就直接取消事务的执⾏。
  • 否则客户端处于事务状态(flags 有 REDIS_MULTI 标识),服务器会遍历客户端的事务队列,然后执⾏事务队列中的所有命令,最后将返回结果全部返回给客户端;

redis不⽀持事务回滚机制,但是它会检查每⼀个事务中的命令是否错误。
Redis 事务不⽀持检查那些程序员⾃⼰逻辑错误。例如对 String 类型的数据库键执⾏对 HashMap 类型 的操作!

  • WATCH命令是⼀个乐观锁,可以为 Redis 事务提供 check-and-set (CAS)⾏为。可以监控⼀个或多个键,⼀旦其中有⼀个键被修改(或删除),之后的事务就不会执⾏,监控⼀直持续到EXEC 命令。
  • MULTI命令⽤于开启⼀个事务,它总是返回OK。MULTI执⾏之后,客户端可以继续向服务器发送任意多条命令,这些命令不会⽴即被执⾏,⽽是被放到⼀个队列中,当 EXEC命令被调⽤时,所有队列 中的命令才会被执⾏。
  • EXEC:执⾏所有事务块内的命令。返回事务块内所有命令的返回值,按命令执⾏的先后顺序排列。 当操作被打断时,返回空值 nil 。通过调⽤DISCARD,客户端可以清空事务队列,并放弃执⾏事务, 并且客户端会从事务状态中退出。
  • UNWATCH命令可以取消watch对所有key的监控。

4 Redis 主从复制的核⼼原理

通过执⾏slaveof命令或设置slaveof选项,让⼀个服务器去复制另⼀个服务器的数据。主数据库可以进⾏读写操作,当写操作导致数据变化时会⾃动将数据同步给从数据库。⽽从数据库⼀般是只读的,并接受主数据库同步过来的数据。⼀个主数据库可以拥有多个从数据库,⽽⼀个从数据库只能拥有⼀个主数据库。
全量复制

  1. 主节点通过bgsave命令fork⼦进程进⾏RDB持久化,该过程是⾮常消耗CPU、内存(⻚表复制)、硬盘IO的
  2. 主节点通过⽹络将RDB⽂件发送给从节点,对主从节点的带宽都会带来很⼤的消耗
  3. 从节点清空⽼数据载⼊新RDB⽂件的过程是阻塞的,⽆法响应客户端的命令;如果从节点执⾏bgrewriteaof,也会带来额外的消耗

部分复制:

  1. 复制偏移量:执⾏复制的双⽅,主从节点,分别会维护⼀个复制偏移量offset
  2. 复制积压缓冲区:主节点内部维护了⼀个固定⻓度的、先进先出(FIFO)队列 作为复制积压缓冲区,
    当主从节点offset的差距过⼤超过缓冲区⻓度时,将⽆法执⾏部分复制,只能执⾏全量复制。
  3. 服务器运⾏ID(runid):每个Redis节点,都有其运⾏ID,运⾏ID由节点在启动时⾃动⽣成,主节点会将⾃⼰的运⾏ID发送给从节点,从节点会将主节点的运⾏ID存起来。 从节点Redis断开重连的时候,就是根据运⾏ID来判断同步的进度:
    • 如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使⽤部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况);
    • 如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进⾏全量复制。

5 Redis有哪些数据结构?分别有哪些典型的应⽤场景?

  1. 字符串:可以⽤来做最简单的数据,可以缓存某个简单的字符串,也可以缓存某个json格式的字符串,Redis分布式锁的实现就利⽤了这种数据结构,还包括可以实现计数器、Session共享、分布式ID
  2. 哈希表:可以⽤来存储⼀些key-value对,更适合⽤来存储对象
  3. 列表:Redis的列表通过命令的组合,既可以当做栈,也可以当做队列来使⽤,可以⽤来缓存类似微信公众号、微博等消息流数据
  4. 集合:和列表类似,也可以存储多个元素,但是不能重复,集合可以进⾏交集、并集、差集操作,从⽽可以实现类似,我和某⼈共同关注的⼈、朋友圈点赞等功能
  5. 有序集合:集合是⽆序的,有序集合可以设置顺序,可以⽤来实现排⾏榜功能

6 Redis分布式锁底层是如何实现的?

  1. ⾸先利⽤setnx来保证:如果key不存在才能获取到锁,如果key存在,则获取不到锁
  2. 然后还要利⽤lua脚本来保证多个redis操作的原⼦性
  3. 同时还要考虑到锁过期,所以需要额外的⼀个看⻔狗定时任务来监听锁是否需要续约
  4. 同时还要考虑到redis节点挂掉后的情况,所以需要采⽤红锁的⽅式来同时向N/2+1个节点申请锁,都申请到了才证明获取锁成功,这样就算其中某个redis节点挂掉了,锁也不能被其他客户端获取到

7 Redis主从复制的核⼼原理

Redis的主从复制是提⾼Redis的可靠性的有效措施,主从复制的流程如下:

  1. 集群启动时,主从库间会先建⽴连接,为全量复制做准备
  2. 主库将所有数据同步给从库。从库收到数据后,在本地完成数据加载,这个过程依赖于内存快照RDB
  3. 在主库将数据同步给从库的过程中,主库不会阻塞,仍然可以正常接收请求。否则,redis的服务就被中断了。但是,这些请求中的写操作并没有记录到刚刚⽣成的RDB⽂件中。为了保证主从库的数据⼀致性,主库会在内存中⽤专⻔的replication buffer,记录RDB⽂件⽣成收到的所有写操作。
  4. 最后,也就是第三个阶段,主库会把第⼆阶段执⾏过程中新收到的写命令,再发送给从库。具体的操作是,当主库完成RDB⽂件发送后,就会把此时replocation buffer中修改操作发送给从库,从库再执⾏这些操作。这样⼀来,主从库就实现同步了
  5. 后续主库和从库都可以处理客户端读操作,写操作只能交给主库处理,主库接收到写操作后,还会将写操作发送给从库,实现增量同步

8 Redis集群策略

Redis提供了三种集群策略:

  1. 主从模式:这种模式⽐较简单,主库可以读写,并且会和从库进⾏数据同步,这种模式下,客户端直接连主库或某个从库,但是但主库或从库宕机后,客户端需要⼿动修改IP,另外,这种模式也⽐较难进⾏扩容,整个集群所能存储的数据受到某台机器的内存容量,所以不可能⽀持特⼤数据量
  2. 哨兵模式:这种模式在主从的基础上新增了哨兵节点,但主库节点宕机后,哨兵会发现主库节点宕机,然后在从库中选择⼀个库作为进的主库,另外哨兵也可以做集群,从⽽可以保证但某⼀个哨兵节点宕机后,还有其他哨兵节点可以继续⼯作,这种模式可以⽐较好的保证Redis集群的⾼可⽤,但是仍然不能很好的解决Redis的容量上限问题。
  3. Cluster模式:Cluster模式是⽤得⽐较多的模式,它⽀持多主多从,这种模式会按照key进⾏槽位的分配,可以使得不同的key分散到不同的主节点上,利⽤这种模式可以使得整个集群⽀持更⼤的数据Redis分布式锁底层是如何实现的?Redis主从复制的核⼼原理Redis集群策略容量,同时每个主节点可以拥有⾃⼰的多个从节点,如果该主节点宕机,会从它的从节点中选举⼀个新的主节点。
    对于这三种模式,如果Redis要存的数据量⼤,可以选择哨兵模式,如果Redis要存的数据量⼤,并且需要持续的扩容,那么选择Cluster模式。

9 缓存穿透、缓存击穿、缓存雪崩分别是什么

缓存中存放的⼤多都是热点数据,⽬的就是防⽌请求可以直接从缓存中获取到数据,⽽不⽤访问Mysql。

  1. 缓存雪崩:如果缓存中某⼀时刻⼤批热点数据同时过期,那么就可能导致⼤量请求直接访问Mysql了,解决办法就是在过期时间上增加⼀点随机值,另外如果搭建⼀个⾼可⽤的Redis集群也是防⽌缓存雪崩的有效⼿段
  2. 缓存击穿:和缓存雪崩类似,缓存雪崩是⼤批热点数据失效,⽽缓存击穿是指某⼀个热点key突然失效,也导致了⼤量请求直接访问Mysql数据库,这就是缓存击穿,解决⽅案就是考虑这个热点key不设过期时间
  3. 缓存穿透:假如某⼀时刻访问redis的⼤量key都在redis中不存在(⽐如⿊客故意伪造⼀些乱七⼋糟的key),那么也会给数据造成压⼒,这就是缓存穿透,解决⽅案是使⽤布隆过滤器,它的作⽤就是如果它认为⼀个key不存在,那么这个key就肯定不存在,所以可以在缓存之前加⼀层布隆过滤器来拦截不存在的key

10 Redis和Mysql如何保证数据⼀致

  1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致
  2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中,这种⽅案能解决⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到Redis中
  3. 延时双删,步骤是:先删除Redis缓存数据,再更新Mysql,延迟⼏百毫秒再删除Redis缓存数据,这样就算在更新Mysql时,有其他线程读了Mysql,把⽼数据读到了Redis中,那么也会被删除掉,从⽽把数据保持⼀致

11 Redis的持久化机制

RDB:Redis DataBase 将某⼀个时刻的内存快照(Snapshot),以⼆进制的⽅式写⼊磁盘。
⼿动触发

  • save命令,使 Redis 处于阻塞状态,直到 RDB 持久化完成,才会响应其他客户端发来的命令,所以在⽣产环境⼀定要慎⽤
  • bgsave命令,fork出⼀个⼦进程执⾏持久化,主进程只在fork过程中有短暂的阻塞,⼦进程创建之后,主进程就可以响应客户端请求了

⾃动触发

  • save m n :在 m 秒内,如果有 n 个键发⽣改变,则⾃动触发持久化,通过bgsave执⾏,如果设置多个、只要满⾜其⼀就会触发,配置⽂件有默认配置(可以注释掉)
  • flushall:⽤于清空redis所有的数据库,flushdb清空当前redis所在库数据(默认是0号数据库),会清空RDB⽂件,同时也会⽣成dump.rdb、内容为空

主从同步:全量同步时会⾃动触发bgsave命令,⽣成rdb发送给从节点

优点:

  1. 整个Redis数据库将只包含⼀个⽂件 dump.rdb,⽅便持久化。
  2. 容灾性好,⽅便备份。
  3. 性能最⼤化,fork ⼦进程来完成写操作,让主进程继续处理命令,所以是 IO 最⼤化。使⽤单独⼦进程来进⾏持久化,主进程不会进⾏任何 IO 操作,保证了 redis 的⾼性能
  4. 相对于数据集⼤时,⽐ AOF的启动效率更⾼。

缺点:

  1. 数据安全性低。RDB 是间隔⼀段时间进⾏持久化,如果持久化之间 redis 发⽣故障,会发⽣数据丢失。所以这种⽅式更适合数据要求不严谨的时候)
  2. 由于RDB是通过fork⼦进程来协助完成数据持久化⼯作的,因此,如果当数据集较⼤时,可能会导致整个服务器停⽌服务⼏百毫秒,甚⾄是1秒钟。会占⽤cpu

AOF:Append Only File 以⽇志的形式记录服务器所处理的每⼀个写、删除操作,查询操作不会记录,以⽂本的⽅式记录,可以打开⽂件看到详细的操作记录,调操作系统命令进程刷盘

  1. 所有的写命令会追加到 AOF 缓冲中。
  2. AOF 缓冲区根据对应的策略向硬盘进⾏同步操作。
  3. 随着 AOF ⽂件越来越⼤,需要定期对 AOF ⽂件进⾏重写,达到压缩的⽬的。
  4. 当 Redis 重启时,可以加载 AOF ⽂件进⾏数据恢复。同步策略:
    • 每秒同步:异步完成,效率⾮常⾼,⼀旦系统出现宕机现象,那么这⼀秒钟之内修改的数据将会丢失
    • 每修改同步:同步持久化,每次发⽣的数据变化都会被⽴即记录到磁盘中,最多丢⼀条 不同步:由操作系统控制,可能丢失较多数据

优点:

  1. 数据安全
  2. 通过 append 模式写⽂件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redischeck-aof ⼯具解决数据⼀致性问题。
  3. AOF 机制的 rewrite 模式。定期对AOF⽂件进⾏重写,以达到压缩的⽬的

缺点:

  1. AOF ⽂件⽐ RDB ⽂件⼤,且恢复速度慢。
  2. 数据集⼤的时候,⽐ rdb 启动效率低。
  3. 运⾏效率没有RDB⾼

对⽐:
1. AOF⽂件⽐RDB更新频率⾼,优先使⽤AOF还原数据。AOF⽐RDB更安全也更⼤
2. RDB性能⽐AOF好
3. 如果两个都配了优先加载AOF

12 Redis单线程为什么这么快

Redis基于Reactor模式开发了⽹络事件处理器、⽂件事件处理器fileeventhandler。它是单线程的, 所以 Redis才叫做单线程的模型,它采⽤IO多路复⽤机制来同时监听多个Socket,根据Socket上的事件类型来选择对应的事件处理器来处理这个事件。可以实现⾼性能的⽹络通信模型,⼜可以跟内部其他单线程的模块进⾏对接,保证了 Redis内部的线程模型的简单性。
⽂件事件处理器的结构包含4个部分:多个Socket、IO多路复⽤程序、⽂件事件分派器以及事件处理器(命令请求处理器、命令回复处理器、连接应答处理器等)。
多个 Socket 可能并发的产⽣不同的事件,IO多路复⽤程序会监听多个 Socket,会将 Socket 放⼊⼀个队列中排队,每次从队列中有序、同步取出⼀个 Socket 给事件分派器,事件分派器把 Socket 给对应的事件处理器。
然后⼀个 Socket 的事件处理完之后,IO多路复⽤程序才会将队列中的下⼀个 Socket 给事件分派器。⽂件事件分派器会根据每个 Socket 当前产⽣的事件,来选择对应的事件处理器来处理。

  1. Redis启动初始化时,将连接应答处理器跟AE_READABLE事件关联。
  2. 若⼀个客户端发起连接,会产⽣⼀个AE_READABLE事件,然后由连接应答处理器负责和客户端建⽴ 连接,创建客户端对应的socket,同时将这个socket的AE_READABLE事件和命令请求处理器关联,使 得客户端可以向主服务器发送命令请求。
  3. 当客户端向Redis发请求时(不管读还是写请求),客户端socket都会产⽣⼀个AE_READABLE事件,触发命令请求处理器。处理器读取客户端的命令内容, 然后传给相关程序执⾏。
  4. 当Redis服务器准备好给客户端的响应数据后,会将socket的AE_WRITABLE事件和命令回复处理器关联,当客户端准备好读取响应数据时,会在socket产⽣⼀个AE_WRITABLE事件,由对应命令回复处 理器处理,即将准备好的响应数据写⼊socket,供客户端读取。
  5. 命令回复处理器全部写完到 socket 后,就会删除该socket的AE_WRITABLE事件和命令回复处理器的映射。

单线程快的原因:
1. 纯内存操作
2. 核⼼是基于⾮阻塞的IO多路复⽤机制
3. 单线程反⽽避免了多线程的频繁上下⽂切换带来的性能问题

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java面试笔试资料包括JAVA基础核心知识点深度学习Spring面试题等资料合集: JAVA核心知识点整理-282页 Java与哈希算法.docx Java中Lambda表达式的使用.docx JAVA多线程之线程间的通信方式.docx Java注解详解.docx Java线程池.docx JDK1.8Stream操作.docx JDK8有新特性.docx JVM堆三代.docx JVM的垃圾回收机制详解和调优.docx Spring源码分析之IoC.docx 关于线程和线程池的学习与使用.docx 深入理解JVM垃圾回收机制.docx 深入理解多线程实现的另一种方式Callable.docx 红黑树简介.docx 线程死锁及解决办法.docx 线程锁之重入锁.docx 线程间的通信.docx 虚拟机内存结构和垃圾回收docx.docx 锁分类的了解.docx 集合的扩容机制.png SpringMVC部分.docx Spring部分.docx 第一题.pdf 第七题 谈谈MySQL支持的事务隔离级别 (1).pdf 第三题 对比HashTable HashMap TreeMap有什么不同.pdf 第二题 Exception Error区别.pdf 第五题 如何保证集合是线程安全的.pdf 第八题 Java并发类库提供的线程池有哪几种 分别有什么特点.pdf 第六题 synchronized和ReentLock有什么区别.pdf 第四题 ArrayList LinkedList Vector的区别.pdf docker讲得最清楚.doc Dubbo是什么?能做什么?.doc java 基于TCP协议的Socket编程和通信.doc Java面试高级篇—说说TCP,UDP和socket,Http之间联系和区别.doc MySQL千万级的大表要怎么优化(读写分离、水平拆分、垂直拆分).doc redis缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级.doc RPC (Remote Procedure Call)即远程过程调用.doc Spring 面试问题 TOP 50(干货推荐收藏必备).doc springboot常见面试题.doc svn和git的区别及适用场景.doc ZooKeeper.doc 为什么分布式一定要有Redis.doc 分布式、高并发、多线程,到底有什么区别.doc 分布式事务.doc 四款消息队列大比拼.docx 多台web服务器之间共享session.docx 消息中间件Kafka与RabbitMQ.doc 电商项目描述注意点.doc 秒杀业务的流量削峰场景如何解决.doc 面试题:Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点.doc

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值