几道常问Redis面试题,你能答对吗?

目录
  • 1、Redis支持的数据类型?
  • 2、什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?
  • 3、Redis 有哪些架构模式?讲讲各自的特点
  • 4、使用过Redis分布式锁么,它是怎么实现的?
  • 5、使用过Redis做异步队列么,你是怎么用的?有什么缺点?
  • 6、什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
  • 7、Redis常用命令
  • 8.Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比
  • 9、为什么Redis 单线程却能支撑高并发?
  • 10、Redis常见性能问题和解决方案:
  • 11、Redis的并发竞争问题如何解决?
  • 12、说说Redis的内存淘汰策略
  • 13、Redis最适合的场景
  • 总结

1、Redis支持的数据类型?

String(字符串)

格式: set key value

string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。

string类型是Redis最基本的数据类型,一个键最大能存储512MB。

Hash(哈希)

格式: hmset name key1 value1 key2 value2

Redis hash 是一个键值(key=>value)对集合。

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

格式: lpush name value

在 key 对应 list 的头部添加字符串元素

格式: rpush name value

在 key 对应 list 的尾部添加字符串元素

格式: lrem name index

key 对应 list 中删除 count 个和 value 相同的元素

格式: llen name

返回 key 对应 list 的长度

Set(集合)

格式: sadd name value

Redis的Set是string类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。

zset(sorted set:有序集合)

格式: zadd name score value

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zset的成员是唯一的,但分数(score)却可以重复。

2、什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

Redis 提供了两种持久化方式:RDB(默认) 和AOF

RDB:

rdb是Redis DataBase缩写

功能核心函数rdbSave(生成RDB文件)和rdbLoad(从文件加载内存)两个函数

AOF:

Aof是Append-only file缩写

每当执行服务器(定时)任务或者函数时flushAppendOnlyFile 函数都会被调用, 这个函数执行以下两个工作

aof写入保存:

  • WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件
  • SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。

存储结构:

内容是redis通讯协议(RESP )格式的命令文本存储。

比较:

  • aof文件比rdb更新频率高,优先使用aof还原数据。
  • aof比rdb更安全也更大
  • rdb性能比aof好
  • 如果两个都配了优先加载AOF

刚刚上面你有提到redis通讯协议(RESP ),能解释下什么是RESP?有什么特点?(可以看到很多面试其实都是连环炮,面试官其实在等着你回答到这个点,如果你答上了对你的评价就又加了一分)

RESP 是redis客户端和服务端之前使用的一种通讯协议;

RESP 的特点:实现简单、快速解析、可读性好

For Simple Strings the first byte of the reply is "+" 回复

For Errors the first byte of the reply is "-" 错误

For Integers the first byte of the reply is ":" 整数

For Bulk Strings the first byte of the reply is "$" 字符串

For Arrays the first byte of the reply is "*" 数组

3、Redis 有哪些架构模式?讲讲各自的特点

单机版

特点:

简单

问题:

  • 内存容量有限
  • 处理能力有限
  • 无法高可用。

主从复制

Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。

只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。

特点:

  • master/slave 角色
  • master/slave 数据相同降低
  • master 读压力在转交从库

问题:

  • 无法保证高可用
  • 没有解决 master 写的压力

哨兵

Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:

  • 监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
  • 提醒(Notification):当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
  • 自动故障迁移(Automatic failover):当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

特点:

保证高可用监控各个节点自动故障迁移

缺点:

  • 主从模式,切换需要时间丢数据
  • 没有解决 master 写的压力

集群(proxy 型)

Twemproxy 是一个 Twitter 开源的一个 redis 和 memcache 快速/轻量级代理服务器;Twemproxy 是一个快速的单线程代理程序,支持 Memcached ASCII 协议和 redis 协议。

特点:

  • 多种 hash 算法:MD5、CRC16、CRC32、CRC32a、hsieh、murmur、Jenkins
  • 支持失败节点自动删除
  • 后端 Sharding 分片逻辑对业务透明,业务方的读写方式和操作单个 Redis 一致

缺点:

  • 增加了新的 proxy,需要维护其高可用。
  • failover 逻辑需要自己实现,其本身不能支持故障的自动转移可扩展性差,进行扩缩容都需要手动干预

