Redis 面试

112 阅读8分钟

1.什么是Redis?

Redis是一个基于内存的高性能的非关系型的键值对数据库,使用C语言编写

2.Redis的优缺点?

  • 优点:

    • 读写性能好,读的速度可达11000次/s,写的速度可达81000次/s

    • 支持数据持久化,有AOF和RDB(默认)两种持久化方式

      • Redis 默认开启RDB持久化方式,在指定的时间间隔内,执行指定次数的写操作,则将内存中的数据写入到磁盘中。
      • AOF :Redis 默认不开启。它的出现是为了弥补RDB的不足(数据的不一致性),所以它采用日志的形式来记录每个写操作,并追加到文件中。Redis 重启的会根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
    • 数据结构丰富,支持string、list、set、hash

    • 支持事务,redis所有的操作都是原子性的,并且还支持几个操作合并后的原子性执行,原子性值操作要么成功执行,要么失败不执行,不会只执行一部分

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

  • 缺点:

    • 因为Redis是将数据存到内存的,索引会收到内存大小的限制,不能用作海量数据的读写
    • Redis不具备自动容错和恢复功能,主机或从机宕机会导致前端部分读写请求失败,需要重启机器或者手动切换前端的IP才可以

3.Redis和Memcached的区别和共同点?

相同点:

  • 两者的读写性能都比较高
  • 都是基于内存的数据库,通常被当做缓存使用
  • 都有过期策略
  • 都是基于C语言实现的

不同点:

不同点RedisMemcache
是否支持复制支持主从复制不支持复制
key长度长度最大为2GB长度为250个字节
数据类型不仅支持key-value类型的数据,还支持hash、list、set、zset等数据类型的数据仅支持key-value类型的数据
数据持久化支持,将数据保存到磁盘不支持
网络IO模型单线程的多路IO复用模型多线程的非常阻塞IO模式
集群原生支持cluster模式集群无原生

4.❤Redis是单线程还是多线程?Redis为什么这么快?

oppo二面

Redis6.0之前是单线程的,为什么Redis6.0之前采用单线程而不是采用多线程

简单来说,就是Redis官方认为没有必要,单线程的Redis的瓶颈通常在CPU的IO,而在使用Redis时几乎不存在CPU成为瓶颈的情况。使用Redis主要的瓶颈在内存和网络,并且使用单线程也存在一些优点,比如系统的复杂度较低(实现简单并高效),可为维护性较高,避免了并发读写所带来的的一系列问题。

Redis为什么这么快主要有以下几个原因

  • 运行在内存中
  • 数据结构简单
  • 使用多路IO复用技术
  • 单线程实现,单线程避免了线程切换、锁造成的性能开销

5.Redis6.0之后为什么引入了多线程?

前面也说了Redis的瓶颈在内存和网路,Redis6.0引入多线程主要是为了解决网络IO读写这个瓶颈,执行命令还是单线程执行,索引也不存在线程安全问题。

Redis6.0默认是否开启了多线程呢?

默认是没有开启的,如需开启,需要修改配置文件redis.conf:io-threads-do-reads no,no改为yes

6.❤Redis的数据类型有哪些?

需要牢记五大数据类型及其应用场景

Redis的常见的数据类型String、Hash、Set、List、ZSet。还有三种不那么常见的数据类型:Bitmap、HyperLogLog、Geospatial

数据类型可以存储的值可进行的操作应用场景
string字符串、整数、浮点数对整数或浮点数可以进行自增、自减键值对缓存及常规技术
list列表(内部使用双向列表实现)向列表两端添加元素,或者获的列表的某一个片段存储ID列表、消息队列
set无序集合(内部使用值为空的散列表)增加/删除/获取元素,去交集并集共同好友,共同关注(使用sinter命令)等
zset有序集合(内部使用列表和跳表)添加、获取、删除元素、排名无序排行榜,延时队列
hash包含键值对的散列添加、获取、移除单个键值对常用于存储对象,比如购物车

