Redis面试题(3)

0    209    1

Tags:

👉 本文共约22899个字,系统预计阅读时间或需87分钟。

一般来讲在面试当中, 关于Redis相关的面试题频率出现比较高的几个关键词是适合哪些场景、数据结构、hash实现原理和如何扩容、如何做持久化、关系型数据库和非关系数据库对比等等。 把这几个点问完基本也差不多10~20分钟了(一般一轮面试1小时左右), 基本这些可以让面试官对你的Redis知识有一定的了解了。

Redis基础知识

什么是 Redis, 有哪些优缺点?

出现概率: ★★★★

Redis是一个非关系性数据库, 开源的、使用C语言编写、支持网络、可基于内存亦可持久化的日志型、key-value(键值对)数据库,是目前分布式架构中不可或缺的一环。

Redis服务器程序是单进程模型,也就是在一台服务器上可以同时启动多个Redis进程,而Redis的实际处理速度则完全依靠于主进程的的执行效率。若在服务器上只运行一个Redis进程,当多个客户端同时访问时,服务器的处理能力会有一定程度的下降,若在同一台服务器上开启多个Redis进程,Redis在提高并发处理能力的同时会给服务器的CPU造成很大压力。也就是说,在实际生产环境中,需要根据实际的需求来决定开启多少个Redis进程。若对高并发要求更高一些,可能会考虑在同一台服务器上开启多个进程。若CPU资源比较紧张,采用单进程即可。

Redis优点:

1)、性能极高, 读写性能优异,从内存当中进行IO读写速度快。

2)、支持数据的持久化(支持AOF和RDB两种持久化方式),对数据的更新采用Copy-on-write技术(写拷贝),可以异步的保存在磁盘上

由于Redis的数据都存放在内存中,如果没有配置持久化,redis重启后数据就全丢失了,于是需要开启redis的持久化功能,将数据保存到磁 盘上,当redis重启后,可以从磁盘中恢复数据。

redis提供两种方式进行持久化,一种是RDB持久化:指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

还有一种是AOF持久化:以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。

3)、支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。

4)、数据结构丰富:除了支持string类型的value外还支持string、hash、set、sortedset、list等数据结构。

5)、原子性:多个操作通过MULTI和EXEC指令支持事务

Redis缺点:

1)、主从同步,如果主机宕机,宕机前有一部分数据没有同步到从机,会导致数据不一致。

2)、主从同步,数据同步会有延迟。

3)、读写分离,主机写的负载量太大,也会导致主机的宕机

4)、数据库容量受到物理内存的限制,不能用作海量数据的高性能读写

redis-最适合的场景-可以简单的说说吗

出现概率: ★★★★

1、会话缓存(Session Cache)最常用的一种使用Redis的情景是会话缓存(session cache), Redis缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。

2、排行榜/计数器

Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。

3、发布/订阅

Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建立聊天系统!

4、缓存热数据

可以缓存一些高频读, 低频写的内容, 比如app首页一些设置等。

5、利用BitMap统计用户签到、统计活跃用户、用户在线状态等

Redis从2.2.0版本开始新增了setbit,getbit,bitcount等几个bitmap相关命令。虽然是新命令,但是并没有新增新的数据类型,因为setbit等命令只不过是在set上的扩展。

可以利用BitMap统计用户签到、统计活跃用户、用户在线状态

Redis面试题(3)

6、限速,接口访问频率限制:比如发送短信验证码的接口,通常为了防止别人恶意频刷,会限制用户每分钟获取验证码的频率,例如一分钟不能超过 5 次。

假设用于数据量上亿的场景下,例如几亿用户系统的签到,去重登录次数统计,某用户是否在线状态等等。腾讯10亿用户,要几个毫秒内查询到某个用户是否在线,能怎么做?

千万别说给每个用户建立一个key,然后挨个记(你可以算一下需要的内存会很恐怖,而且这种类似的需求很多。这里要用到位操作——使用setbit、getbit、bitcount命令。原理是:

redis内构建一个足够长的数组,每个数组元素只能是0和1两个值,然后这个数组的下标index用来表示用户id(必须是数字哈),那么很显然,这个几亿长的大数组就能通过下标和元素值(0和1)来构建一个记忆系统。

Redis key name 约定

Redis 数据结构

keysign:20220405sign:20220405sign:20220405 ...
offset (UserId)100010011002
value011
status未签到已签到已签到

使用经验

这里需要注意的是Redis中字符串限制最大为512MB,所以位图中最大可以设置2^32个不同的位(42.9亿个)。图位的最小单位是比特(bit),每个bit的值只能是0或1。 同时注意setbit时的偏移量,当偏移量很大时,可能会有较大耗时。 位图不是绝对的好,有时可能更浪费空间。

redis-相比-memcached-有哪些优势

出现概率: ★★★

如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:

1 、数据支持类型 Memcache 对数据类型支持相对简单。Redis 有复杂的数据类型。Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

2 、Redis支持数据的备份,即master-slave模式的数据备份。

3 、存储方式 Memecache 把数据全部存在内存之中, 断电后会挂掉, 数据不能超过内存大小。Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

一个字符串类型的值能存储最大容量是多少

Redis中字符串限制最大为512MB

redis-读写分离

出现概率: ★★★

读取请求QPS(Queries Per Second)压力较大的服务, 可以采用Redis读写分离,可以提供高可用、高性能、灵活的读写分离服务,满足热点数据集中及高并发读取的业务需求,最大化地节约运维成本。

读写分离版采取链式复制架构,可以通过扩展只读实例个数使整体实例性能呈线性增长,同时基于源码层面对Redis复制流程的定制优化,可以最大程度地提升线性复制的系统稳定性,充分利用每一个只读节点的物理资源。

Redis面试题(3)

由于数据同步至只读节点存在一定延迟,且采用链式复制,只读节点数越多,靠近链路末端的只读节点数据延迟越大,因此选用此架构时,业务需要能接受一定程度的脏数据。如果对数据一致性要求较高,推荐选用集群架构。

你知道怎么用redis实现实现分布式锁

出现概率: ★★★★

Redis 官方站提出了一种权威的基于 Redis 实现分布式锁的方式名叫Redlock,此种方式比原先的单节点的方法更安全。它可以保证以下特性:

安全特性:互斥访问,即永远只有一个client能拿到锁

避免死锁:最终 client 都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的 client crash 了或者出现了网络分区

容错性:只要大部分 Redis 节点存活就可以正常提供服务

Redis数据结构

Redis的数据类型有哪些?

出现概率: ★★★★★

这个在面试的过程出现的概率特别高了。

Redis 支持五种常用的数据类型:string( 字符串),hash( 哈希), list( 列表), set( 集合) 及 zsetsorted set:有序集合)。