集群(直连型):

从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。

特点:

  • 无中心架构(不存在哪个节点影响性能瓶颈),少了 proxy 层。
  • 数据按照 slot 存储分布在多个节点,节点间数据共享,可动态调整数据分布。
  • 可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。
  • 高可用性,部分节点不可用时,集群仍可用。通过增加 Slave 做备份数据副本 -实现故障自动 failover,节点之间通过 gossip 协议交换状态信息,用投票机制完成 Slave到 Master 的角色提升。

缺点:

  • 资源隔离性较差,容易出现相互影响的情况。
  • 数据通过异步复制,不保证数据的强一致性

高可用Redis架构分析搭建,可以参考:

高可用Redis服务架构分析与搭建

4、使用过Redis分布式锁么,它是怎么实现的?

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。

如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?

set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

5、使用过Redis做异步队列么,你是怎么用的?有什么缺点?

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。

缺点:

在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。

能不能生产一次消费多次呢?

使用pub/sub主题订阅者模式,可以实现1:N的消息队列。

6、什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?

缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

如何避免?

  • 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
  • 对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

如何避免?

  • 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
  • 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期
  • 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

这道相当常见,详细再参考下文,一定熟练掌握:

Redis缓存雪崩、缓存击穿、缓存穿透和常见的几种缓存模式

7、Redis常用命令

管理命令

# dbsize 返回当前数据库 key 的数量。 # info 返回当前 redis 服务器状态和一些统计信息。 # monitor 实时监听并返回redis服务器接收到的所有请求信息。 # shutdown 把数据同步保存到磁盘上,并关闭redis服务。 # config get parameter 获取一个 redis 配置参数信息。(个别参数可能无法获取) # config set parameter value 设置一个 redis 配置参数信息。(个别参数可能无法获取) # config resetstat 重置 info 命令的统计信息。(重置包括:keyspace 命中数、 # keyspace 错误数、 处理命令数,接收连接数、过期 key 数) # debug object key 获取一个 key 的调试信息。 # debug segfault 制造一次服务器当机。 # flushdb 删除当前数据库中所有 key,此方法不会失败。小心慎用 # flushall 删除全部数据库中所有 key,此方法不会失败。小心慎用

工具命令

#redis-server:Redis 服务器的 daemon 启动程序 #redis-cli:Redis 命令行操作工具。当然,你也可以用 telnet 根据其纯文本协议来操作 #redis-benchmark:Redis 性能测试工具,测试 Redis 在你的系统及你的配置下的读写性能 $redis-benchmark -n 100000 –c 50 #模拟同时由 50 个客户端发送 100000 个 SETs/GETs 查询 #redis-check-aof:更新日志检查 #redis-check-dump:本地数据库检查

8.Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比

Redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比

9、为什么Redis 单线程却能支撑高并发?

为什么Redis 单线程却能支撑高并发?

10、Redis常见性能问题和解决方案:

1).Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以Master最好不要写内存快照。

2).Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,AOF文件过大会影响Master重启的恢复速度。Master最好不要做任何持久化工作,包括内存快照和AOF日志文件,特别是不要启用内存快照做持久化,如果数据比较关键,某个Slave开启AOF备份数据,策略为每秒同步一次。

3).Master调用BGREWRITEAOF重写AOF文件,AOF在重写的时候会占大量的CPU和内存资源,导致服务load过高,出现短暂服务暂停现象。

4).Redis主从复制的性能问题,为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内

Redis性能分析相关问题,限于篇幅,给出文章链接:

Redis 性能问题分析(好文推荐)

11、Redis的并发竞争问题如何解决?

Redis为单进程单线程模式,采用队列模式将并发访问变为串行访问。Redis本身没有锁的概念,Redis对于多个客户端连接并不存在竞争,但是在Jedis客户端对Redis进行并发访问时会发生连接超时、数据转换错误、阻塞、客户端关闭连接等问题,这些问题均是由于客户端连接混乱造成。对此有2种解决方法:

  • 客户端角度,为保证每个客户端间正常有序与Redis进行通信,对连接进行池化,同时对客户端读写Redis操作采用内部锁synchronized。
  • 服务器角度,利用setnx实现锁。

