面试题答案
一键面试数据读取流程
- 客户端请求:客户端向应用程序发起数据读取请求。
- 缓存查询:应用程序首先查询Redis缓存。如果缓存中有对应的数据(命中),直接将数据返回给客户端,这极大地提高了响应速度,因为Redis是基于内存的,读写速度极快。
- 缓存未命中:若Redis中没有所需数据(未命中),应用程序会去MySQL数据库查询。从MySQL获取数据后,一方面将数据返回给客户端,另一方面将数据写入Redis缓存,以便后续相同请求可以直接从缓存获取,这个过程称为缓存预热。
数据更新流程
- 客户端请求更新:客户端向应用程序发起数据更新请求。
- 更新数据库:应用程序先更新MySQL数据库中的数据,确保数据的持久化和一致性。
- 更新缓存:更新完数据库后,应用程序需要更新Redis缓存中的数据。常见策略有两种:
- 先更新数据库,再删除缓存:先执行数据库的更新操作,成功后删除Redis中对应的缓存数据。下次读取时缓存未命中,会重新从数据库读取并更新缓存。
- 先删除缓存,再更新数据库:先删除Redis中的缓存数据,然后进行数据库的更新操作。但这种方式可能在删除缓存后,更新数据库前有其他读请求,导致读到旧数据。
可能遇到的问题及解决方案
- 缓存穿透
- 问题描述:恶意请求频繁查询不存在的数据,每次都绕过缓存直接访问数据库,导致数据库压力过大。
- 解决方案:
- 布隆过滤器:在缓存之前使用布隆过滤器,将数据库中已存在的键存放在布隆过滤器中。当请求过来时,先经过布隆过滤器判断,如果不存在则直接返回,不会查询数据库。
- 空值缓存:当查询数据库发现数据不存在时,也将空值写入缓存,并设置较短的过期时间,这样后续相同请求直接从缓存获取空值,避免重复查询数据库。
- 缓存雪崩
- 问题描述:大量缓存数据在同一时间过期,导致后续大量请求直接访问数据库,造成数据库压力骤增甚至崩溃。
- 解决方案:
- 设置随机过期时间:在设置缓存过期时间时,给每个缓存项加上一个随机的过期时间偏移量,避免大量缓存同时过期。
- 二级缓存:采用主从缓存或多级缓存策略,当一级缓存失效时,二级缓存可以继续提供服务,减轻数据库压力。
- 缓存击穿
- 问题描述:热点数据的缓存过期瞬间,大量请求同时访问,这些请求都会绕过缓存直接访问数据库,造成数据库压力瞬间增大。
- 解决方案:
- 互斥锁:在缓存失效时,使用互斥锁(如Redis的SETNX命令)保证只有一个请求去查询数据库并更新缓存,其他请求等待。等更新完缓存后,其他请求可以直接从缓存获取数据。
- 永不过期:对于热点数据设置永不过期,通过后台异步线程定时更新缓存数据,避免缓存过期瞬间的高并发请求。