Redis 与 MySQL 的区别:什么时候用缓存,什么时候回到数据库
Redis 与 MySQL、Redis 与 Memcached 的对比内容,讲清键值结构与关系表、内存与磁盘、命令集与 SQL、低延迟与事务查询之间的边界。
相关工具
先别问谁替代谁
Redis 和 MySQL 经常一起出现在系统架构图里,也经常一起出现在面试题里。很多问题表面上是在问区别,实际是在问边界:什么数据应该进 Redis,什么数据必须落 MySQL;什么时候可以先读缓存,什么时候不能绕过数据库;为什么已经有了 MySQL,还要引入 Redis 这一层。
相关基础内容 对两者的区分很直接:Redis 基于键值对,支持多种数据结构;MySQL 是关系型数据库,用表来组织数据。Redis 主要把数据放在内存里,再通过持久化机制把数据写到磁盘;MySQL 通常把数据存储在磁盘上。Redis 不使用 SQL,而是使用自己的命令集;MySQL 使用 SQL 做查询和操作。Redis 追求高性能和低延迟,更适合读多写少、高并发访问;MySQL 更适合复杂查询、事务处理和大规模数据集。
这些句子背后其实是一条很朴素的工程经验:Redis 不是 MySQL 的升级版,MySQL 也不是 Redis 的低配版。它们解决的问题不同。把 Redis 放到系统里,是为了让热点读取、计数、排行榜、会话状态这类访问更快;把 MySQL 放在系统里,是为了让订单、用户、支付、库存这些业务事实有清晰的结构、事务和恢复能力。

