【测开求职】面试题:Redis 吐血整理

编程入门 行业动态 更新时间:2024-10-24 11:17:05

【测开求职】<a href=https://www.elefans.com/category/jswz/34/1769418.html style=面试题:Redis 吐血整理"/>

【测开求职】面试题:Redis 吐血整理

部分大厂除了要求测开工程师掌握MySQL之外,对Redis也有要求,本篇文章整理了Redis相关的面试题,之前完全没有接触过Redis的朋友们也无需担心,可以看第二个部分的"入门笔记",两小时可以速通。亲测第一部分的面试题应对各个大厂的测开工程师毫无压力👉

目录

  • 一、面试题
    • Redis是什么
    • Redis的优缺点
    • Redis的应用场景
    • Redis为什么这么快
    • 为什么不直接用Redis做数据库
    • Redis的常见数据结构
    • Redis的持久化机制
    • Redis内存用完了会怎么办
    • Redis事务
    • Redis存在线程安全问题吗
    • Redis事务支持隔离性吗
    • Redis事务支持原子性吗
    • Redis支持回滚吗
    • 缓存雪崩
    • 缓存击穿
    • 缓存穿透
  • 入门笔记
    • 初始Redis
    • Redis常见命令
      • Redis 的数据结构
      • 通用命令
      • String 类型
      • redis 的 key 的格式
      • Hash类型
      • List 类型
      • Set类型
      • SortedSet 类型
    • redis的java客户端

一、面试题

以下面试题参考:
.html

Redis是什么

  • Redis是一个由c语言编写的,高性能非关系型数据库
  • 与传统的数据库不同的是,Redis的数据库是存在内存中的,读写速度非常快,广泛应用于缓存方向
  • Redis可以将数据写入磁盘中,保证数据的安全不丢失
  • Redis的操作是原子性的

Redis的优缺点

优点:

  • 基于内存:读写速度快
  • 支持多种数据结构:String、Hash、List、Set、ZSet
  • 支持持久化:支持RDB和AOF两种持久化机制,持久化功能可以有效地避免数据丢失问题
  • 支持事务:Redis的所有操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行
  • 支持主从复制:主节点会自动将数据同步到从节点,可以进行读写分离。
  • 单线程:Redis命令的处理是单线程的。Redis6.0引入了多线程,需要注意的是,多线程用于处理网络数据的读写和协议解析,Redis命令执行还是单线程的

缺点:

  • 对结构化查询的支持比较差
  • 容量受到物理内存的限制,不适合用作海量数据的高性能读写,使用的场景主要局限在较小数据量的操作
  • 较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂

Redis的应用场景

  • 缓存热点数据:缓解数据库压力
  • 计数器:利用 Redis 原子性的自增操作,可以实现计数器的功能,比如统计用户点赞数、用户访问数等。
  • 分布式锁:在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用 Redis 自带的 SETNX 命令实现分布式锁,除此之外,还可以使用官方提供的 RedLock 分布式锁实现。
  • 简单的消息队列:可以使用Redis自身的发布/订阅模式或者List来实现简单的消息队列,实现异步操作。
  • 限速器:可用于限制某个用户访问某个接口的频率,比如秒杀场景用于防止用户快速点击带来不必要的压力。
  • 好友关系:利用集合的一些命令,比如交集、并集、差集等,实现共同好友、共同爱好之类的功能。

Redis为什么这么快

  • 基于内存:Redis是使用内存存储,没有磁盘IO上的开销。数据存在内存中,读写速度快
  • IO多路复用模型:Redis 采用 IO 多路复用技术。Redis 使用单线程来轮询描述符,将数据库的操作都转换成了事件,不在网络I/O上浪费过多的时间
  • 高效的数据结构:Redis 每种数据类型底层都做了优化,目的就是为了追求更快的速度

IO多路复用:一种同步IO模型,实现一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出cpu。多路是指网络连接,复用指的是同一个线程

为什么不直接用Redis做数据库

虽然Redis非常快,但它还有一些限制,不能完全替代主数据库。

  • 事务处理:只支持简单的事务处理,对复杂的事务处理无能为力,比如跨多个键的事务处理
  • 数据持久化:Redis是内存数据库,数据存储在内存中,如果服务器崩溃或断电,数据可能丢失。虽然Redis提供了数据持久化机制,但有一些限制。
  • 数据结构:只支持一些简单的数据结构,比如字符串、列表、哈希表等。如果需要处理复杂的数据结构,比如关系型数据库中的表,那么Redis可能不是一个好的选择
  • 数据安全:Redis没有提供像主数据库那样的安全机制,比如用户认证、访问控制等等。

所以,使用Redis作为缓存是一种很好的方式,可以提高应用程序的性能,并减少数据库的负载。

Redis的常见数据结构


