Redis —— 基本知识大全,面试看这一篇就够了。

    科技2026-06-15  1

    目录

    基本介绍

    Redis的适用场景

    Redis的缺点

    Redis支持五种数据类型

    八种底层数据结构

    遵守BSD协议

    Redis相比memcached有哪些优势?

    为什么Redis需要把所有数据放到内存中?

    Redis是单进程单线程的

    Redis的删除过期键

    Redis有哪几种数据淘汰策略?

    Redis的更新

    缓存【失效】

    缓存【命中】

    缓存【更新】

    为什么不采取更新后删除缓存?

    为什么不删除缓存后再更新数据库?

    Redis能否将数据持久化,如何实现?

    RDB持久化原理Redis DataBase

    AOF持久化原理Append-only file

    Redis的三种集群方式:主从复制,哨兵模式和集群

    主从复制

    哨兵模式:

    Redis-Cluster集群

    RESP

    缓存穿透

    解决办法

    缓存雪崩

    解决办法

    缓存击穿

    解决办法


    基本介绍

    redis是一个基于内存的高性能key-value数据库,是非关系型数据库,适用于存储缓存用的数据,也适合需要高速读/写的场合使用它快速读/写。

    Redis的适用场景

    1)会话缓存(Session Cache)

    2)全页缓存(FPC)

    3)队列

    4)排行榜/计数器

    5)发布/订阅

    Redis的缺点

    缓存穿透、缓存击穿、缓存雪崩

    Redis支持五种数据类型

    StringString是最常用的一种数据类型,普通的kv存储都可以归为此类。hash适合存储对象类型信息,例如个人信息、商品信息等。list应用场景可以有微博的关注列表、粉丝列表、消息列表等。setset表示存储的一个元素不重合的集合,适合做共同好友等功能sorted set网站排行榜

    八种底层数据结构

    long类型的整数、整数集合 、embstr编码的简单动态字符串 、简单动态字符串 、双向链表 、压缩列表 、字典 (保存键值对的一种数据结构)、跳跃表+字典。

    遵守BSD协议

    允许使用者修改和重新发布代码,也允许使用或在BSD代码基础上开发商业软件发布和销售,因此是适用于商业软件的。使用者使用时还必须做到满足三个条件:

    1)如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协议。

    2)如果再发布的只是二进制类库/软件,则需要在类库/软件的文档和版权声明中包含原来代码中的BSD协议。

    3)不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

    Redis相比memcached有哪些优势?

    1)memcached所有的值均是简单的字符串,redis支持更为丰富的数据类型

    2)redis的速度比memcached快很多 

    3)redis可以持久化其数据

    4)存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,这样能保证数据的持久性。

    为什么Redis需要把所有数据放到内存中?

      Redis为了达到最快的读写速度,所有数据都是保存在内存中,然后不定期的通过异步方式保存到磁盘上。所以redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。

    Redis是单进程单线程的

      redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销

    Redis的删除过期键

    redis采用的是定期删除+惰性删除策略。

    定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

    于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

    Redis有哪几种数据淘汰策略?

    当前已用内存超过最大值时,触发主动清理策略。

    主动清理策略主要有一下六种:

    volatile-lru从已设置过期的数据集中挑选最近最少使用的淘汰volatile-ttl从已设置过期的数据集中挑选将要过期的数据淘汰volatile-random从已设置过期的数据集中任意挑选数据淘汰allkeys-lru从数据集中挑选最近最少使用的数据淘汰allkeys-random从数据集中任意挑选数据淘汰noenviction禁止淘汰数据

    Redis的更新

    缓存【失效】

    客户端请求数据先从缓存中查询,如果没有再查询数据库,最后将数据放入缓存

     

    缓存【命中】

    客户端从缓存中直接取到数据,返回结果

    缓存【更新】

    客户端写入数据到数据库,成功之后,让缓存失效(下次请求时从缓存中拿不到,则查询数据库,再放入缓存)

    为什么不采取更新后删除缓存?

    防止并发写操作导致脏数据。

    为什么不删除缓存后再更新数据库?

    两个并发请求,一个读操作,一个写操作,如果先删除缓存,读操作会将【旧数据】写入缓存,写操作【更新数据】后也不会更新缓存,导致脏数据一直存在。

    Redis能否将数据持久化,如何实现?

    能,将内存中的数据异步写入硬盘中,两种方式:RDB(默认)和AOF。

    RDB持久化原理Redis DataBase

    指定的时间间隔内保存数据快照。实际操作过程是fork一个子进程出来,子进程将数据写入临时的rdb快照文件中,完成rdb快照文件的生成之后,就替换之前的旧的快照文件。是周期性的持久化

    优点:Redis加载RDB恢复数据远远快于AOF的方式。

    缺点:由于每次生成RDB开销较大,非实时持久化,有可能会丢失数据

    AOF持久化原理Append-only file

    以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。Redis通过rewrite的机制,让AOF文件不至于太庞大。就是大概是数据量多的时候,重写一个新的,把不需要的剔除。

    优点:实时持久化。

    缺点:所以AOF文件体积逐渐变大,需要定期执行重写操作来降低文件体积,加载慢。

    Redis的三种集群方式:主从复制,哨兵模式和集群

    主从复制

    Slave从节点服务启动并连接到Master之后,它将主动发送一个SYNC命令。Master服务主节点收到同步命令后将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave从节点服务在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master主节点继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。

    哨兵模式:

    使用一个或者多个哨兵(Sentinel)实例组成的系统,对redis节点进行监控,在主节点出现故障的情况下,能将从节点中的一个升级为主节点,进行故障转义,保证系统的可用性。

    监控: 哨兵通过gossip 协议会不断地检查你的Master和Slave是否运作正常;

    提醒:当被监控的某个Redis节点出现问题时, 哨兵可以通过 API 向管理员或者其他应用程序发送通知;

    自动故障迁移:当一个Master不能正常工作时,哨兵通过投票协议会开始一次自动故障迁移操作,它会将其他一个Slave升级为新的Master,当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用现在的Master替换失效Master。Master和Slave服务器切换后,Master的配置文件的内容都会发生相应的改变,即,Master主服务器的redis.conf配置文件中会多一行slaveof的配置,sentinel.conf的监控目标会随之调换。

    Redis-Cluster集群

    redis的哨兵模式基本已经可以实现高可用,读写分离 ,但是在这种模式下每台redis服务器都存储相同的数据,很浪费内存,所以在redis3.0上加入了cluster模式,实现的redis的分布式存储,也就是说每台redis节点上存储不同的内容。

    Redis-Cluster采用无中心结构,它的特点如下:

    所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。

    节点的fail是通过集群中超过半数的节点检测失效时才生效。

    客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

    工作方式:

    在redis的每一个节点上,都有这么两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。当我们的存取的key到达的时候,redis会根据crc16的算法得出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,通过这个值,去找到对应的插槽所对应的节点,然后直接自动跳转到这个对应的节点上进行存取操作。

    为了保证高可用,redis-cluster集群引入了主从模式,一个主节点对应一个或者多个从节点,当主节点宕机的时候,就会启用从节点。当其它主节点ping一个主节点A时,如果半数以上的主节点与A通信超时,那么认为主节点A宕机了。如果主节点A和它的从节点A1都宕机了,那么该集群就无法再提供服务了。

    RESP

    RESP 是redis客户端和服务端之前使用的一种通讯协议;

    RESP 的特点:实现简单、快速解析、可读性好。

    缓存穿透

    是指查询一个数据库一定不存在的数据。

    程序在处理缓存时,一般是先从缓存查询,如果缓存没有这个key获取为null,则会从DB中查询,并设置到缓存中去。按这种做法,那查询一个一定不存在的数据值,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。

    解决办法

    最好对于每一个缓存key都有一定的规范约束,这样在程序中对不符合parttern的key 的请求可以拒绝。(但一般key都是通过程序自动生成的)

    将可能出现的缓存key的组合方式的所有数值以hash形式存储在一个很大的bitmap中<布隆过滤器>(需要考虑如何将这个可能出现的数据的hash值之后同步到bitmap中, eg. 后端每次新增一个可能的组合就同步一次,或者 穷举),一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

    常用: 如果对应在数据库中的数据都不存在,我们将此key对应的value设置为一个默认的值,比如“NULL”,并设置一个缓存的失效时间。当然这个key的时效比正常的时效要小的多。

    缓存雪崩

    指的是大量缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。

    解决办法

    这个没有完美解决办法,但可以分析用户行为,尽量让失效时间点均匀分布,设置不同的过期时间。

    用加分布式锁或者分布式队列的方式保证缓存的单线程(进程)写 (eg. redis的 SETNX),从而避免失效时大量的并发请求落到底层存储系统上。在加锁方法内先从缓存中再获取一次(防止另外的线程优先获取锁已经写入了缓存),没有再查DB写入缓存。 (当然也可以: 在没有获取锁(tryLock)的线程中一直轮询缓存,至超限时)

    缓存击穿

    指的是热点key在某个特殊的场景时间内恰好失效了,恰好有大量并发请求过来了,造成DB压力。

    解决办法

    与缓存雪崩的解决方法类似: 用加锁或者队列的方式保证缓存的单线程(进程)写,在加锁方法内先从缓存中再获取一次,没有再查DB写入缓存。 

    还有一种比较好用的(针对缓存雪崩与缓存击穿):

    物理上的缓存是不设置超时时间的(或者超时时间比较长), 但是在缓存的对象上增加一个属性来标识超时时间(此时间相对小)。 当获取到数据后,校验数据内部的标记时间,判定是否快超时了,如果是,异步发起一个线程(控制好并发)去主动更新该缓存。这种方式会导致一定时间内,有些请求获取缓存会拿到过期的值,看业务是否能接受而定。

    Processed: 0.016, SQL: 9