bitmap:位图,是一个以位为单位的数组,数组中只能1或0,数组的下标叫偏移量。bitmap实现统计功能,更省空间。面试过程中常问的的布隆过滤器就用到这种数据结构,布隆过滤器可以判断出哪些数据一定不在数据库中,所以常用来解决Redis缓存穿透问题

hyperloglog: *['haɪpər]*是一种用于统计基数 的数据集合类型,

**Geospatial:**ˌ/dʒiːəʊˈspeɪʃəl/ 主要用于存储地理位置信息,常用于定位附近的人,打车距离的计算等。

7.❤Redis的数据结构有哪些?

小红书

  • 简单动态字符串:Redis的底层是用C语言编写,但Redis并没有直接使用C语言传统的字符串表示,而是构建了一种名为简单动态字符串的抽象类型。

  • 链表:链表提供了高效的节点重排能力,以及顺序性的结点访问方式,并且可以通过增删节点来灵活的调整链表的长度。链表是列表的底层实现之一

  • 字典:又称符号表、关联数组或映射

  • 整数集合:整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。

  • 压缩列表(ziplist) :压缩列表是Redis为了节约内存开发的,是由一系列特殊编码的连续内存组成的顺序型数据结构。

  • 对象:上面的是Redis的底层数据结构,但Redis并没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建了一个对象系统,这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型的的对象

    为什么不直接使用这些底层数据结构,而是要创建对象系统。对象系统主要有以下优点:

    • 通过五种不同类型的对象,Redis可以在执行命令之前,根据对象的类型来判断一个对象是否可以给定的命令

    • 我们可以针对不同的使用场景,为对象设置多种不同的数据结构实现,从而优化对象在不同场景下的使用效率

    • 实现了基于引用计数的内存回收机制,当程序不再使用某个对象的时候,这个对象所占用的内存就会被自动释放,

    • 还通过引用计数实现了对象共享机制,这一级至可以再适当的条件下,通过让多个数据库键共享一个对象来节约内存

      img

  • 跳跃表面试常问):跳跃表是一种有序数据结构,它通过在每个节点维持多个指向其他结点的指针,从而达到快速访问节点的目的。平均O(logN)、最坏O(N)复杂度的结点查找,还可以通过顺序性操作来批量处理节点。跳跃表是有序集合键的底层实现之一 ,跳跃表还在集群节点中用作内部数据结构。跳跃表本质是一种空间换时间的策略,是一种可以进行二分查找的有序链表,跳跃表在原有的有序链表上增加了多级索引,通过索引来实现快速查询。跳表不仅能提高搜索性能,同时可以提高插入和删除操作的性能

    img

    建立一级索引:

    img

    对于理想的跳跃表,每先上一层索引节点数量都是下一层的1/2,跳跃表为O(logN),空间复杂度为O(N),虽然是空间换时间的策略,这里距离存储的知识数字,如果是存储比较大的对象,浪费的空间就不值一提了,因为索引节点只需要存储关键值和几个指针,并不需要存储对象

跳跃表相比于红黑树的优点(redis为什么用跳跃表而不是红黑树):

  • 内存占用更少,自定义参数化决定使用多少内存、查询性能至少不比红黑树差
  • 简单更容易实现和维护

最后,说下Redis中的跳跃表和普通的跳跃表有什么区别?

  • Redis中的跳跃表分数(score)允许重复,即跳跃表的key允许重复。如果分数重复,还需要根据数据内容来进行字典排序。普通的跳跃表是不支持的
  • 第一层链表不是一个单向链表,而是一个双向链表。这是为了方便一倒序方式获取一个范围内的元素。
  • 在Redis的跳跃表中可以很方便地计算出每个元素的排名

其他知识点

穿透、击穿、雪崩 + 一致性策略 + 缓存优化 见此文 缓存设计常见问题