背景
计算机为了在性能上有一个倍数式的增长,引入了缓存设计,同时也间接引入了并发问题。抛开让人闻风丧胆的并发问题,缓存的引入,本质的问题是磁盘虽然硬件成本低,但是性能低效,而缓存则相反,成本高,但是性能极好,所以在二者权衡之下,选择折中的方案,两者相结合得最大性价比。系统架构同样也面临着性能问题,响应问题。
缓存带来的作用:由于redis的容量一般都只有几个G(那些大土豪请忽略),如此宝贵的缓存当然是放最合适的数据!行业上有个说法是:冷热数据分离,可以考虑把热数据放置在redis中。当用户发起请求时,优先访问redis缓存层,由于缓存访问速度高效的特性,响应速度更好,体验更好,且多数请求不会直接流到数据层。
计算机加入高速缓存层后,出现了并发问题,系统架构中加入缓存后,同样出现了比如:缓存更新问题,缓存穿透,缓存雪崩,缓存一致性等等的一系列问题。缓存的数据会失效,所以需要一个更新策略,来保证缓存中的数据与数据库中的数据一致。今天我们就聊一聊缓存到的更新问题。
缓存在系统部署中的位置:
如何控制缓存更新
发现问题:
- 1、增加一个get方法,现在缓存中加载,加载不到时从数据库中加载,并更新缓存。
- 2、现在有另一个客户端 insert()了一条数据,在查询时发现缓存数据并没有更新,数据库数据已经更新:
解决缓存数据一致性问题方案:
1、数据实时同步失效:
这里需要注意几点:
- 一定是先更新数据库,后淘汰缓存。如果反过来,在并发情况下会有问题:先淘汰缓存,此时恰好有一个get请求访问该数据,这时数据库还没有更新,那么缓存的还是淘汰的数据(脏数据),而后进行了数据库的更新。这就有缓存一致性的问题了。
- 淘汰缓存,可能会出现缓存雪崩的问题,所以此时最好采取同步措施,来减少数据库的压力。推荐使用轻粒度锁,key值相同的竞争同一把锁。之后再从缓存中获取一次,使竞争失败的请求直接从缓存中获取,因为已经更新完成了。
2、数据准实时更新:
- 采取异步方式,先更新数据库,之后发送消息到MQ中。
- 监听MQ,通知Redis相应key值发生更新,redis从数据库中更新缓存。