Redis高频面试题(来自字节跳动,腾讯,百度面试题总结)

Redis面试题(2020最新版)_ThinkWon的博客-CSDN博客_redis面试题

Redis面试题

#Redis高频面试题(来自字节跳动,腾讯,百度面试题总结)

概述

什么是Redis

Redis 是一个使用 C 语言写成的,开源的 key-value 数据库。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。目前,Vmware在资助着redis项目的开发和维护。

Redis为什么这么快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路 I/O 复用模型,非阻塞 IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis 直接自己构建了 VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

Redis 数据类型

Redis有哪些数据类型?

Redis目前支持5种数据类型,分别是: String(字符串):

List(列表):

Hash(字典):

Set(集合):

Sorted Set(有序集合):

Redis的zset实现原理及时间复杂度

数据量少的时候使用压缩链表ziplist实现,有序集合使用紧挨在一起的压缩列表节点来保存,第一个节点保存member,第二个保存score。ziplist内的集合元素按score从小到大排序,score较小的排在表头位置。 数据量大的时候使用跳跃列表skiplist和哈希表hash_map结合实现,查找删除插入的时间复杂度都是O(longN)

持久化原理

什么是持久化

Redis 是一种内存数据库,将数据保存在内存中,一旦进程退出,Redis 的数据就会丢失。 为了解决这个问题,Redis 提供了 RDB 和 AOF 两种持久化方案,将内存中的数据保存到磁盘中,避免数据丢失。

持久化方式RDB和AOF底层原理

Redis 提供了不同级别的持久化方式:RDB(默认方式)和AOF

RDB 持久化方式能够在指定的时间间隔能对你的数据进行快照(snapshotting)存储,将内存中的数据不断写入二进制文件中,默认文件dump.rdb,可配置Redis在n秒内如果超过m个key被修改就自动保存快照。(性能高,但是可能会出现数据丢失) save 900 1 #900秒内如果超过1个key被修改,则发起快照保存。 save 300 10 #300秒内如果超过10个key被修改,则快照保存。

RDB持久化只会周期性的保存数据,在未触发下一次存储时服务宕机,就会丢失增量数据。当数据量较大的情况下,fork子进程这个操作很消耗cpu,可能会发生长达秒级别的阻塞情况。

SAVE是阻塞式持久化,执行命令时Redis主进程把内存数据写入到RDB文件中直到创建完毕,期间Redis不能处理任何命令。

BGSAVE属于非阻塞式持久化,创建一个子进程把内存中数据写入RDB文件里同时主进程处理命令请求。

如图展示了RDB使用save 或者 bgsave 进行fork子进程进行持久化的流程:

https://i2.wp.com/img-blog.csdnimg.cn/20200521220154269.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2E1MTk2NDAwMjY=,size_16,color_FFFFFF,t_70

AOF(Append-only file) 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大。(类似于MySql的日志方式,记录每次更新的日志)(性能低,但是数据完整)

当开启AOF后,服务端每执行一次写操作就会把该条命令追加到一个单独的AOF缓冲区的末尾,然后把AOF缓冲区的内容写入AOF文件里,由于磁盘缓冲区的存在写入AOF文件之后,并不代表数据已经落盘了,而何时进行文件同步则是根据配置的appendfsync来进行配置:

appendfsync选项:always、everysec和no: always:服务器在每执行一个事件就把AOF缓冲区的内容强制性的写入硬盘上的AOF文件里,保证了数据持久化的完整性,效率是最慢的但最安全的;

everysec:服务端每隔一秒才会进行一次文件同步把内存缓冲区里的AOF缓存数据真正写入AOF文件里,兼顾了效率和完整性,极端情况服务器宕机只会丢失一秒内对Redis数据库的写操作;

no:表示默认系统的缓存区写入磁盘的机制,不做程序强制,数据安全性和完整性差一些。

RDB和AOF的优缺点和使用场景

RDB优点:

RDB缺点:

AOF 优点:

AOF 缺点:

如何选择RDB和AOF

RDB 和 AOF在数据恢复时的优先级?

数据恢复时 AOF 优先于 RDB, 因为AOF的同步频率相对高,可靠性高

事务

什么是事务?

Redis事务的概念

