请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

先更新数据库再更新Redis为什么会出现脏数据?

数据库有行锁更新完之后事务没提交再更新Redis成功之后再提交事务,释放行数之后别的事务才能拿到行锁,请问你说的脏数据是哪一步有问题?

正在回答 回答被采纳积分+3

1回答

Danny_Idea 2023-08-28 10:49:17

嗯,这是个很好的问题,这里我们先假定场景是mysql的innodb存储引擎。

你所描述的场景 还比较特别,是在一个事务里面做了更新和redis的操作。如果update的sql有了事务的保护,自然是安全的,而且也必须要等到事务提交后,才能释放。但是通常来说,我们不会这么做,具体原因如下:

  1. 设计有点过度,没有涉及到多MySQL表的数据一致性保护,用事务的意义不大。

  2. 性能不高,通常引入了事务之后,写性能会降低很多倍

  3. 假设事务中的redis访问出现了网络超时,但是没有抛出异常,很可能会导致行锁或者表锁持有时间过久,需要考虑这类风险。

假设没有了事务的保护,那么我们来模拟下这种场景。

线程A:update了DB一条数据,写入Redis

线程B:update了线程A的同一条数据,写入Redis

顺序是线程A先更新完了DB,然后线程B再更新DB,那么DB的数据应该以线程B的为准。假设线程A在更新Redis的时候,因为一些网络问题,延迟了下,让线程B先刷入到了Redis中,然后过一段时间后,线程A的网络通畅了,把脏数据刷入了Redis,导致数据不一致。

所以我建议更合适的方案可以是在查询的时候再将数据刷入缓存中。

1 回复 有任何疑惑可以回复我~
  • 先更新数据库再删除缓存出现不一致的情况:查询事务先查询redis未命中,然后查询mysql命中,但还未更新到redis缓存,这个时候更新事务去数据库更新了该值,最后查询事务将旧值更新到redis。导致redis还是旧值,mysql是新值。这种情况存在吗?
    回复 有任何疑惑可以回复我~ 2024-06-09 18:44:46
  • 存在 假设你的MySQL是主从架构,更新写到了master,此时数据还未同步到从节点 而又有请求路由到从节点进行数据查询,就会导致脏数据被带了出来。不过这种场景可以用缓存双删机制来避免。
    回复 有任何疑惑可以回复我~ 2024-06-10 20:46:19
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信