基本数据类型

  • String:是Redis中最简单的存储类型,有三类(普通字符串、整数型、浮点型),都是以字节数组形式存储,只不过编码方式不同,最大空间不能超过512m
  • Hash:类似于java中的hashMap,存储键值对
  • List:和java中的linkedlist类似,常用来存储有序可重复数据,比如说朋友圈的点赞列表,评论列表
  • Set:和java中hashset类似,常用来存储无序不可重复数据。提供了交集、并集等方法,对于实现共同好友、共同关注等功能特别方便。
  • SortedSet:有序Set,内部维护了一个score参数来实现。适用于排行榜和带权重的消息队列等场景。

特殊数据类型:

  • Bitmap:位图,可以认为是一个以位为单位数组,数组中的每个单元只能存0或者1,数组的下标在 Bitmap 中叫做偏移量。Bitmap的长度与集合中元素个数无关,而是与基数的上限有关。
  • Hyperlog:用来做基数统计的算法,其优点是,在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的、并且是很小的。典型的使用场景是统计独立访客。
  • Geo:主要用于存储地理位置信息,并对存储的信息进行操作,适用场景如定位、附近的人等

这里的基数指的是什么啊:集合中不重复的元素

Redis的持久化机制

持久化:把内存数据写到磁盘,防止服务器宕机导致数据库丢失。有两种数据持久化机制:

  • RDB:默认方式
    • 根据指定的规则定时将内存中的数据存储在磁盘上
    • 优点:速度快,使用单独的进程来进行持久化,主进程不会进行任何IO操作,保证了Redis的高性能
    • 缺点:无法做到实时持久化;存在老版本的Redis无法兼容新版本的RDB格式的问题
  • AOF:主流方式
    • 以独立日志的方式记录每次写命令
    • 优点:解决了数据持久化的实时性,默认情况下系统每30秒会执行一次同步操作
    • 缺点:速度慢

两种持久化机制应该如何选择

  • 如果数据不敏感,且可以从其他地方重新生成,可以关闭持久化
  • 如果数据比较重要,且能够承受几分钟的数据丢失,比如缓存等,只需要使用RDB即可
  • 如果是用做内存数据,要使用Redis的持久化,建议是RDB和AOF都开启

当RDB与AOF两种方式都开启时,Redis会优先使用AOF恢复数据,因为AOF保存的文件比RDB文件更完整。

Redis内存用完了会怎么办

  • Redis的写命令会返回错误信息(但是读命令是可以正常读的)
  • 可以配置内存淘汰机制,当Redis内存达到上线时会重刷掉旧的内容

Redis事务

Redis事务的原理:

  • 将一个事务范围内的若干命令发送给Redis,然后再让Redis依次执行这些命令

Redis事务的生命周期:

  • 使用MULTI开启一个事务
  • 在开启事务的时候,每次操作的命令将会被插入到一个队列中,此时这些命令不会被真的执行
  • 使用EXEC命令提交事务

Redis存在线程安全问题吗

从服务端层面来看:

  • 不需要任何同步机制,不会存在线程安全
  • Redis6.0增加的多线程只是用来处理网络IO事件的,对于指令的执行过程,仍然是主线程处理,所以不会存在安全问题

从客户端层面来看:

  • 有多个客户端同时执行多个指令的时候,无法保证原子性
  • 解决办法:对客户端访问的资源加锁、尽可能使用Redis中的原子指令、通过Lua来实现多个指令的操作

Redis事务支持隔离性吗

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

Redis事务支持原子性吗

Redis单条命令是原子性执行的,但事务不保证原子性。

原子性:一个事务中的多条命令,要么全部执行,要么全部不执行

Redis支持回滚吗

不支持回滚,事务中任意命令执行失败,其余命令仍然会被执行

缓存雪崩

缓存雪崩:

  • 大量数据在同一时间过期(失效)
  • 如果刚好此时有大量的请求,Redis无法命中就是能访问数据库
  • 数据库压力骤增,严重的会造成数据库宕机,这就是缓存雪崩的问题

    解决办法:
  • 将缓存的失效时间打散:在原有的失效时间基础上增加一个随机数,防止大量数据在同一时间内失效
  • 设置缓存不过期:使用后台服务来更新缓存数据,不设置过期

缓存击穿

缓存击穿:

  • 某个热点数据过期,此时大量的请求访问该热点数据
  • Redis无法命中就会直接访问数据路,数据库很容易被高并发的请求冲垮,这就是缓存击穿问题

    解决办法:
  • 互斥锁:保证同一时间只有一个业务线程请求缓存
  • 不给热点数据设置过期时间:可以通过程序在热点数据要过期时进行更新

缓存穿透

缓存穿透:

  • 当发生缓存雪崩和缓存击穿时,数据库中还是保存了要访问的数据的
  • 但是缓存穿透是指,用户访问的数据既不在缓存中,也不在数据库
  • 当有大量这样的请求来时,数据库压力剧增,这就是缓存穿透问题

    缓存穿透发生的原因
  • 业务误操作:缓存和数据库中的数据都被误删了
  • 黑客恶意攻击:故意访问大量不存在的业务数据