读请求优先命中 Redis,未命中再回源 MySQL;写请求以 MySQL 为准,再删除或更新缓存,避免把缓存当成最终事实。
数据模型不同:键值结构和关系表
Redis 的入口是 key。应用拿着一个 key 去读写 value,value 可以是 String、Hash、List、Set、Zset 等结构。它更像是一组面向访问速度和具体业务动作设计的数据容器。计数器可以用 String 自增,用户资料的局部字段可以用 Hash,关注列表可以用 Set,排行榜可以用 Zset。命令和结构是配套的。
MySQL 的入口是表。用户表、订单表、商品表、支付流水表通过字段、主键、外键、索引组织起来。你会关心一张表有哪些列,列是什么类型,主键怎么选,索引怎么建,两张表怎么关联,查询条件怎样写。MySQL 的强项不是把一个 key 快速取出来,而是把结构化数据按关系组织好,再用 SQL 做筛选、关联、聚合和排序。
所以,Redis 适合表达访问路径已经很明确的数据。比如首页商品榜单、用户登录态、短信验证码、文章阅读数,应用知道要读哪个 key,Redis 可以很快返回。MySQL 适合表达需要沉淀和追溯的业务数据。比如订单从创建到支付到退款,每一步都要可查、可对账、可恢复,这类数据不能只靠缓存结构撑住。
存储位置不同:内存优先和磁盘持久
文中说 Redis 将数据存在内存中,通过持久化机制写入磁盘。这句话很关键。Redis 快,很大一部分原因来自内存访问。内存读写延迟远低于磁盘,热点数据放在 Redis 里,应用就不用每次都让数据库执行查询、读取索引、访问数据页。
但内存也有天然边界。容量更贵,断电和进程异常也需要额外的恢复机制。Redis 有 RDB 和 AOF 这类持久化方案,也有主从、哨兵、集群等高可用设计,但它的常见定位仍然不是“唯一可信的数据仓库”。很多业务会允许 Redis 中的数据短暂失效、过期、被淘汰,前提是 MySQL 里还有完整数据可以回源。
MySQL 通常把数据存储在磁盘上,并围绕磁盘数据建立了成熟的事务、日志和恢复机制。它没法像 Redis 那样天然低延迟,但它更适合承接长期数据。系统设计时不要只看快慢,还要看数据丢了能不能补、错了能不能查、并发写入时能不能保证业务规则。
查询方式不同:命令集和 SQL
Redis 不使用 SQL。它有自己的命令集,比如 GET、SET、HGET、LPUSH、SADD、ZADD、EXPIRE。命令通常围绕某个 key 或某类数据结构展开,目标是把一次操作做得短、直接、低延迟。你想拿用户会话,就 GET 一个 session key;想更新计数,就 INCR 一个计数字段;想取排行榜,就按 Zset 分数范围读取。
MySQL 使用 SQL。SQL 的优势是表达复杂查询:按多个条件筛选,跨表关联,分组统计,按字段排序,配合索引优化访问路径。它适合回答“过去三个月某类用户的订单金额是多少”“这个商品关联了哪些活动和库存批次”“某个状态下的记录按时间分页展示”等问题。
这也是很多缓存设计出问题的地方。有人看到 Redis 快,就想把复杂筛选也搬进去,最后在应用层维护一堆 key、集合和反向索引。短期看少查了几次数据库,长期看数据同步、过期、回收、排查都会变复杂。Redis 的命令集适合明确路径的高速访问,MySQL 的 SQL 适合结构化查询和业务事实管理。
性能目标不同:低延迟访问和复杂事务
资料 对 Redis 的描述是高性能、低延迟,适用于读多写少的应用场景。这里的“读多写少”要认真理解。很多页面数据、配置数据、用户状态、热门列表,读取次数远大于更新次数。把这部分数据缓存起来,可以显著减少 MySQL 的压力。
MySQL 更适合事务处理和复杂查询。转账、下单、扣库存、生成账单,都不只是把一个值写进去这么简单。它们要保证多个修改之间的原子性,要能回滚,要能在并发下保持一致。MySQL 的事务、隔离级别、undo log、redo log、binlog 等机制,就是为这类问题服务的。
所以架构上常见的分工是:读请求优先访问 Redis,命中就直接返回;未命中再查 MySQL,并把结果写回 Redis。写请求则以 MySQL 为准,先把真实数据写入数据库,再删除或更新缓存。这样 Redis 负责挡住高频读流量,MySQL 负责承接可信写入和复杂查询。
Redis 不是最终事实来源
把 Redis 用好,第一条边界是别把缓存当最终事实。用户昵称、文章标题、商品详情可以缓存,但最终仍要以数据库为准。余额、订单状态、库存扣减这类数据,即使用 Redis 做加速,也不能让 Redis 单独决定最终结果,除非系统专门为它设计了可靠的落库、补偿和审计流程。
原因很现实。缓存可能过期,可能被淘汰,可能因为内存压力被清掉,也可能因为网络抖动短暂不可用。Redis 的持久化能提高恢复能力,但并不等于所有场景都应该把它当主数据库。尤其是涉及财务、库存、权限这类数据时,缓存层的任何延迟和不一致都可能影响业务判断。
更稳妥的做法是给数据分类。展示类、热点类、可重建类数据适合进 Redis;交易类、审计类、强一致类数据必须落 MySQL。缓存层可以帮助加速读取,但不要替代数据库对业务事实的管理。
一起使用时的读写链路
典型读链路很简单:应用先查 Redis。如果命中,直接返回缓存结果;如果未命中,再查 MySQL,然后把查询结果写回 Redis,并设置合适的过期时间。这个过程能把大量重复读取挡在 Redis 层,减少数据库查询压力。
写链路要更谨慎。常见做法是先更新 MySQL,再删除 Redis 缓存。删除缓存后,下一次读请求会回源 MySQL,拿到新值后再写回缓存。上一章我们已经讲过 Cache Aside 的一致性问题,这里只强调边界:写入的准绳是数据库,不是缓存。
有些业务会选择更新 MySQL 后同步更新 Redis。这样缓存命中率更高,但并发更新时更容易出现旧值覆盖新值。除非你愿意引入分布式锁、版本号、短 TTL 或消息队列补偿,否则“先写库,再删缓存”通常更容易维护。
Redis 与 Memcached 的边界
同时把 Redis 和 Memcached 做了对比,这对理解 Redis 的定位很有帮助。Memcached 主要是简单键值存储,适合做轻量缓存。Redis 支持的数据结构更多,除了 String,还支持 List、Hash、Set、Zset 等结构,因此能覆盖更多业务场景。
持久性也是差异之一。Redis 支持数据持久化,可以把内存数据以 RDB 或 AOF 的方式保存下来;Memcached 重启服务后数据会丢失。对只需要临时缓存的场景来说,这未必是问题,但对希望缓存层具备一定恢复能力的系统,Redis 会更灵活。
文中还提到 Redis 通常更快,部分原因是单线程模型减少了锁竞争;Memcached 则通过多线程处理并发请求。这里不要把结论理解成“Redis 永远更好”。如果只是简单 key-value 缓存,Memcached 仍然直接;如果需要丰富数据结构、持久化、高可用和更多命令能力,Redis 更常被选中。
常见误区:把 Redis 当万能加速器
第一个误区是所有慢查询都丢给 Redis。慢查询真正的问题可能是索引缺失、SQL 写法不合理、表结构不清晰,或者查询本身就不该出现在高频路径上。Redis 能挡住重复读,但不能替你修好数据库设计。
第二个误区是缓存粒度过细或过粗。粒度太细,key 数量暴涨,维护成本变高;粒度太粗,一次缓存里塞进太多字段,更新其中一个字段就要处理整块数据。粒度应该跟访问场景绑定:页面需要什么、接口返回什么、更新频率怎样,都要一起看。
第三个误区是没有过期和回源策略。缓存不是写进去就完事。TTL 怎么设置,热点 key 怎么保护,缓存穿透怎么处理,缓存删除失败怎么重试,都要提前设计。Redis 与 MySQL 搭配使用时,真正麻烦的往往不是读快一点,而是写入、失效和恢复。
面试可以这样回答
如果被问 Redis 和 MySQL 的区别,可以先从四个角度说:数据模型上,Redis 基于键值对并支持多种数据结构,MySQL 是关系型数据库,用表组织数据;存储上,Redis 以内存为主并提供持久化机制,MySQL 通常把数据存储在磁盘上;查询方式上,Redis 使用自己的命令集,MySQL 使用 SQL;使用场景上,Redis 追求高性能低延迟,适合热点缓存和高并发读取,MySQL 适合复杂查询、事务处理和长期数据管理。
如果继续问为什么两者经常一起用,可以回答:MySQL 保存完整、可信的业务事实,Redis 放在应用和数据库之间承接热点访问。读请求先查 Redis,未命中再查 MySQL 并回写缓存;写请求通常先更新 MySQL,再删除或更新 Redis 缓存。这样既能降低数据库压力,也能保留数据库的事务和恢复能力。
如果问 Redis 和 Memcached 的区别,可以说:Memcached 更偏简单 key-value 缓存;Redis 支持更多数据结构,也支持持久化和更丰富的功能,适合缓存之外的计数、排行榜、集合运算等场景。选择时不要只背性能结论,要看业务是否需要这些能力。
常见问题
Redis 能替代 MySQL 吗?
大多数业务里不能。Redis 适合做高速访问和热点缓存,MySQL 更适合保存结构化业务事实、处理事务、支持复杂查询和长期数据恢复。
为什么系统里已经有 MySQL,还要用 Redis?
因为高频读请求直接打 MySQL 会增加数据库压力。Redis 可以把热点数据放在内存里,命中后快速返回,未命中再回源 MySQL。
写数据时应该写 Redis 还是写 MySQL?
通常以 MySQL 为准。常见做法是先更新 MySQL,再删除或更新 Redis 缓存,让后续读请求重新回源并构建新缓存。
Redis 和 Memcached 怎么选?
只做简单 key-value 缓存时,Memcached 很直接;如果需要多种数据结构、持久化、高可用或更丰富的命令能力,Redis 更合适。