乐趣区

关于java:持续输出面试题之Redis篇

开篇介绍

大家好,我是 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 事务性能是通过 MULTIEXECDISCARDWATCH 四个原语实现的

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)
  • 队列
  • 排行榜 / 计数器
  • 公布 / 订阅
退出移动版