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

来源:4-15 如何解决高并发场景下的缓存和数据库之间数据一致性问题

程序猿大叔文海

2023-08-28

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

写回答

1回答

Danny_Idea

2023-08-28

嗯,这是个很好的问题,这里我们先假定场景是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
2
Danny_Idea
回复
qq_慕运维7046742
存在 假设你的MySQL是主从架构,更新写到了master,此时数据还未同步到从节点 而又有请求路由到从节点进行数据查询,就会导致脏数据被带了出来。不过这种场景可以用缓存双删机制来避免。
2024-06-10
共2条回复

SpringCloudAlibaba高并发仿斗鱼直播平台实战

SpringCloudAlibaba高并发仿斗鱼直播平台实战

421 学习 · 344 问题

查看课程