Redis概述 | 青训营笔记

62 阅读10分钟

Redis概述

  1. 什么是Redis?

    Redis是一个高性能的非关系型的键值对数据库,使用C编写实现的。与传统的数据库不同的是Redis是存在内存中的,所以读写速度非常快,每秒可以处理超过10万次的读写操作,这也是Redis常常被用作缓存的原因。

  2. Redis的优缺点?

    优点:

    • 读写性能好,读的速度可达110000次/s,写的速度可达81000次/s。
    • 支持数据持久化,有AOF和RDB两中持久化方式
    • 数据结构丰富,支持String、List、Set、Hash等结构
    • 支持事务,Redis所有的操作都是原子性的,并且还支持几个操作合并后的原子性执行,原子性指操作要么成功执行,要么失败不执行,不会执行一部分。
    • 支持主从复制,主机可以自动将数据同步到从机,进行读写分离。

    缺点:

    • 因为Redis是将数据存到内存中的,所以会受到内存大小的限制,不能用作海量数据的读写。
    • Redis不具备自动容错和恢复功能,主机或从机宕机会导致前端部分读写请求失败,需要重启机器或者手动切换前端的IP才能切换。
  3. Redis为什么常常用作缓存?相比于guava有什么优势?

    • 缓存的定义是访问速度比一般随机存取存储器快的一种高速存储器,而因为Redis是基于内存提供了高性能的数据存取功能,其比较显著的优势就是非常地快。
    • 缓存可以分为本地缓存或者分布式缓存,比较常用的guava缓存就是一种本地缓存,其主要特点是轻量并且快速,生命周期随着JVM的销毁而结束,缺点是在多实例的情况下,每个实例都要自己保存一份缓存,这样会导致缓存的一致性出现问题。
    • Redis则是分布式缓存,在多实例情况下,每个实例都共享一份缓存数据,缓存具备一致性。缺点是要保持Redis的高可用整体架构会比较复杂。
  4. Redis和Memcached的区别与共同点?

    相同点:

    • 两者的读写性能都比较高
    • 都是基于内存的数据库,通常被当作缓存使用
    • 都有过期策略
    • 都是基于C语言实现
    不同点RedisMemcached
    是否支持复制支持主从复制不支持复制
    key长度长度最大为 2GB长度最多为 250 个字节
    数据类型不仅支持key-value类型的数据,还支持hash、list、set、zset等数据等数据类型的数据仅支持key-value类型的数据
    数据持久化支持数据持久化,可以将数据保存到磁盘不支持数据持久化
    网络IO模型单线程的多路 IO 复用模型多线程的非阻塞IO模式
    集群原生支持cluster 模式集群无原生
  5. Redis是单线程还是多线程?Redis为什么这么快?

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

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

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

    • 运行在内存中,避免了大量的磁盘IO开销。
    • 数据结构简单
    • 使用多路IO复用技术
    • 单线程实现,单线程避免了线程切换、锁等造成的性能开销【6.0前】。
  6. Redis6.0之后为什么引入了多线程?

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

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

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

  7. Redis的数据类型有哪些?

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

    数据类型可以存储的值可进行的操作应用场景
    STRING字符串、整数、浮点数对整数或浮点数可以进行自增、自减操作 对字符串操作键值对缓存及常规计数: 微博数, 粉丝数
    LIST列表(内部使用双向列表实现)向列表两端添加元素,或者获得列表的某一个片段存储文章ID列表、存储评论列表等
    SET无序集合(内部使用值为空的散列表)增加/删除元素、获取集合中元素、取交集并集等等共同好友、共同关注等
    ZSET有序集合(内部使用散列表和跳表)添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名去重、获取排名前几的用户
    HASH包含键值对的无序散列表添加、获取、移除单个键值对 获取所有键值对 检查某个键是否存在常用于存储对象

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

    Hyperloglog: HyperLogLog 是一种用于统计基数的数据集合类型,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。HyperLogLog 的优点是,在输入元素的数量或者体积非常大时,计算基数所需的空间总是固定的、并且是很小的。缺点是 HyperLogLog 的统计规则是基于概率完成的,所以它给出的统计结果是有一定误差的,标准误算率是 0.81%。常见的应用场景:统计网站的UV。

    Geospatial: 主要用于存储地理位置信息,常用于定位附近的人,打车距离的计算等。

  8. Redis的底层数据结构有哪些?

    Redis的数据结构有简单动态字符串、链表、字典、跳跃表、整数集合、压缩列表等。

    • 简单动态字符串:大家都知道,Redis的底层是用C语言编写,但Redis并没有直接使用C语言传统的字符串表示,而是构建了一种名为简单动态字符串的抽象类型。
    • 链表:链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。链表是列表的底层实现之一。
    • 字典:字典,又称为符号表(symbol table)、关联数组(associativearray)或映射(map),是一种用于保存键值对(key-value pair)的抽象数据结构。字典在Redis中的应用相当广泛,比如Redis的数据库就是使用字典来作为底层实现的,对数据库的增、删、查、改操作也是构建在对字典的操作之上的。
    • 整数集合: 整数集合(intset)是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。
    • 压缩列表(ziplist) :压缩列表是Redis为了节约内存而开发的,是由一系列特殊编码的连续内存块组成的顺序型(sequential)数据结构。
    • 跳跃表(skiplist) :跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。跳跃表作是序集合键的底层实现之一。Redis只在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点。
  9. Redis的应用场景有哪些?

    • 缓存:Redis基于内存,读写速度非常快,并且有键过期功能和键淘汰策略,可以作为缓存使用。
    • 排行榜:Redis提供的有序集合可以很方便地实现排行榜。
    • 分布式锁:Redis的setnx功能来实现分布式的锁。
    • 社交功能:实现共同好友、共同关注等。
    • 计数器:通过String进行自增自减实现计数功能。
    • 消息队列:Redis提供了发布、订阅、阻塞队列等功能,可以实现一个简单的消息队列。
    • 注册中心:RPC的注册中心
    • 全局ID
  10. Redis是单线程的,如何提高CPU的利用率?

    可以在一个服务器上部署多个Redis实例,把他们当作不同的服务器使用。

  11. Redis与MySQL区别?

    数据库类型:MySQL是关系型数据库、Redis是键值对数据库。

    存储介质:MySQL数据存储在磁盘中,读写速度相对较慢;Redis的数据存储在内存中,读写速度快。

    事务支持:MySQL支持完整的ACID事务特性,支持多种隔离级别;Redis只支持部分ACID特性(单条命令具有原子性)。

    适用场景

    • Redis:高并发、高频率读写的场景。可以配合MySQL使用。
    • MySQL:一般的场景、需要事务支持的场景、需要持久化、复杂的查询(join之类的)等。
  12. Redis线程模型?

    • 多个socket套接字
    • IO多路复用程序
    • 文件事件分派器
    • 事件处理器(命令请求、命令回复、连接应答处理器)

    img

    多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。

    多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,然后程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。
    ​
    这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个客户端的网络IO连接请求(尽量减少网络 IO 的时间消耗)