前言:
了不起学弟:最近看到一个老生常谈的面试题啊,redis和mysql如何保持数据一致性。
了不起:这个问题确实是很多面试官喜欢问的问题,你看的怎么样?
了不起学弟:也能够懂了一些,但有些也还是不懂。
了不起:那我给你讲一讲吧!
正文:
我们在多线程,高并发的情况下,redis作为mysql的缓冲,就会和mysql出现数据不一致的问题。
举例:线程A,线程B(后边举例同理) A修改了数据,B在读取数据,A可能是改或者删redis也可能是改mysql,这就会出现数据不一致的问题。
这里给大家说一些数据一致性的解决方案,最基础的不可行的都给大家讲一下。
- 先更新mysql,再更新redis A修改mysql改数据为1,B修改mysql改数据为2。B修改redis为2,A修改redis为1.
最终数据:redis为1,mysql为2. 所以先更新数据库,再更新缓存的方式不可取。
2.先更新redis,再更新mysql 这个和先mysql,再redis是一样的,也会出现数据不一致的情况,也不可取。
3.先删除redis,再更新mysql A删除redis数据,B查询redis未查询到,B直接去mysql修改数据为1,A修改mysql数据为2,B回写redis为1.
此时数据库为2,redis为1,数据不一致。
4.先删除redis,再更新mysql,再删除redis(所谓的延迟双删) 前面的步骤一样,到最后还会删除一遍redis。
最后一次删除,解决了数据不一致的问题。但是延迟双删,我们也需要多考虑一下。
等待时间的设置:需要根据具体的业务需求和性能要求,合理设置等待时间,以确保缓存失效期间数据库中的数据已经被更新,同时避免等待时间过长带来的性能问题。可能会出现数据不一致:如果延迟时间设置不当,可能会导致缓存失效期间读取到旧的数据库数据,从而出现数据不一致的情况。
并发读写的处理:需要考虑并发读写的情况,确保在等待期间,读请求能够自动重新加载数据,写请求能够更新数据库中的数据。
缓存的一致性:需要考虑缓存的一致性问题,确保在缓存失效期间,读请求能够自动重新加载数据,而不会读取到旧的缓存数据。
5.先更新mysql,再删除redis。A更新mysql数据为1,B查询缓存为2,A删除缓存,B第二次查询缓存未命中,查询数据库为1,A回写缓存为1. 这种方式会出现一次数据不一致性的问题,之后就没问题了,再数据不要求强一致性的情况下可以使用。
6.更新mysql,再通过binlog异步更新redis。这个方案也是可以保证一致性的。先更新mysql,消息队列监听binlog,再去异步更新redis。但是这个方法需要去引入比较专业的mq去操作,这增加了系统的复杂性,和成本。通过mq,会增加一些性能开销,这需要去评估和优化。
了不起觉得使用消息队列的方式会比较好,这是最终一致性的解决方式。延迟双删也是不错,但是要注意等待时间的设置。
总结
好了,关于这个面试题就讲到这里。