Redis常见面试题

参考博客:

  1. Redis常见面试题:http://jasontec.cn/articles/2019/12/20/1576826633007.html
  2. redis面试总结(未看):https://www.cnblogs.com/jiahaoJAVA/p/6244278.html
  3. 什么是缓存穿刺和缓存雪崩?如何解决缓存穿透,缓存雪崩:https://blog.csdn.net/u011665991/article/details/89956398
  4. Redis 通信协议RESP:https://blog.csdn.net/alex_xfboy/article/details/88959064
  5. 为什么redis cluster至少需要三个主节点?:https://www.zhihu.com/question/354518943
  6. Redis ==> 集群的三种模式:https://www.cnblogs.com/L-Test/p/11626124.html

介绍:Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API的非关系型数据库。

传统数据库遵循 ACID原则 。而 Nosql(Not Only SQL 的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称) 一般为分布式而分布式一般遵循 CAP原则

Github 源码:https://github.com/antirez/redis
Redis 官网:https://redis.io/

1.Redis支持的五种数据类型?

string类型是Redis最基本的数据类型,一个键最大能存储512MB。
Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。

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 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
	在 key 对应 list 的头部添加字符串元素
	格式: lpush  name  value

	在 key 对应 list 的尾部添加字符串元素
	格式: rpush  name  value

	key 对应 list 中删除 count 个和 value 相同的元素
	格式: lrem name index

	返回 key 对应 list 的长度
	格式: llen name  

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 文件保存到磁盘中。

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

3. redis通讯协议(RESP ),能解释下什么是RESP?有什么特点?

RESP 是redis客户端和服务端之前使用的一种通讯协议;
RESP 的特点:实现简单、快速解析、可读性好;

4. Redis 有哪些架构模式?讲讲各自的特点?

详情见:https://www.cnblogs.com/L-Test/p/11626124.html
1. 单机版
在这里插入图片描述
优缺点:
优点:

 1. 简单;

缺点:

 1. 内存容量有限;
 2. 处理能力有限;
 3. 无法高可用;

2. 主从复制
在这里插入图片描述
Redis 的复制(replication)功能允许用户根据一个 Redis 服务器来创建任意多个该服务器的复制品,其中被复制的服务器为主服务器(master),而通过复制创建出来的服务器复制品则为从服务器(slave)。
只要主从服务器之间的网络连接正常,主从服务器两者会具有相同的数据,主服务器就会一直将发生在自己身上的数据更新同步 给从服务器,从而一直保证主从服务器的数据相同。
优缺点:
优点:

 1. master/slave 角色;
 2. master/slave 数据相同;
 3. 降低 master 读压力在转交从库;
 4. 无法保证高可用;

缺点:

1.没有解决 master 写的压力;
2.无法高可用;

3. 哨兵(sentinel)
在这里插入图片描述
Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。其中三个特性:

监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。

优缺点:
优点:

1.保证高可用;
2.监控各个节点;
3.自动故障迁移;

缺点:

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

4. 集群(proxy型)
在这里插入图片描述
Twemproxy 是一个 Twitter 开源的一个 redis 和 memcache 快速/轻量级代理服务器; Twemproxy 是一个快速的单线程代理程序,支持 Memcached ASCII 协议和 redis 协议。
优缺点:
优点:

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

缺点:

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

5. 集群(直连型)
在这里插入图片描述
从redis 3.0之后版本支持redis-cluster集群,Redis-Cluster采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
优缺点:
优点:

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

缺点:

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

5.什么是一致性哈希算法?什么是哈希槽?(未看)

这两个问题篇幅过长 网上找了两个解锁的不错的文章

https://www.cnblogs.com/lpfuture/p/5796398.html

http://www.jasontec.cn/articles/2020/04/11/1586586130767.html

6.Redis常用命令?

Keys pattern
*表示区配所有

Exists key
查看key是否存在

Set
设置 key 对应的值为 string 类型的 value。

setnx
设置 key 对应的值为 string 类型的 value。如果 key 已经存在,返回 0,nx 是 not exist 的意思。

del key
删除某个key

Expire 
设置过期时间(单位秒)

TTL key
查看剩下多少时间,返回负数则key失效,key不存在了

Setex
设置 key 对应的值为 string 类型的 value,并指定此键值对应的有效期。

Mset
一次设置多个 key 的值,成功返回 ok 表示所有的值都设置了,失败返回 0 表示没有任何值被设置。

Getset
设置 key 的值,并返回 key 的旧值。

Mget
一次获取多个 key 的值,如果对应 key 不存在,则对应返回 nil。

Incr
对 key 的值做加加操作,并返回新的值。注意 incr 一个不是 int 的 value 会返回错误,incr 一个不存在的 key,则设置 key 为 1

incrby
同 incr 类似,加指定值 ,key 不存在时候会设置 key,并认为原来的 value 是 0

Decr
对 key 的值做的是减减操作,decr 一个不存在 key,则设置 key 为-1

Decrby
同 decr,减指定值。

Append
给指定 key 的字符串值追加 value,返回新字符串值的长度。

Strlen
取指定 key 的 value 值的长度。

persist xxx(取消过期时间)
选择数据库(0-15库)

Select 0
选择数据库

move age 1
把age 移动到1库

Randomkey
随机返回一个key

Rename
重命名

Type 
返回数据类型

7.Redis分布式锁是怎么实现的?

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放,执行业务,完成之后释放锁;

如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!

redis分布式锁原理及实现:https://blog.csdn.net/shuangyueliao/article/details/89344256

8.Redis做异步队列怎么使用?有什么缺点?

生产者和消费者一对一:一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
生产者消费者一对多:用redis的主题订阅者模式:pub/sub。可以实现1:N的消息队列。
生产者消费者一对多缺点:pub/sub是无状态的,就是不知道是不是一定到达。对于发送者来说,消息发了就再也找不到了。

redis异步队列:https://www.jianshu.com/p/479ed6233742

9.什么是缓存穿透?如何解决?什么是缓存雪崩?何如解决?(https://blog.csdn.net/u011665991/article/details/89956398

缓存穿透:是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查询不到数据则不写入缓存,这将导致这个不存在的数据每次请求都到数据库去查询,造成缓存穿透。
缓存穿透解决方案

1.过滤(布隆过滤 Bloom filter):对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。
2.缓存空对象,将 null 变成一个值:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

缓存雪崩:如果缓存集中在一段时间内失效,发生大量缓存穿透,所有查询都落在数据库上,造成了缓存雪崩。
缓存雪崩解决方案

这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。

1.数据预热:
可以通过缓存reload机制,预先去更新缓存,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀;

2.加锁排队:
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
业界比较常用的做法,是使用mutex(互斥锁)。
简单地来说,就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
SETNX,是「SET if Not eXists」的缩写,也就是只有不存在的时候才设置,可以利用它来实现锁的效果。

3.做二级缓存,或者双缓存策略:
A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。

4.缓存永不过期:
这里的“永远不过期”包含两层意思:
 (1) 从缓存上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。
(2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期。
从实战看,这种方法对于性能非常友好,唯一不足的就是构建缓存时候,其余线程(非构建缓存的线程)可能访问的是老数据,但是对于一般的互联网功能来说这个还是可以忍受。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值