Redis 事务的本质是通过MULTI、EXEC、WATCH等一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。 总结说:redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。

Redis事务命令

Redis事务使用方法

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的

Redis会将一个事务中的所有命令序列化,然后按顺序执行。

以下示例会原子化地递增foo键和bar键的值:

https://i2.wp.com/imgconvert.csdnimg.cn/aHR0cDovL2dob3VsaWNoLnhuaW5qYS5vcmcvd3AtY29udGVudC91cGxvYWRzL3NpdGVzLzIvMjAxNi8xMC9pbWFnZS0wMV90cmFuc2FjdGlvbi1leGFtcGxlLnBuZw?x-oss-process=image/format,png

Redis事务中出错会怎样?

事务期间,可能会遇到几种命令错误:

对于第一种错误,客户端会在EXEC调用之前检测, 通过检查排队命令的状态回复,如果命令使用QUEUED进行响应,则它已正确排队;否则Redis将返回错误。

对于第二种错误,服务端会记住在累积命令期间发生的错误,当EXEC命令调用时,将拒绝执行事务,并返回这些错误,同时自动清除命令队列。即使事务中的某些命令执行失败,其他命令仍会被正常执行。(包括出错命令之后的命令)

为什么Redis事务不支持回滚?

事实上Redis命令在事务执行时可能会失败,但仍会继续执行剩余命令而不是Rollback(事务回滚)。如果你使用过关系数据库,这种情况可能会让你感到很奇怪。然而针对这种情况具备很好的解释:

“如果错误就是发生了呢?”这是一个反对Redis观点的争论。然而应该指出的是,通常情况下,回滚并不能挽救编程错误。鉴于没有人能够挽救程序员的错误,并且Redis命令失败所需的错误类型不太可能进入生产环境,所以我们选择了不支持错误回滚(Rollback)这种更简单快捷的方法。

Redis事务支持隔离性吗

Redis 是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis 的事务是总是带有隔离性的。

Redis事务其他实现

基于Lua脚本,Redis可以保证脚本内的命令一次性、按顺序地执行, 其同时也不提供事务运行错误的回滚,执行过程中如果部分命令运行错误,剩下的命令还是会继续运行完 基于中间标记变量,通过另外的标记变量来标识事务是否执行完成,读取数据时先读取该标记变量判断是否事务执行完成。但这样会需要额外写代码实现,比较繁琐

乐观锁与悲观锁的区别?

Redis中的管道有什么用

一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多POP3协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。

缓存雪崩,缓存击穿,缓存穿透现象及解决方案

缓存雪崩:

缓存穿透:

缓存击穿:

缓存高可用方案

这就是三者的区别,差不多,但又有一些区别。因为缓存雪崩、穿透和击穿,是缓存最大的问题,要么不出现,一旦出现就是致命性的问题 一般避免以上情况发生我们从三个时间段去分析下:

Redis的过期策略和内存淘汰策略

Redis key过期删除策略

使用过Redis的同学应该知道,我们在设置一个key之后,可以指定这个key的过期时间。那么这个key到了过期时间就会立即被删除吗?Redis是如何删除这些过期key的呢? Redis是使用定期删除 + 惰性删除 两者配合的过期策略。

文章二

Java面试总结汇总,整理了包括Java基础知识,集合容器,并发编程,JVM,常用开源框架Spring,MyBatis,数据库,中间件等,包含了作为一个Java工程师在面试中需要用到或者可能用到的绝大部分知识。欢迎大家阅读,本人见识有限,写的博客难免有错误或者疏忽的地方,还望各位大佬指点,在此表示感激不尽。文章持续更新中…

https://img-blog.csdnimg.cn/20200116103941934.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly90aGlua3dvbi5ibG9nLmNzZG4ubmV0,size_16,color_FFFFFF,t_70

概述

什么是Redis

Redis(Remote Dictionary Server) 是一个使用 C 语言编写的,开源的(BSD许可)高性能非关系型(NoSQL)的键值对数据库。

Redis 可以存储键和五种不同类型的值之间的映射。键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。

与传统数据库不同的是 Redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。另外,Redis 也经常用来做分布式锁。除此之外,Redis 支持事务 、持久化、LUA脚本、LRU驱动事件、多种集群方案。

Redis有哪些优缺点

优点