Redis面试题(3)

redis 的基本数据结构对应的底层实现如下图所示:

Redis面试题(3)

1)、Redis 的字符串是动态字符串,是可以修改的字符串,内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配,如图所示:

len 是当前字符串实际长度,capacity 是为字符串分配的可用空间,当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次只会多扩 1M 的空间。字符串最大长度为 512M。

Redis面试题(3)

2)、hash

Redis Hash通过分桶的方式解决 hash 冲突。它是无序字典。内部实现结构是同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。第一维是数组,第二维是链表。数组中存储的是第二维链表的第一个元素的指针。

Redis面试题(3)

3)、list

Redis 的列表相当于 Java 语言中的 LinkedList,注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n)。

list的特点是:

  • 有序
  • 可以重复
  • 右边进左边出或者左边进右边出,则列表可以充当队列
  • 左边进左边出或者右边进右边出,则列表可以充当栈

Redis面试题(3)

4)、set

set和字典非常类似,其内部实现就是上述的hashTable的特殊实现,与字典不同的地方有两点:

  • 只关注key值,所有的value都是NULL。
  • 在新增数据时会进行去重。

Redis面试题(3)

5)、zsetsorted set

zset是Redis非常有特色的数据结构,它是基于Set并提供排序的有序集合。其中最为重要的特点就是支持通过score的权重来指定权重。一些排行榜、延迟任务比如指定1小时后执行, 就是使用这个数据结构实现的。

Redis面试题(3)

6)、拓展篇

如果你说你还知道一些其他的几种数据结构比如: HyperLogLog、Geo、Pub/Sub、Redis Module,BloomFilter,RedisSearch,Redis-ML,面试官得眼睛就开始发亮了。

Redis5.0带来了Stream类型。从字面上看是流类型,但其实从功能上看,应该是Redis对消息队列(MQ,Message Queue)的完善实现。用过Redis做消息队列的都了解,基于Reids的消息队列实现有很多种,例如:

  • PUB/SUB,订阅/发布模式
  • 基于List的 LPUSH+BRPOP 的实现
  • 基于Sorted-Set的实现

Redis Stream的结构如图所示,它有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的ID和对应的内容。消息是持久化的,Redis重启后,内容还在。

Redis面试题(3)

hash如何实现o-1-的查询和设置速度-以及扩容原理

出现概率: ★★★★★

Redis Hash通过分桶的方式解决 hash 冲突。它是无序字典。内部实现结构是同样的数组 + 链表二维结构。第一维 hash 的数组位置碰撞时,就会将碰撞的元素使用链表串接起来。第一维是数组,第二维是链表。数组中存储的是第二维链表的第一个元素的指针。

因为是通过数组取模的方式, 可以实现O(1)的查询和设置速度。

Redis面试题(3)

不过如果概率多时, 链表长度过长时,查询时间复杂度会降低到O(n)。这个需要进行扩容了。

大字典的扩容是非常耗时间的,需要重新申请新的数组,正常情况下,当 hash 表中元素的个数等于第一维数组的长度时,就会开始扩容,扩容的新数组是原数组大小的 2 倍,然后将旧字典所有链表中的元素重新挂接到新的数组下面,这是一个 O(n)级别的操作,Redis 使用渐进式 rehash 扩容,分多次来慢慢的将旧数组中的键值对rehash到新数组的操作就称之为渐进式rehash。渐进式rehash可以避免了集中式rehash带来的庞大计算量,在渐进式rehash过程中,因为还可能会有新的键值对存进来,此时Redis的做法是新添加的键值对统一放入ht[1]中,这样就确保了ht[0]键值对的数量只会减少,当执行rehash操作时需要执行查询操作,此时会先查询ht[0],查找不到结果再到ht[1]中查询。

说说-redis-哈希槽的概念

出现概率: ★★★

本人提供Oracle(OCP、OCM)、MySQL(OCP)、PostgreSQL(PGCA、PGCE、PGCM)等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!
Redis面试题(3)后续精彩内容已被小麦苗无情隐藏,请输入验证码解锁本站所有文章!
验证码:
请先关注本站微信公众号,然后回复“验证码”,获取验证码。在微信里搜索“DB宝”或者“www_xmmup_com”或者微信扫描右侧二维码都可以关注本站微信公众号。

标签:

Avatar photo

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复

嘿,我是小麦,需要帮助随时找我哦。
  • 18509239930
  • 个人微信

  • DB宝
  • 个人邮箱
  • 点击加入QQ群
  • 个人微店

  • 回到顶部