网易首页 > 网易号 > 正文 申请入驻

到底应该先操作缓存还是先操作数据库?

0
分享至

在数据读多写少的情况下作为缓存来使用,恐怕是Redis使用最普遍的场景了。当使用Redis作为缓存的时候,一般流程是这样的。

  1. 如果缓存在Redis中存在,即缓存命中,则直接返回数据

  1. 如果Redis中没有对应缓存,则需要直接查询数据库,然后存入Redis,最后把数据返回

通常情况下,我们会为某个缓存设置一个key值,并针对key值设置一个过期时间,如果被查询的数据对应的key过期了,则直接查询数据库,并将查询得到的数据存入Redis,然后重置过期时间,最后将数据返回,伪代码如下:

/**
* 根据用户名获取用户详细信息
* @author 公众号【蝉沐风】
*/
public User getUserInfo(String userName) {
User user = redisCache.getName("user:" + userName);
if (user != null) {
return user;
}
// 从数据库中直接搜索
user = selectUserByUserName(userName);
// 将数据写入Redis,并设置过期时间
redisCache.set("user:" + userName, user, 30000);
// 返回数据
return user;
}

一致性问题

但是,在Redis的key值未过期的情况下,用户修改了个人信息,我们此时既要操作数据库数据,也要操作Redis数据。现在我们面临了两种选择:

  1. 先操作Redis的数据,再操作数据库的数据
  2. 先操作数据库的数据,再操作Redis的数据

如论选择哪种方法,最理想的情况下,两个操作要么同时成功,要么同时失败,否则就会出现Redis和数据库数据不一致的情况。

遗憾的是,目前没有什么框架能够保证Redis的数据和数据库的数据的完全一致性。我们只能根据场景和所需要付出的代码来采取一定的措施降低数据不一致出现的概率,在一致性和性能之间取得一个折中。

下面我们来讨论一下关于Redis和数据库之间数据一致性的一些方案。

方案选择
是删除缓存还是更新缓存?

当数据库数据发生变化的时候,Redis的数据也需要进行相应的操作,那么这个「操作」到底是用「更新」还是用「删除」呢?

「更新」的话调用Redis的set方法,新值替换旧值;「删除」直接删除原来的缓存,下次查询的时候重新读取数据库,然后再更新Redis。

结论:推荐直接使用「删除」操作

因为使用「更新」操作的话,你会面临两种选择

  1. 先更新缓存,再更新数据库
  2. 先更新数据库,再更新缓存

第1种不用考虑了,下面讨论一下「先更新数据库,再更新缓存」这种方案。

如果线程1和线程2同时进行更新操作,但是每个线程的执行顺序如上图所示,此时就会导致数据不一致,因此从这个角度上我们推荐直接使用删除缓存的方式。

此外,推荐使用「删除缓存」还有两点原因。

  1. 如果写数据库的场景比读数据场景多,采用这种方案就会导致缓存就被频繁写入,浪费性能;
  2. 如果缓存要经过一系列复杂的计算才能得到,那么每次写入数据库后,都再次计算写入的缓存无疑也是浪费性能的。

明确这个问题之后,摆在我们面前的就只有两个选择了:

  1. 先更新数据库,再删除缓存
  2. 先删除缓存,再更新数据库
先更新数据库,再删除缓存

这种方式可能存在以下两种异常情况

  1. 更新数据库失败,这时可以通过程序捕获异常,直接返回结果,不再继续删除缓存,所以不会出现数据不一致的问题
  2. 更新数据库成功,删除缓存失败。导致数据库是最新数据,缓存中的是旧数据,数据不一致

第2种情况应该怎么办呢?我们有两种方式:失败重试异步更新

失败重试

如果删除缓存失败,我们可以捕获这个异常,把需要删除的 key 发送到消息队列。自己创建一个消费者消费,尝试再次删除这个 key,直到删除成功为止。

这种方式有个缺点,首先会对业务代码造成入侵,其次引入了消息队列,增加了系统的不确定性。

异步更新缓存

因为更新数据库时会往 binlog 中写入日志,所以我们可以启动一个监听 binlog变化的服务(比如使用阿里的 canal开源组件),然后在客户端完成删除 key 的操作。如果删除失败的话,再发送到消息队列。

总结

总之,对于删除缓存失败的情况,我们的做法是不断地重试删除操作,直到成功。无论是重试还是异步删除,都是最终一致性的思想。

先删除缓存,再更新数据库

这种方式可能存在以下两种异常情况

  1. 删除缓存失败,这时可以通过程序捕获异常,直接返回结果,不再继续更新数据库,所以不会出现数据不一致的问题
  2. 删除缓存成功,更新数据库失败。在多线程下可能会出现数据不一致的问题

这时,Redis中存储的旧数据,数据库的值是新数据,导致数据不一致。这时我们可以采用延时双删的策略,即更新数据库数据之后,再删除一次缓存。

用伪代码表示就是:

/**
* 延时双删
* @author 公众号【蝉沐风】
*/
public void update(String key, Object data) {
// 首先删除缓存
redisCache.delKey(key);
// 更新数据库
db.updateData(data);
// 休眠一段时间,时间依据数据的读取耗费的时间而定
Thread.sleep(500);
// 再次删除缓存
redisCache.delKey(key);
}

