梁恒嘉的技术专栏 全栈之路

Redis面试知识整理

2022-09-24
NanKe

主要记载与Redis相关的面试知识,包括Redis的线程模型,Redis为什么是单线程,速度还快,Redis 持久化,Redis事务,Redis的主从复制,Redis哨兵机制,Redis过期策略,Redis中的缓存穿透,缓存击穿,缓存雪崩

一、Redis的线程模型

在Redis6.x之前的Redis是单线程的,在处理网络客户端连接与数据的读写操作的时候都是由一个线程操作

在Redis6.x之后的Redis中,在处理网络客户端连接的时候使用多线程进行处理,但是在进行数据的读写操作时依旧是单线程进行操作

二、Redis为什么是单线程,速度还快

  1. 数据存储在内存,CPU不是它的瓶颈(CPU由寄存器,处理器,运算器,时钟组成,它的工作主要是处理计算机中的指令以及软件中的数据。我们在处理软件中数据的时候,一般是将软件中的数据先存储磁盘当中,当我们需要数据的时候会将磁盘中的数据加载到内存中进行处理,但是Redis则是将数据直接存储在内存中,与常规相比,少了从磁盘加载数据的操作),内存的大小是他的瓶颈
  2. Redis的数据结构简单,底层是一张全局哈希表,它的查找速度是O(1)
  3. 采用的是IO多路复用,非阻塞式IO模型,提高链接访问效率
  4. 单线程执行命令,不存在线程切换,节省开销,线程安全

三、Redis 持久化

持久化的实质是指将数据持久存储在介质上。如,之前学到的对象持久化

Redis提供RDB(Redis Database)方式与AOF(Append Only File)方式进行持久化

RDB方式:这种模式是Redis默认的持久化方式。这种方式是指将Redis里面的数据快照以二进制文件的形式存储在dump.rdb文件里面。

数据快照触发的条件:

  1. save的规则满足的情况下,会自动触发RDB规则 save是Redis.conf里面用来配置触发Redis的RDB持久化条件,也就是什么时候将内存中的数据存储到磁盘中去 如:save m n 表示m秒内数据集存在n次修改时,触发保存 save 900 10:表示900秒内,至少10个键被更改则触发保存 不需要此功能,也可以在redis.conf里面取消此功能
  2. 执行flushall命令的时候,会触发保存
  3. Redis退出的时候,会触发保存

AOF方式 :Redis默认是不开启的。这种方式以日志的形式将Redis里面的执行命令记录

AOF里面的同步机制主要有两种:always与everysec

always的同步方式是每执行一次命令就将执行的命令保存起来,开销很大

everysec的同步方式是每秒执行一次保存,将执行命令保存起来,可能会导致执行的命令丢失

appendfsync always
appendsync everysec

四、Redis事务

Redis在执行单条命令的时候,是保证原子性的,执行命令是单线程在操作,一次只会处理一条命令

Redis如果需要一次性执行多条命令时,需要使用事务

在Redis里面使用multi命令开启Redis的事务,之后我们输入命令之后,Redis不会立即执行

当我们将需要执行的命令全部添加到Redis队列里面后并且执行exec命令后,Redis才会将添加的指令全部执行,但是Redis不保证事务的原子性(一组命令操作中,如果最后一条命令执行失败,那么Redis不会像MySQL一样,会将之前的操作回滚;因为Redis不会保证原子性,所以这一组操作中执行成功的命令不会回滚,会有执行效果,仅仅执行失败的命令会失败)。Redis只会保证隔离性,将这一组操作与其他操作会分隔开

五、Redis的主从复制

当服务的用户量很大,就必须要保证线上服务的数据安全,一般会采用集群的方式,在Redis中,我们为了防止Redis宕机后造成MySQL数据库压力变大,我们会采用主从复制的机制去缓解。我们使用多台Redis服务器,并且将读写的操作分开,让主机进行写数据操作,从机去进行读数据操作。使用一个Redis实例作为主机,其余的作为备份机,从主机里面将数据复制到从机里面。主从模式很好的解决了数据备份问题,客户端将数据写入到主机里面,主机将数据同步复制到从机里面,由于数据的一致性,我们可以将写数据的命令发送到主机里面,将读数据的命令发送到从机里面,达到读写分离的目的

