面试八股文-Redis数据库

Redis数据库

Redis是什么?

Redis是一个C语言编写的开源的非关系型数据库,可以用来存储键值对数据
它有持久化机制,可以实现主从同步, 所以有时被用来做分布式锁
它的数据被存放在内存中,读写很快,经常被用来做缓存

Redis与Memcached的区别有哪些?

  • Redis有持久化机制; Memecached没有
  • Redis有5种数据类型; Memcached只有String这一种类型;
  • Redis原生支持集群; Memcached不支持
  • Redis是单线程; Memcached是多线程

关系型数据库 与 非关系型数据库的区别

关系型数据库的优势:支持复杂查询 和 事务
非关系型数据库的优势:性能 和 灵活性
两者是互补的,一方的优势就是另一方的劣势

为什么要使用Redis?

项目中一般使用Redis作为缓存,可以保证高性能和高并发
当请求第一次访问MySQL数据库,要从硬盘上读取数据,如果把这些数据通过Redis缓存到内存中,这样下次相同的请求就能直接从内存中获取,速度会快很多

Redis常用的数据类型

  • string: 字符串

    • 存放一些简单的k-v键值对
    • 使用场景: b站的关注数,粉丝数
  • list: 列表

    • 用一个双链表实现的列表
    • 使用场景: b站的关注列表,粉丝列表,可以用lrange做出那种下拉不断分页的效果
  • hash: 哈希表

    • 存放一些对象信息
    • 使用场景: 存用户信息,商品信息
  • set: 集合

    • 存放一些不重复数据
    • 使用场景: 像微博这类社交应用,用集合存放每个人的好友,sinter求交集获取共同好友
  • zset: 有序集合

    • 根据权重参数有序地存放不重复数据
    • 使用场景: 虎牙直播间的弹幕消息排行榜

为什么不用dict做缓存,而选用Redis?

缓存分为 本地缓存 和 分布式缓存

dict变量只能做 本地缓存,它的生命周期随着变量离开作用域就结束了,而且在多实例的情况下,dict变量的值难以保证一致

redis支持分布式缓存,在多实例的情况下,各个实例共享同一份缓存数据

除此之外,Redis可以给值设置一个过期时间,这是非常实用的,比如图形和短信验证码都是有时间限制的,

如果用dict还要自己判断过期,这样会严重影响项目的性能

Redis的线程模型? 为什么能支持高并发?

Redis是单线程的,它采用IO多路复用机制同时监听多个socket,并且因为都是在内存中操作,处理得很快,能够支持高并发

考虑到RDB文件的Fork,一些定时任务的处理,Redis其实也可以说是多进程的,但是它对于数据的处理,始终是单线程

Redis为什么用单线程而不用多线程?

Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是网络的带宽或者内存的大小。

Redis处理命令的流程

Redis基于Reactor模式,开发了自己的文件事件处理器,它会根据套接字的accept,read等操作关联不同的事件处理器,当有新的Redis客户端发起连接,或者已连接的客户端发来数据,就会触发相应的事件处理器,执行不同的命令

Redis的过期键清除策略

Redis过期键清除策略是定期删除+惰性删除。

  • 定期删除: 每隔一段时间就抽取一些设置了过期时间的key,检查是否过期,若过期就删除.

  • 惰性删除: 使用的时候,发现key过期了再删除

定期和惰性能保证删除过期数据吗?

不能,如果定期删除没抽取到该过期数据,后面也一直没获取过这个数据,那么它可能一直占据内存
为了解决这个问题,redis允许我们在配置文件中指定内存淘汰策略maxmemory_policy,默认是不开启
一般可以设为lru,淘汰最近最少使用的数据

Redis的持久化机制

  • RDB: 记录的是某一时刻Redis存放在内存中的全部数据
    • 优点: 恢复数据较快,可以通过fork子进程来完成持久化操作, 不会影响Redis服务端执行命令
    • 缺点: 数据安全性较低,RDB是每隔一段时间进行持久化,如果系统宕机会导致这段时间的数据丢失
  • AOF: 记录的是执行过的写命令
    • 优点: 数据安全,默认设置是每秒钟把缓存中的写命令刷到磁盘文件,这样出现故障最多丢失一秒的数据
    • 缺点: 要通过执行命令恢复数据,所以速度较慢

AOF文件越来越大怎么处理?

Redis可以在AOF文件体积变得过大时,自动地在后台Fork一个子进程,专门对AOF进行重写。本质上就是合并相同key的操作,用后面的值覆盖前面的值。

在重写的过程中执行的命令会被记录在AOF重写缓冲区,等到新的AOF文件创建完成,Redis就会将重写缓冲区的内容追加到新的AOF文件中,再用新的AOF替换原来的文件

Redis主从同步机制

主库和从库第一次连接时,会先进行全量同步

  • 从库先发送sync命令,主库收到后调用save命令生成rdb文件,并记录 此期间的写命令 到 缓冲区
  • 主库把rdb文件发给从库,从库收到后, 读取rdb文件的内容到内存中
  • 主库还会继续把缓冲区的写命令发给从库,从库收到后执行这些写命令

全量同步结束后,进行增量同步,主库每执行一个写命令就向从库发送相同的命令,从库接收并执行该命令

Redis主从可以自动切换吗?

不能,但Redis提供了现成的解决方案,这就是哨兵机制,由哨兵来检测各个Redis服务是否正常,为了避免哨兵单点故障,哨兵也需要多机部署,如果master挂掉,哨兵Leader会在slave节点中选择一个作为新的master.

如果数据太大,Redis存不下怎么办?

使用集群模式,将数据分片,根据一致性hash算法 将不同的key 路由到 不同的节点

一致性哈希算法

一致性哈希算法可以解决服务器数量发生改变时,所有的路由被打乱,导致服务器缓存在同时失效的问题。它把节点和数据,以相同的hash函数映射到同一个hash环上,数据要在hash环上顺时针查找距其最近的节点来存放,这样当新增一个节点时,最多只会影响后面一个节点的数据.

缓存雪崩

原因: 大量缓存key同时失效,导致大量请求直接访问数据库
解决: 设置随机的过期时间

缓存穿透

原因: 大量缓存key查询不到,导致大量请求直接访问数据库,很可能是黑客攻击
解决: 对于数据库没查到的数据也添加到缓存,设置一个较短的过期时间

缓存击穿

原因: 非常热点的缓存key过期,导致大量请求直接访问数据库
解决: 热点的缓存key设为永不过期; 使用分布式锁,只让获取到锁的线程 读取数据库并更新缓存

Redis如何实现分布式锁?

  • 使用 set dlock uuid EX 过期秒数 NX来实现加锁
  • 通过 get dlock 判断它是不是刚刚自己设置的uuid,若是,说明加锁成功,否则失败
  • 释放锁时,也通过get dlock判断它是不是刚刚自己设置的uuid,若是才执行del

MySQL,Redis的应用场景及优缺点

MySQL一般作为主存储,Redis作为缓存

MySQL: 可以存放复杂的关系型数据,数据主要存储在磁盘,容量大,但读写慢

Redis: 只能存放键值对数据,数据主要存储在内存,读写快

服务端性能优化措施

  • 数据结构和算法优化
  • 数据库: 消除慢查询语句,为某些常用作搜索条件的字段建立索引,删除不必要的索引
  • 缓存: 使用redis这种内存数据库缓存MySQL数据库中查询的数据,缓解MySQL压力
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值