最后给读者留下两个思考题:

  1. 为什么先更新缓存,再更新数据库行不通?
  2. 延时双删的方法为什么要休眠一段时间呢?

欢迎大家评论区留言。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
有人预测:不出意外,下半年开始,米面油、将迎来行业新一轮洗牌

有人预测:不出意外,下半年开始,米面油、将迎来行业新一轮洗牌

趣味萌宠的日常
2026-06-29 15:36:22
台军慌了!解放军亮出收台新战法,防务部门承认:预警期已归零!

台军慌了!解放军亮出收台新战法,防务部门承认:预警期已归零!

音乐时光的娱乐
2026-06-29 19:05:01
2分钟内就相撞!东沙爆发对峙,海巡署舰开足马力冲向大陆海警船

2分钟内就相撞!东沙爆发对峙,海巡署舰开足马力冲向大陆海警船

阿龙聊军事
2026-06-28 08:23:30
38岁341天,纳帅将成为近40年执教世界杯淘汰赛最年轻教练

38岁341天,纳帅将成为近40年执教世界杯淘汰赛最年轻教练

懂球帝
2026-06-29 07:41:05
别再比退休金了!2026年满60岁,拿到这个数就偷着乐吧

别再比退休金了!2026年满60岁,拿到这个数就偷着乐吧

椰青美食分享
2026-06-29 19:04:57
人人疯考驾照的时代彻底结束 大批年轻人果断放弃,真实原因太现实

人人疯考驾照的时代彻底结束 大批年轻人果断放弃,真实原因太现实

周哥一影视
2026-06-29 12:38:04
日本没料到,美国也没想到,如今的中国广东省,已成了全球焦点

日本没料到,美国也没想到,如今的中国广东省,已成了全球焦点

混沌录
2026-06-27 17:07:33
人要照顾好身体,就默念这8句中医顺口溜

人要照顾好身体,就默念这8句中医顺口溜

洞见
2026-06-29 09:26:17
英国上将揭露:1997年香港回归真相,谁敢抗衡中国解放军?

英国上将揭露:1997年香港回归真相,谁敢抗衡中国解放军?

蜉蝣说
2026-06-29 11:34:20
韩红道歉!发文时已泣不成声,会退出公益事业,多位名人发声挽留

韩红道歉!发文时已泣不成声,会退出公益事业,多位名人发声挽留

青梅侃史啊
2026-06-29 14:25:49
新华社消息|外交部:中方绝不允许日菲侵害中方海洋权益

新华社消息|外交部:中方绝不允许日菲侵害中方海洋权益

新华社
2026-06-29 18:43:01
理发店成片倒闭,真不是没人剪头发,而是把客人做没了!

理发店成片倒闭,真不是没人剪头发,而是把客人做没了!

猫叔东山再起
2026-06-14 12:30:06
十年胜场全联盟第一!!他就这么被对待!!

十年胜场全联盟第一!!他就这么被对待!!

柚子说球
2026-06-28 19:11:52
彻查!信号强烈!中央升级反腐“天网”!

彻查!信号强烈!中央升级反腐“天网”!

职场资深秘书
2026-06-28 16:35:23
熬过2次世界大战和20任总统后,141岁的巨龟被美国动物园安乐死

熬过2次世界大战和20任总统后,141岁的巨龟被美国动物园安乐死

狸猫之一的动物圈
2026-06-28 10:52:53
A股:收盘后,传来一个重要信息,明天行情或开始加速!

A股:收盘后,传来一个重要信息,明天行情或开始加速!

明心
2026-06-29 17:16:09
外国专家:毛泽东之所以打仗厉害,主要有3大“看家本领”

外国专家:毛泽东之所以打仗厉害,主要有3大“看家本领”

大运河时空
2026-06-29 15:50:03
官宣!郭昊文,国王!

官宣!郭昊文,国王!

刺猬篮球
2026-06-28 17:07:26
一场5-0,让韩国崩溃!更不能接受的是,亚洲全帮倒忙 连送5分

一场5-0,让韩国崩溃!更不能接受的是,亚洲全帮倒忙 连送5分

胡一舸南游y
2026-06-28 22:58:44
乔治王子近照公开,英国网民惊呆:这孩子怎么变成这样了...

乔治王子近照公开,英国网民惊呆:这孩子怎么变成这样了...

悦居英国
2026-06-29 02:30:33
2026-06-29 21:31:00
ITPUB学院
ITPUB学院
分享技术干货,了解最新动态
1242文章数 629关注度
往期回顾 全部

科技要闻

杀疯了!深圳一天出两家200亿具身智能公司

头条要闻

媒体:中国再对日本出重拳 一红一黄两张牌同时打出

头条要闻

媒体:中国再对日本出重拳 一红一黄两张牌同时打出

体育要闻

他和伊朗队,再次赢得全世界的尊重

娱乐要闻

跟风电影《给阿公的牛肉丸》开机

财经要闻

近20家半导体企业开启新一轮涨价潮

汽车要闻

全新宝马iX3长轴版将于成都车展预售 四季度交付

态度原创

家居
健康
手机
公开课
军事航空

家居要闻

传奇筑 日常诗

狂吃“糯叽叽”小心肠梗阻!

手机要闻

vivo黄韬:X Fold6要做用户唯一主力机

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

普京最新发声:俄罗斯正处于命运攸关之际

无障碍浏览 进入关怀版