主从复制的作用

  1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
  2. 服务冗余:当主节点的数据出现问题的时候,我们使用从节点的数据可以很快速的将数据进行恢复
  3. 负载均衡:主从复制配合读写分离,可以很好的实现负载均衡,特别是写操作少读操作多的业务,我们将写操作集中在主机中,读操作合理分配到各个从机,分担了服务器压力,大大提高了Redis服务器的并发量
  4. 高可用基石:主从复制是哨兵机制和Redis集群的基石

Redis在linux里面实现主从复制

现在笔者进行的实现是伪集群(因为是在同一台主机进行),实际上是使用多台服务器进行配置

实现主从复制的大致思想:我们创建多个配置文件,配置一台主服务器,配置多台从机

在配置文件里面主要需要配置从机端口号,日志文件,pid文件,RDB文件,Redis主机的IP以及端口号和主机Redis密码

主机配置

bind 0.0.0.0 #任何 ip 都可以访问

daemonize yes 后台运行

pidfile /var/run/redis_6379.pid #进程号文件

logfile “redis6379.log” #日志文件 注意文件名修改只是为了区分

dbfilename dump6379.rdb #数据文件

requirepass root #主机密码

从机配置

#bind 注释

daemonize yes 后台运行

pidfile /var/run/redis_6380.pid #进程号文件

logfile “redis6380.log” #日志文件 注意文件名修改只是为了区分

dbfilename dump6380.rdb #数据文件

replicaof 主机 ip 主机端口

masterauth 主机密码

启动主机使用命令./redis-server redis6379.conf

启动从机命令./redis-server redis6380.conf

主机进入客户端模式 ./redis-cli -p 主机端口

从机进入客户端模式 ./redis-cli -p 从机端口

进入客户端,使用 info replication 命令查看

查看已运行的Redis 查看主机 查看从机

六、Redis哨兵机制

使用哨兵机制的目的是为了在主机服务宕机的时候可以由其他从机充当主机服务,从而不影响整个系统的运行,当原来主机恢复后,原来主机继续充当主机运行

七、Redis过期策略

  1. 立即删除:在键过期的时候,会由时间处理器去执行回调函数,将过期键所占用的内存释放,缺点是可能对Redis性能造成影响
  2. 惰性删除:在键过期的时候不会被立即删除,只有在过期的键被再次使用的时候,根据键的状态将键删除掉,占用内存
  3. 定期删除:每隔一段时间,对到期的键进行删除

Redis的过期策略采用的是惰性删除与定期删除

八、Redis中的缓存穿透,缓存击穿,缓存雪崩

缓存:为了减小数据库压力,提出缓存的策略,将常用的数据放在缓存里面,等到需要使用该数据的时候,就可以直接从缓存里面读取,不需要从数据库里面读取,降低了数据库查询次数

缓冲:我们需要对某些数据进行处理,但是一次性处理的数据较少。处理这些较少数据我们花费的内存与CPU资源与一次性处理一定规格的数据花费的计算机资源是一样的。此时我们就使用缓冲,让计算机一次性处理的数据是一定规格,这个规格也就是缓冲区的大小

但是缓存在使用的时候会出现一些问题:

缓存穿透:key对应的值在数据库里面本身就不存在,因为数据库里面不存在该键对应的值,所以缓存是不会存在这个值的。当下次再次查询这个键的时候,因为缓存里面没有这个键对应的值,所以会直接访问数据库。这种查询中,缓存并没有任何实质的效果。所以我们称之为缓存穿透

解决方法:

  1. 将查询出来的这个key对应的值设置为空放在缓存里面
  2. 对查询的参数进行格式化检验,不符合我们的设计要求,则不进行数据库查询

缓存击穿:查询的key对应的值在数据库里面存在,在缓存里面也存在,但是在访问的时候缓存已经过期,此时大量请求访问这个key对应的值,因为缓存已经不存在,所以会去数据库里面查询,大量的查询会导致数据库宕机

解决方法:

  1. 设置热点key永不过期或者过期时间足够长
  2. 查询缓存不存在后,访问数据库时加锁访问

缓存雪崩:与缓存击穿相比,缓存雪崩是指大量的key过期,而缓存击穿是指一个或者说少量的key过期,导数数据库宕机

解决方法:

  1. 随机设置key的失效时间,减少大量key过期的可能性
  2. 如果在集群里面,则可以设置热点key均匀分布在从机里面

上一篇 Redis基础知识

下一篇 JVM整体结构

 

Content