解决办法:

  • 限制非法请求
  • 设置空值或者默认值:在缓存数据中设置一些空值或者默认值,这样就不会访问数据库
  • 使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在

入门笔记

=3&spm_id_from=pageDriver&vd_source=4af69ca6d4c9233482138fb1c303b63b

初始Redis

  • sql是关系型数据库,nosql是非关系型数据库,两者的区别是:

  • Redis是键值数据库,NoSql数据库

  • Remote dictionary sever 远程词典服务器,是一个基于内存的键值型NOSQL数据库

  • 特征

    • 键值型: value支持多种数据结构,功能丰富
    • 单线程,每个命令具备原子性
    • 低延迟,速度快(这是因为他基于内存🍓、IO多路复用、良好的编码)
    • 支持数据的持久化(内存虽然快,但是一旦断电数据就消失了,所以需要数据持久化):定期将数据从内存持久化到硬盘
    • 支持主从集群(从节点可以备份主节点的数据,主从可以读写分离,提高效率)、分片集群(把数据拆分成多份)
    • 支持多语言客户端
  • 安装

  • 原作者根本就没有编写windows版本的,只要linux版本

Redis常见命令

Redis 的数据结构

最主要的是这八个,还有其他的

  • 官方文档中的命令介绍:/
  • redis在线练习:/

通用命令

  • KEYS pattern : 查看复合模板的所有key,因为模板的查询是模糊的,效率比较低,所以不建议在生产环境中使用
> keys *
1) "name"
2) "age"
  • DEL key : 指定删除一个key
> del age
(integer) 1
> keys *
1) "name"
  • EXISTS key:判断一个key是否存在
> exists age
(integer) 0
  • EXPIRE:给key设置一个有效期,有效期到了之后删除该key
  • TTL:查看一个key的有效时间。-1 代表永久有效、-2代表已失效
> expire age 10
(integer) 1
> ttl age
(integer) 6
> ttl age
(integer) 2

String 类型

字符串类型,是Redis中最简单的存储类型,有以下三类,都是以字节数组形式存储,只不过编码方式不同,最大空间不能超过512m

  • string:普通字符串
  • int:整数类型,可以自增自减
  • float:浮点类型,可以自增自减

    String 类型的常见命令:
  • SET
  • GET
  • MEST
  • MGET
  • INCR:让整型key自增1
  • INCREBY
  • INCRBYFLOAT
  • SETNX
  • SETEX
> incrbyfloat score 0.5
1.6
> incrbyfloat score 0.5
2.1

redis 的 key 的格式

redis中没有table的概念,如何区分不同类型的key呢?比如说要存储用户、商品信息到redis,有一个用户的id是1,商品的id也恰好是1

  • Redis中的key允许有多个单词形成层级关系,多个单词之间用:隔开
  • 项目名:类型:id
  • heima:user:1
  • heima:product:1

Hash类型

value是一个无序字典,类似于java中的hashMap

> hgetall heima:user:1
1) "name"
2) "gaoyi"
3) "age"
4) "25"

List 类型

和java中的linkedlist类似,常用来存储有序数据,比如说朋友圈的点赞列表,评论列表,有以下特征:

  • 有序
  • 可重复
  • 插入删除快
  • 查询速度一般

如何用list模拟一个栈:lpush lpop
如何用list模拟一个队列 lpush rpop
如何利用list模拟一个阻塞队列 blpop brpop

Set类型

和java中hashset类似,可以看做是一个value为null的hashmap,有以下特征

  • 无序
  • 不可重复
  • 查找快
  • 支持交集、并集、差集等功能

> sadd friends gao gai ta
(integer) 3
> smembers friends
1) "gai"
2) "ta"
3) "gao"
> scard friends
3
> sismember friends gao
(integer) 1

> sadd girlfriends lisa lusy gao
(integer) 3
> sinter friends girlfriends
1) "gao"
> sdiff friends girlfriends
1) "gai"
2) "ta"
> sunion friends girlfriends
1) "gai"
2) "gao"
3) "ta"
4) "lisa"
5) "lusy"

SortedSet 类型

  • 可排序的set集合,和java中的treeset有些类似,但是底层数据结构却差别很大。
  • SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序
  • 经常用来实现排行榜这样的功能
  • 底层实现是一个跳表(skiplist)加hash表,有以下特征:
    • 可排序
    • 不重复
    • 查询速度快

redis的java客户端

  • jedis:学习成本低,但是线程不安全,需要使用搭配线程池来使用
  • lettuce
  • redisson

更多推荐

【测开求职】面试题:Redis 吐血整理

本文发布于:2023-11-15 23:47:23,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1609919.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:面试题   Redis

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!