一般情况下,Redis用来实现应用和数据库之间读操作的缓存层,主要目的是减少数据
库IO,还可以提升数据的IO性能。
这是它的整体架构。
当应用程序需要去读取某个数据的时候,首先会先尝试去Redis里面加载,如果命中就
直接返回。如果没有命中,就从数据库查询,查询到数据后再把这个数据缓存到Redis
里面。
(如图)在这样一个架构中,会出现一个问题,就是一份数据,同时保存在数据库和
Redis里面,当数据发生变化的时候,需要同时更新Redis和Mysql,由于更新是有先
后顺序的,并且它不像Mysql中的多表事务操作,可以满足ACID特性。所以就会出
现数据一致性问题。
在这种情况下,能够选择的方法只有几种。
1.先更新数据库,再更新缓存
2.先删除缓存,再更新数据库
如果先更新数据库,再更新缓存,如果缓存更新失败,就会导致数据库和Redis中的数
据不一致。
如果是先删除缓存,再更新数据库,理想情况是应用下次访问Redis的时候,发现Redis
里面的数据是空的,就从数据库加载保存到Redis里面,那么数据是一致的。但是在极
端情况下,由于删除Redis和更新数据库这两个操作并不是原子的,所以这个过程如果
有其他线程来访问,还是会存在数据不一致问题。
所以,如果需要在极端情况下仍然保证Redis和Mysql的数据一致性,就只能采用最
终一致性方案。
(如图)比如基于RocketMQ的可靠性消息通信,来实现最终一致性。
(如图)还可以直接通过Canal组件,监控Mysql中binlog的日志,把更新后的数据
同步到Redis里面。
因为这里是基于最终一致性来实现的,如果业务场景不能接受数据的短期不一致性,那
就不能使用这个方案来做。
以上就是我对这个问题的理解。