面向面试知识-Redis

面向面试知识-Redis

什么是Redis

运行于内存的基于key-value的非关系型数据库。

一款开源的内存数据结构存储,用作数据库、缓存、消息代理等。(可以基于Redis实现分布式锁、以及消息队列)
发布订阅??

对数据类型的操作都是原子性的,因为执行命令由单线程负责,不存在并发竞争的问题。
除此之外,Redis还支持:

Redis与Memcached的区别?

Redis和Memcached的共同点:

  1. 都是基于内存的数据库,性能都很高,一般可以用做缓存;
  2. 都有过期策略。

Redis和Memcached的区别:

  • Redis支持的数据类型更加丰富(String、Hash、Set、List、Zset);而Memcached只支持最简单的key-value数据类型;
  • Redis支持数据的持久化,如何持久化??,可以将内存中的数据保持在磁盘中,重启时可以再次加载使用;而Memcached没有持久化功能;
  • Redis原生支持集群;
  • Redis支持订阅模型、Lua脚本、事务等功能,而Memcached不支持。

为什么使用Redis作为MySQL的缓存

主要是因为高性能和高并发

  1. Redis具备高性能
    运行在内存的key-value缓存,读取速度快。
    面向面试知识-Redis_第1张图片
    但是需要一定的方法解决Redis和MySQL数据库数据一致性的问题。
  2. Redis具备高并发
    单台设备的Redis的QPS(Query Per Second),是MySQL的10倍,Redis单机的QPS能轻松破10w,而MySQL单机的QPS很难破1W。
    因此可以考虑把数据库的部分数据转移到缓存中,这样会直接到缓存而不用经过数据库。

Redis的数据类型

类型类型:存储的值:结构的读写能力;

String字符串;缓存对象、常规计数、分布式锁、共享session信息等;
Hash哈希;缓存对象、购物车等??
List列表;消息队列(有两个问题①生产者需要自行实现全局唯一;②不能以消费组形式消费数据等;);
Set集合;聚合计算(并集、交集、差集)场景,比如点赞、共同关注、==抽奖活动,为嘛?==等
Zset有序集合;排序场景,比如排行榜、电话和姓名排序等。

Redis常见数据类型:
面向面试知识-Redis_第2张图片
数据类型:存储的值:结构的读写能力
面向面试知识-Redis_第3张图片
Redis各数据类型的数据结构实现:
面向面试知识-Redis_第4张图片

  1. String类型内部实现:
    主要是SDS,Simple Dynamic String,简单动态字符串。
  • SDS不仅可以保存文本数据,还可以保存二进制数据。
  • SDS获取字符串长度的时间复杂度为O(1)。
  • Redis的SDS API是安全的,拼接字符串不会造成缓冲区溢出。
  1. List类型内部实现:
    底层数据结构是由双向链表或压缩列表实现的:
  • if 列表元素个数小于512,每个item的值都小于64字节,Redis会使用List类型的底层;
  • else 使用双向链表;
    在Redis3.2之后,List数据类型的底层DS只由quickList实现。
  1. Hash类型内部实现:
    压缩列表或者哈希表
  • if 列表元素个数小于512,且所有值小于64字节,用压缩列表;
  • else 使用Hash表;
    Redis 7.0之后只由quickList实现
  1. Set类型内部实现:
    Hash表或者整数集合实现
  • if 集合中的元素都是整数,且元素个数小于512,使用整数集合;
  • else 使用哈希表;
  1. Zset类型内部实现
    压缩列表或者跳表:
  • if 有序集合的元素个数小于128个,且所有元素的值小于64个字节时,使用压缩列表;
  • else 使用跳表;
    Redis7.0之后使用listpack实现。

Redis的线程模型

Redis是单线程吗?

在处理一系列请求时,即接受客户端请求,解析请求,进行数据读写等操作,返回数据给客服端的过程,是单线程;
但是Redis程序并不是单线程的,Redis在启动的时候,会启动后台线程(BIO)。

  • Redis在2.6版本加了两个后台线程,分别处理关闭文件、AOF刷盘两个任务;
  • Redis 4.0之后,新增了一个后台线程,用来异步释放Redis内存,也就是lazyfree线程。
    详细内容见Redis 常见面试题
    之所以 Redis 为「关闭文件、AOF 刷盘、释放内存」这些任务创建单独的线程来处理,是因为这些任务的操作都是很耗时的,如果把这些任务都放在主线程来处理,那么 Redis 主线程就很容易发生阻塞,这样就无法处理后续的请求了。
    面向面试知识-Redis_第5张图片
    此图太大了,内容有点多,慢慢看一下;
    面向面试知识-Redis_第6张图片

