缓存+数据库一致性问题是一个经典问题,现对其分析一二。
问题1:为什么引入缓存?
解:提高性能,更准确的说是提高读的性能。典型的缓存中间件采用redis。
问题2:一致性分为那些情况?
解:弱一致性、强一致性、最终一致性。在性能与一致性的选择中必然需要根据具体需求牺牲某一个。
问题3:到底是更新缓存还是删除缓存?
解:删除缓存,分析见下面问题及分析过程。
问题4:到底是先更新数据库再删除缓存,还是先删除缓存再更新数据库?
解:前者,分析见下面问题及分析过程。
问题5:更新缓存场景,操作失败引起的一致性问题?
解:更新缓存存在2种情况,可自行验证
①先更新缓存,后更新数据库?后者操作失败会出现不一致
②先更新数据库,后更新缓存?后者操作失败会出现不一致
问题6:更新缓存场景,并发操作引起的一致性问题?
解:同样存在2种情况,可自行验证
执行顺序错乱会导致出现不一致
问题7:删除缓存场景,操作失败引起的一致性问题?
解:删除缓存存在2种情况,可自行验证
①先删除缓存,后更新数据库?后者操作失败会出现不一致
②先更新数据库,后删除缓存?后者操作失败会出现不一致
问题8:删除缓存场景,并发操作引起的一致性问题?
解:同样存在2种情况,可自行验证
读写并发导致不一致
在先更新数据库,后删除缓存场景下,读写并发会导致不一致,但实际上出现的概率小,因为写数据库通常是要比读数据库的时间更长的,所有推荐该方案。
问题9:删除场景的并发下,读写导致不一致,其他?
解:举例,2个线程,同时读不影响数据一致性;同时写也不影响一致性,因为在删除场景下最终都是要删除缓存;同时读写会导致一致性问题,但实际上概率很小,需要从减小概率的方向努力即可。
问题10:并发下可以选择先更新数据库后删除缓存的方案,若是操作失败怎么解决一致性?
解:若后者操作失败,则应避免操作失败,保证都操作成功,可以从重试的方向努力,推荐选择消息队列来避免操作失败的概率。