mysql和redis联动问题
老师好。我理解redis适合作为储存常量数据,方便服务器快速反应。我的问题是当redis写入数据的时候,是否会和mysql进行联动。
我的理解中,现实工作中,mysql一台服务器,redis一台服务器,javaservlet一台服务器。当javaservlet收到写入数据指令的时候,是否会先修改redis的内容,再同步修改mysql中内容呢?
正在回答 回答被采纳积分+1
你好同学,Redis和MySQL是两个独立的数据库,不存在内置的同步机制,所有同步逻辑都必须由业务代码实现。你理解的 “先改 Redis 再同步 MySQL” 是一种常见写法,但顺序和策略要根据业务场景选择,也不能一概而论的。
1.我们为什么不能 “先改 Redis 再改 MySQL”?
如果先更新 Redis、再更新 MySQL,会出现短暂的脏读问题:
步骤1:业务代码更新 Redis 中的数据为新值
步骤2:在更新 MySQL 之前,有其他请求读取 Redis,拿到了还没落地到数据库的 “临时新值”
若步骤3:更新 MySQL 失败,Redis 和 MySQL 就会永久不一致
这是典型的缓存与数据库双写不一致问题,生产环境中通常会避免这种顺序。
2. 推荐的几种联动方案
方案一:先更新 MySQL,再删除 / 更新 Redis(最常用)它的优点是:利用 MySQL 事务保证数据最终一致,缓存失效后下次查询会自动从 MySQL 加载最新数据。适用读多写少、对一致性要求较高的业务(如用户信息、商品详情)场景。具体参考以下代码:
// 伪代码逻辑
@Transactional
public void updateData(String key, Object data) {
// 1. 先更新 MySQL 持久化数据
mysqlMapper.update(data);
// 2. 再删除 Redis 缓存(或更新为新值)
redisTemplate.delete(key);
}方案二:先更新 MySQL,再异步更新 Redis,它的优点是,同步链路更短,接口响应更快,异步更新 Redis 不影响主业务。适用高并发写场景、允许短暂缓存延迟的业务场景。具体参考以下代码:
// 伪代码逻辑
@Transactional
public void updateData(String key, Object data) {
// 1. 更新 MySQL
mysqlMapper.update(data);
// 2. 发送消息到 MQ(如 RabbitMQ/Kafka)
messageSender.sendUpdateMsg(key, data);
}
// 异步消费者
@RabbitListener(queues = "redis_update_queue")
public void updateRedis(String key, Object data) {
// 3. 异步更新 Redis
redisTemplate.opsForValue().set(key, data, expireTime);
}方案三:直接操作 MySQL,Redis 仅做查询缓存这种方式最简单,它的优点是,完全避免双写问题,代码最简单,最不容易出错。具体参考以下代码:
public Object queryData(String key) {
// 1. 先查 Redis
Object data = redisTemplate.opsForValue().get(key);
if (data == null) {
// 2. Redis 不存在,查 MySQL
data = mysqlMapper.selectByKey(key);
// 3. 写入 Redis 缓存
redisTemplate.opsForValue().set(key, data, expireTime);
}
return data;
}适用那种数据更新频率低、查询频率高的常量数据(如字典表、配置项)的场景,这也是你提到的 “Redis 存常量数据” 的典型用法。祝同学学习愉快!
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星