注:对于第一种,需要应用程序自己处理资源的同步,可以使用的方法比较通俗,可以使用synchronized也可以使用lock;第二种需要用到Redis的setnx命令,但是需要注意一些问题。

12、说说Redis的内存淘汰策略

直接点这里:Redis的内存淘汰策略

13、Redis最适合的场景

Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?

如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:

  • Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
  • Redis支持数据的备份,即master-slave模式的数据备份。
  • Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

会话缓存(Session Cache)

最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗?

幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。

全页缓存(FPC)

除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。

再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。

此外,对WordPress的用户来说,Pantheon有一个非常好的插件 wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。

队列

Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。

如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这里去查看。

排行榜/计数器

Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”。

当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行:ZRANGE user_scores 0 10 WITHSCORES

Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以在这里看到。发布/订阅

最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Redis分布式锁的实现方式(redis面试题)

    什么是分布式锁? 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁.进程锁. 线程锁:主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比如synchronized是共享对象头,显示锁Lock是共享某个变量(state). 进程锁:为了控制同一操作系统中多个进程访问某个共享资源,因为进程具有独立性,各个进程无法访问其他进程的资源,因此无法通过synchronize

  • Java面试题冲刺第二天--Redis篇

    目录 面试题1:为什么要用 Redis ?业务在哪块儿用到的? 正经回答: 深入追问: 追问1:Redis里有哪些数据类型? 追问2:Redis与Memcached有哪些区别? 追问3:那Redis怎样防止异常数据不丢失的?如何持久化? 面试题2:Redis为啥是单线程的? 正经回答: 深入追问: 追问1:单线程只使用了单核CPU,太浪费,有什么办法发挥多核CPU的性能嘛? 面试题3:聊一下对缓存穿透.缓存击穿.缓存雪崩的理解吧 正经回答: 深入追问: 追问1:那你说一下针对缓存击穿的解决方法

  • 2021年最新Redis面试题汇总(2)

    目录 1.渐进式 rehash 的优点 2.rehash 流程在数据量大的时候会有什么问题吗(Hash 对象的扩容流程在数据量大的时候会有什么问题吗) 3.Redis 的网络事件处理器(Reactor 模式) 4.Redis 删除过期键的策略(缓存失效策略.数据过期策略) 5.Redis 的内存淘汰(驱逐)策略 6.Redis 的 LRU 算法怎么实现的? 7.Redis 的持久化机制有哪几种,各自的实现原理和优缺点? 1)RDB 2)AOF 8.为什么需要 AOF 重写 9.介绍下 AOF 重

  • 硬核 Redis 高频面试题解析

    目录 1.Redis 是单线程还是多线程? 2.为什么 Redis 是单线程? 3.Redis 为什么使用单进程.单线程也很快 4.Redis 在项目中的使用场景 5.Redis 常见的数据结构 6.Redis 的字符串(SDS)和C语言的字符串区别 7.Sorted Set底层数据结构 8.Sorted Set 为什么同时使用字典和跳跃表? 9.Sorted Set 为什么使用跳跃表,而不是红黑树? 10.Hash 对象底层结构 11.Hash 对象的扩容流程 12.渐进式 rehash 的优

  • 几道常问Redis面试题,你能答对吗?

    目录 1.Redis支持的数据类型? 2.什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么? 3.Redis 有哪些架构模式?讲讲各自的特点 4.使用过Redis分布式锁么,它是怎么实现的? 5.使用过Redis做异步队列么,你是怎么用的?有什么缺点? 6.什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免? 7.Redis常用命令 8.Redis单例.主从模式.sentinel以及集群的配置方式及优缺点对比 9.为什么Redis 单线程却能支撑高并发? 10.Redis常见性

  • Java多线程面试题(面试官常问)

    进程和线程 进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的.系统运行一个程序即是从一个进程从创建.运行到消亡的过程.在Java中,当我们启动main函数时其实就是启动了一个JVM的进程,而mian函数所在的线程就是这个进程中的一个线程,称为主线程. 线程是比进程更小的执行单位.一个进程在其执行的过程中可以产生多个线程.与进程不同的是同类的多个线程共享进程的堆和方法区资源,但每个线程都有自己的程序计数器.虚拟机和本地方法栈,所以系统在产生一个线程,或在各个线程之间切换工作是,

  • 面试常问:如何保证Redis缓存和数据库的数据一致性

    目录 一.一致性 1.强一致性 2.弱一致性 3.最终一致性 二.redis缓存和mysql数据库数据一致性解决 1.方案一:采用延时双删策略 2.方案二:一步更新缓存(基于订阅Binlog的同步机制) 首先,我们先来看看有哪几种一致性的情况呢? 一.一致性 1.强一致性 如果你的项目对缓存的要求是强一致性的,那么请不要使用缓存.这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大. 2.弱一致性 这种一致性级别约束了系统在写入成

  • SpringBoot服务监控机制原理解析(面试官常问)

    前言 任何一个服务如果没有监控,那就是两眼一抹黑,无法知道当前服务的运行情况,也就无法对可能出现的异常状况进行很好的处理,所以对任意一个服务来说,监控都是必不可少的. 就目前而言,大部分微服务应用都是基于 SpringBoot 来构建,所以了解 SpringBoot 的监控特性是非常有必要的,而 SpringBoot 也提供了一些特性来帮助我们监控应用. 本文基于 SpringBoot 2.3.1.RELEASE 版本演示. SpringBoot 监控 SpringBoot 中的监控可以分为 H

  • Java初学者常问的问题(推荐)

    本文介绍一些Java初学者常问的问题,可以用%除以一个小数吗? a += b 和 a = a + b 的效果有区别吗? 声明一个数组为什么需要花费大量时间? 为什么Java库不用随机pivot方式的快速排序? 基本数据类型 Q. 为什么 -0/3 结果是 0,而 -0.0/3.0 结果是 -0.0?(注意后边的结果0带负号) A. 在Java里,整数是用补码表示的.在补码中0只有一种表示方法.另一方面,浮点数则是用 IEEE 标准表示的, 对于0有两种表示方法, 0 和 -0. Q. 我可以用

  • Linux面试中最常问的10个问题总结

    前言 如果你要去面试一个Linux系统运维工程师的职位,下面这十个最常见的问题一定要会,否则你的面试可能就危险了.这些都是比较基本的问题,大家要理解,不能光死记硬背. 1.如何查看系统内核的版本 这里有两种方法: 1) uname -a uname 这个命令是用来打印系统信息的, -a 可以打印系统所有信息,其中包含内核版本,比如我的版本号是3.10.0-957.21.3.el7.X86_64. 2) cat /proc/version 下面再补充一下各个数字和字母代表的含义: 3 表示主版本号

  • 面试官:怎么做JDK8的垃圾收集器的调优(面试常问)

    看着面试官真诚的眼神,心中暗想看起来年纪轻轻却提出如此直击灵魂的问题.擦了擦额头上汗,我稍微调整了一下紧张的情绪,对面试官说: 在JDK8中有Serial收集器.Parallel收集器.CMS收集器.G1收集器这么几种收集器,需要根据实际硬件配置和业务需求进行选择调优. 如此浅显的回答,无法让面试官达到深入的要求,肯定不能满足面试官强烈的需求,果不其然面试官又追问到:如果是桌面应用,内存占用也就100MB,应该选择哪种垃圾收集器呢?我快速的回答:Serial收集器.看着面试官期待的眼神,我又详细

  • java关于string最常出现的面试题整理

    在学习了不少使用string处理字符串的方法后,对于这方面基础内容模块已经初步掌握.对于java面试时,字符串是比较基础和重点的模块,所以在学习和复习的时候,都需要在这方面做重点的学习.我们把试题分为基础内容和实例代码试题的运行两个部分,下面一起来看看具体内容. 一.基础内容 1.String类型是基础类型吗 基本数据类型包括byte,int,char,long,float,double,boolean,short一共八个 Java.lang.String类是final类型的,因此不能继承,修改

  • 面试最常问的13种Vue修饰符

    目录 1.lazy 2.trim 3.number 4.stop 5.capture 6.self 7.once 8.prevent 9.native 10.left,right,middle 11.passive 12.camel 12.sync 13.keyCode 1.lazy lazy修饰符作用是,改变输入框的值时value不会改变,当光标离开输入框时,v-model绑定的值value才会改变 <input type="text" v-model.lazy="v

随机推荐