开篇介绍
大家好,我是Java最全面试题库
的提裤姐,明天这篇是数据库面试题系列的第五篇,次要总结了Redis相干的面试题;在后续,会沿着第一篇开篇的常识线路始终总结上来,做到日更!如果我能做到百日百更,心愿你也能够跟着百日百刷,一百天养成一个好习惯。
redis的数据类型有哪些?
String
惯例的set/get操作,value能够是String也能够是数字。
利用:个别做一些简单的计数性能的缓存。
hash
这里value寄存的是结构化的对象,比拟不便的就是操作其中的某个字段。
利用:单点登录,就是用这种数据结构存储用户信息,以cookieId
作为key,设置30分钟为缓存过期工夫,能很好的模拟出相似session的成果。
list
List的数据结构
利用:能够做简略的音讯队列的性能。另外,能够利用lrange
命令,做基于redis的分页性能,性能极佳,用户体验好。生产者和消费者的场景,LIST能够很好的实现排队,先进先出的准则。
set
因为set堆放的是一堆不反复值的汇合。
利用:能够做全局去重的性能。为什么不必JVM自带的Set进行去重?因为咱们的零碎个别都是集群部署,应用JVM自带的Set,比拟麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。 另外,就是利用交加、并集、差集等操作,能够计算独特爱好,全副的爱好,本人独有的爱好等性能。
sorted set
sorted set多了一个权重参数score,汇合中的元素可能按score进行排列。
利用:能够做排行榜利用,取TOP N操作。
Redis 内部结构有哪些?
dict
实质上是为了解决算法中的查找问题(Searching)是一个用于保护key和value映射关系的数据结构,与很多语言中的Map或dictionary相似。 实质上是为了解决算法中的查找问题(Searching)。
sds
sds就等同于char * 它能够存储任意二进制数据,不能像C语言字符串那样以字符’\0’
来标识字符串的完结,因而它必然有个长度字段。
skiplist (跳跃表)
跳表是一种实现起来很简略,单层多指针的链表,它查找效率很高,堪比优化过的二叉均衡树,且比均衡树的实现。
ziplist 压缩表
ziplist是一个编码后的列表,是由一系列非凡编码的间断内存块组成的程序型数据结构。
Memcache 与 Redis 的区别都有哪些?
存储形式不同:
Memcache 是把数据全副存在内存中,数据不能超过内存的大小,断电后数据库会挂掉。
Redis 有局部存在硬盘上,这样能保证数据的持久性。
数据反对的类型不同:
memcahe 对数据类型反对绝对简略
redis 有简单的数据类型。
应用底层模型不同:
它们之间底层实现形式 以及与客户端之间通信的利用协定不一样。
Redis 间接本人构建了 VM 机制 ,因为个别的零碎调用零碎函数的话,会节约肯定的工夫去挪动和申请。
反对的 value 大小不一样:
redis 最大能够达到 1GB
而 memcache 只有 1MB
为什么 redis 须要把所有数据放到内存中?
Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的形式将数据写入磁盘。所以 redis 具备疾速和数据长久化的特色。如果不将数据放在内存中,磁盘 I/O 速度为重大影响 redis 的性能。在内存越来越便宜的明天,redis 将会越来越受欢迎。如果设置了最大应用的内存,则数据已有记录数达到内存限值后不能持续插入新值。
Redis 如何进行长久化?
Redis是一个反对长久化的内存数据库,通过长久化机制把内存中的数据同步到硬盘文件来保证数据长久化。当Redis重启后通过把硬盘文件从新加载到内存,就能达到复原数据的目标。
实现:
独自创立fork()一个子过程,将以后父过程的数据库数据复制到子过程的内存中,而后由子过程写入到临时文件中,长久化的过程完结了,再用这个临时文件替换上次的快照文件,而后子过程退出,内存开释。
形式:
- RDB是Redis默认的长久化形式。依照肯定的工夫周期策略把内存的数据以快照的模式保留到硬盘的二进制文件。即
Snapshot
快照存储,对应产生的数据文件为dump.rdb
,通过配置文件中的save
参数来定义快照的周期。( 快照能够是其所示意的数据的一个正本,也能够是数据的一个复制品。) - AOF:Redis会将每一个收到的写命令都通过
Write
函数追加到文件最初,相似于MySQL的binlog
。当Redis重启是会通过从新执行文件中保留的写命令来在内存中重建整个数据库的内容。
当两种形式同时开启时,数据恢复Redis会优先选择AOF复原。
RDB和AOF的优缺点有哪些?
RDB长久化
- 长处:RDB文件紧凑,体积小,网络传输快,适宜全量复制;复原速度比AOF快很多。当然,与AOF相比,RDB最重要的长处之一是对性能的影响绝对较小。
- 毛病:RDB文件的致命毛病在于其数据快照的长久化形式决定了必然做不到实时长久化,而在数据越来越重要的明天,数据的大量失落很多时候是无奈承受的,因而AOF长久化成为支流。此外,RDB文件须要满足特定格局,兼容性差(如老版本的Redis不兼容新版本的RDB文件)。
AOF长久化
- 长处:反对秒级长久化、兼容性好
- 毛病:文件大、复原速度慢、对性能影响大。
什么是缓存穿透?如何防止?
缓存穿透
个别的缓存零碎,都是依照key去缓存查问,如果不存在对应的value,就应该去后端系统查找(比方DB)。一些歹意的申请会成心查问不存在的key,申请量很大,就会对后端系统造成很大的压力,就叫做缓存穿透。
防止
- 对查问后果为空的状况也进行缓存,缓存工夫设置短一点,或者该key对应的数据insert了之后清理缓存。
- 对肯定不存在的key进行过滤。能够把所有的可能存在的key放到一个大的
Bitmap
中,查问时通过该bitmap过滤。
什么是缓存雪崩?何如防止?
缓存雪崩
当缓存服务器重启或者大量缓存集中在某一个时间段生效,这样在生效的时候,会给后端系统带来很大压力。导致系统解体。
防止
- 在缓存生效后,通过加锁或者队列来管制读数据库写缓存的线程数量。比方对某个key只容许一个线程查问数据和写缓存,其余线程期待。
- 做二级缓存,A1为原始缓存,A2为拷贝缓存;A1生效时,能够拜访A2,A1缓存生效工夫设置为短期,A2设置为长期
- 不同的key,设置不同的过期工夫,让缓存生效的工夫点尽量平均。
redis的淘汰策略有哪些?
noeviction
:不删除策略,达到最大内存限度时,如果须要更多内存,间接返回错误信息。大多数写命令都会导致占用更多的内存(有极少数会例外)allkeys-lru
:所有key通用;优先删除最近起码应用(less recently used ,LRU) 的 key。volatile-lru
:只限于设置了 expire 的局部;优先删除最近起码应用(less recently used ,LRU) 的 key。allkeys-random
:所有key通用;随机删除一部分 key。volatile-random
:只限于设置了 expire 的局部;随机删除一部分 key。volatile-ttl
:只限于设置了 expire 的局部;优先删除剩余时间(time to live,TTL) 短的key。
Redis是单线程的,但为什么这么快?
1、齐全基于内存,绝大部分申请是纯正的内存操作,十分疾速。数据存在内存中,相似于HashMap,HashMap的劣势就是查找和操作的工夫复杂度都是O(1)
;
2、数据结构简略,对数据操作也简略,Redis中的数据结构是专门进行设计的;
3、采纳单线程,防止了不必要的上下文切换和竞争条件,也不存在多过程或者多线程导致的切换而耗费 CPU,不必去思考各种锁的问题,不存在加锁开释锁操作,没有因为可能呈现死锁而导致的性能耗费;
4、应用多路I/O复用模型,非阻塞IO;这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程
5、应用底层模型不同,它们之间底层实现形式以及与客户端之间通信的利用协定不一样,Redis间接本人构建了VM 机制 ,因为个别的零碎调用零碎函数的话,会节约肯定的工夫去挪动和申请;
Redis的内存分为哪些?
数据
作为数据库,数据是最次要的局部;这部分占用的内存会统计在used_memory
中。
过程自身运行须要的内存
Redis主过程自身运行必定须要占用内存,如代码、常量池等等;这部分内存大概几兆,在大多数生产环境中与Redis数据占用的内存相比能够疏忽。这部分内存不是由jemalloc调配,因而不会统计在used_memory
中。
缓冲内存
缓冲内存包含客户端缓冲区
、复制积压缓冲区
、AOF缓冲区
等;
客户端缓冲存储客户端连贯的输入输出缓冲;
复制积压缓冲用于局部复制性能;
AOF缓冲区用于在进行AOF重写时,保留最近的写入命令。
在理解相应性能之前,不须要晓得这些缓冲的细节;这部分内存由jemalloc调配,因而会统计在used_memory
中。
内存碎片
内存碎片是Redis在调配、回收物理内存过程中产生的。例如,如果对数据的更改频繁,而且数据之间的大小相差很大,可能导致redis开释的空间在物理内存中并没有开释,但redis又无奈无效利用,这就造成了内存碎片。内存碎片不会统计在used_memory
中。
说说Redis事务?
Redis事务性能是通过MULTI
、EXEC
、DISCARD
和WATCH
四个原语实现的
Redis会将一个事务中的所有命令序列化,而后按程序执行。
- redis 不反对回滚“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”, 所以 Redis 的外部能够放弃简略且疾速。
- 如果在一个事务中的命令呈现谬误,那么所有的命令都不会执行;
- 如果在一个事务中呈现运行谬误,那么正确的命令会被执行。
命令
MULTI
命令用于开启一个事务,它总是返回OK。 MULTI执行之后,客户端能够持续向服务器发送任意多条命令,这些命令不会立刻被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。EXEC
:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil 。DISCARD
:通过调用DISCARD,客户端能够清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。WATCH
命令能够为 Redis 事务提供check-and-set (CAS)
行为。 能够监控一个或多个键,一旦其中有一个键被批改(或删除),之后的事务就不会执行,监控始终继续到EXEC命令。
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 适宜的场景有哪些?
- 会话缓存(Session Cache)
- 全页缓存(FPC)
- 队列
- 排行榜/计数器
- 公布/订阅