为什么Redis采用单线程都能这么快?

  1. 运行在内存;
  2. 非多线程,避免了多线程竞争,免去了线程切换等的资源消耗;
  3. 采用I/O多路复用处理大量的客户端Socket请求;

Redis在6.0之后引入了多线程,但是主要面向I/O,采用了多个I/O线程来处理网络请求,因为随着网络硬件的性能提升,Redis的性能瓶颈有时会出现在网络I/O的处理上。

Redis持久化

Redis如何实现数据不丢失

Redis运行在内存,当重启或者崩溃,内存中的数据会丢失,因此需要将数据保存至磁盘实现数据的持久化,在Redis重启后重新恢复保存在磁盘中的数据,避免数据丢失。
三种持久化方式:

  • AOF日志:每执行一条写操作,就将该命令以追加的方式写入一个特定文件中。
  • RDB快照:将某一时刻的内存数据,以二进制的方式写入磁盘。
  • 混合持久化方式:集成了AOF和RDB的优点。

AOF日志是如何实现的?

AOF,Append only File(追加文件)
记录写操作命令到一个文件中,然后Redis重启时,读取文件记录的命令,并逐一执行命令,进行数据恢复。
面向面试知识-Redis_第7张图片
为什么先执行命令再保存到文件?

  • 避免额外的检查开销:防止保存完执行过程发现语法错误等;
  • 不会阻塞写命令的执行:;
    可能的风险:
  • 数据可能会丢失:两个过程,如果写文件过程中,服务器宕机,那么数据就会有丢失的风险;
  • 可能阻塞其他操作:因为AOF日志是需要主线程执行的;
AOF的写回策略有哪些?

面向面试知识-Redis_第8张图片
内核缓冲区的数据何时写入硬盘?

  • Always,
  • Everysec,
  • No,
    面向面试知识-Redis_第9张图片
    AOF文件过大时,会出发AOF重写机制。即去除冗余操作,精简文件内容。
    面向面试知识-Redis_第10张图片

RDB是如何实现的?

RDB,Redis DataBase,内存快照。

上两部分见参考:Redis 如何实现数据不丢失?
RDB的优点是:数据恢复速度快,但是快照的时机把握是一个比较难的问题;
AOF的优点是:丢失数据少,但是恢复慢;

混合持久化

发生在AOF日志重写过程。
使用混合持久化的AOF文件,前半部分是RDB格式的全量数据,后半部分是AOF格式的增量数据。
面向面试知识-Redis_第11张图片
优点:

  • 前半部分是RDB数据,所以加载速度快;
  • 后半部分是AOF数据,加载完RDB数据,再加载AOF,所以数据的完整性较好,丢失的数据少。
    缺点:
  • AOF文件中加入RDB文件,可读性变差;
  • 兼容性差,不能用于Redis4.0之前的版本;

Redis集群

主从复制

面向面试知识-Redis_第12张图片
主从服务器的命令复制是异步进行的。无法实现强一致性,数据不一致在所难免。

哨兵模式

面向面试知识-Redis_第13张图片
主从复制模式有一个问题,当主节点宕机时,需要手动恢复。为了自动恢复,Redis增加了哨兵模式,因为哨兵模式可以监控主从服务器,且提供主从节点故障转移功能

切片集群模式

当Redis缓存数据量大到一台服务器无法缓存时,就需要使用Redis切片集群
使用哈希槽的方案,

Redis的内存淘汰策略

Redis使用的过期删除测试是惰性删除+定期删除

  • 惰性删除:只有被访问时,才会检查过期时间,若过期则删除。问题:如果一直不被访问,就一直无法删除。面向面试知识-Redis_第14张图片

  • 定期删除:每过一段时间,随机从数据库中取出一定数量的key值进行检查,删除过期的key。面向面试知识-Redis_第15张图片

  • redis的定期删除:如上图
    缺点是无法准确的设定删除执行时长和频率。

持久化时,对过期键的处理

RDB:
AOF:

Redis如何保证数据一致性

Redis如何解决数据一致性问题?

先更新数据库,再更新缓存
先更新缓存,再更新数据库
先删除缓存,再更新数据库
先更新数据库,再删除缓存

延迟双删

如何解决缓存击穿、穿透、雪崩等问题?

缓存击穿

缓存穿透

缓存雪崩

你可能感兴趣的:(Lottery抽奖系统,Redis,redis,缓存,数据库)