当前位置:首页 > 问答 > 正文

Redis缓存是怎么加载的?来聊聊它背后的那些原理和细节吧

Redis本身是一个独立的、基于内存的键值数据库,它不是一个直接依附于你主应用(比如一个网站后端)的附属品,谈论“加载”,我们需要从两个角度去看:一是Redis服务本身的启动和加载数据;二是你的应用程序如何与Redis建立连接并开始使用它。

Redis服务端的启动与数据加载

当你启动Redis服务器(比如在Linux上执行 redis-server 命令)时,它会做几件关键的事情,根据“Redis设计与实现”这本书以及Redis官方文档的描述,其核心过程如下:

  1. 初始化与配置读取:Redis首先会读取配置文件(redis.conf),根据配置来设定它的运行参数,例如监听哪个端口(默认6379)、设置密码、定义数据持久化方式等,这是它为自己“布置房间”的阶段。

  2. 数据加载——关键的一步:这是“加载”缓存数据的核心,Redis的数据是存储在内存里的,但为了防止服务器重启或宕机导致数据全部丢失,它提供了两种主要的持久化机制,将内存中的数据备份到硬盘上,启动时,Redis会根据配置决定如何从硬盘恢复数据到内存中。

    • RDB方式(快照):这种方式可以想象成给当前内存里的数据拍一张完整的照片,然后保存成一个文件(通常是 dump.rdb),当Redis重启时,它会去检查配置的目录下有没有这个RDB文件,如果有,它就会把这个文件直接“读入”内存,这个过程非常快,因为是一次性加载整个二进制文件,就像把一本相册快速翻看一遍一样,缺点是可能会丢失最后一次快照之后的数据。
    • AOF方式(追加日志):这种方式更像是一个记账本,Redis会把每一个会修改数据的写命令(SET, HSET)记录到一个日志文件(appendonly.aof)的末尾,当Redis重启时,它不会直接读取数据,而是会把这个“记账本”从头到尾重新执行一遍,从而在内存中重建出完整的数据集,这个过程通常比加载RDB要慢,因为相当于把所有的操作重新做一遍,但数据安全性更高,最多可能只丢失一秒内的数据(取决于配置)。

    Redis在启动时,如果同时开启了AOF和RDB,它会优先使用AOF文件来恢复数据,因为AOF通常能保证更完整的数据。

  3. 开始服务:数据加载到内存后,Redis就会启动事件循环,开始监听网络端口,等待客户端的连接和命令请求,至此,Redis服务端自身的“加载”就完成了,它已经是一个装满数据(或者空数据)的、待命的状态。

客户端(你的应用程序)如何加载并使用缓存

你的应用程序(比如用Java写的网站后端)需要去连接这个已经启动好的Redis服务,这个过程就是我们常说的“缓存加载”或“缓存预热”。

  1. 建立连接:你的应用程序会通过一个Redis客户端库(比如Java的Jedis、Lettuce)与Redis服务器建立网络连接,这就像你的手机通过Wi-Fi连接到路由器一样。

  2. 缓存查询逻辑(核心原理):这是缓存发挥作用的根本,当你的应用需要某个数据时(比如根据用户ID查询用户信息),它不会直接去查询速度很慢的数据库(如MySQL),而是遵循以下步骤:

    • 第一步:查缓存:应用程序首先会向Redis发送一个GET命令,询问:“Redis,你有没有键为 user:123 的数据?”
    • 第二步:缓存命中:如果Redis里有这个数据,它就直接返回给应用程序,应用程序欢天喜地地使用这个数据,完全不用打扰数据库,这个过程极快,通常在一毫秒以内。
    • 第三步:缓存未命中:如果Redis里没有这个数据(这可能是第一次查询,或者数据过期了,或者被清除了),应用程序就会“失望地”去查询背后的慢速数据库。
    • 第四步:回写缓存:从数据库拿到数据后,应用程序在返回给用户的同时,会向Redis发送一个SET命令,说:“Redis,这是 user:123 的数据,你帮我存起来,下次再用。” 并且通常会设置一个过期时间(TTL),比如30分钟,防止数据永远 stale(陈旧)。

    这个“先查缓存,未命中再查数据库并回写”的过程,就是缓存数据被动态“加载”到Redis中的最主要方式,它是在应用程序的运行过程中,按需完成的。

  3. 缓存预热:在一些高并发场景下,如果所有请求都在启动初期同时发生缓存未命中,会导致数据库瞬间压力过大,有时我们会主动进行“缓存预热”,即在系统上线前或低峰期,通过一个脚本程序提前把热点数据查询出来,并批量写入Redis,这样当真实用户流量到来时,大部分请求都能直接命中缓存,从而平稳度过高峰期。

背后的重要细节

  • 过期策略:Redis怎么知道哪些数据该删掉?它采用了惰性删除+定期删除的组合拳,惰性删除是当你访问一个键时,才检查它是否过期,过期就删,定期删除是Redis每隔一段时间随机抽查一些键,删除其中过期的,这保证了内存不会被无用的数据占满。
  • 内存淘汰策略:当内存不够用时,Redis怎么办?这由配置决定,比如可以淘汰最近最少使用的数据(LRU)、随机淘汰等,这决定了在内存压力下,哪些数据会被优先“牺牲”掉。
  • 单线程模型:Redis处理命令的核心模块是单线程的,这听起来是缺点,但实际上是它高性能的重要原因之一,它避免了多线程的上下文切换和竞争问题,而且因为所有数据都在内存中,操作速度极快,单线程足以处理极高的并发,持久化、网络IO等操作会由额外的线程或子进程处理。

Redis缓存的“加载”是一个双向的过程:服务端启动时从磁盘持久化文件(RDB/AOF)加载数据到内存;客户端应用程序在运行时通过“查询-回写”的机制,将热点数据按需加载到Redis中,从而构建起一个高效的速度屏障。

Redis缓存是怎么加载的?来聊聊它背后的那些原理和细节吧