照顾好应用的缓存,应付大流量

概述

为了提升系统的响应速度,通常会系统中使用缓存,例如:中央缓存,本地缓存等。但是使用缓存有好有坏,坏处是,如果缓存数据是旧的,那么应用输出的数据便是错误的数据,可能造成严重的影响。

本文介绍一些让缓存保持新鲜以及使用缓存的一些技巧。

利用MQ实时刷新缓存

一旦db数据发生变化,则可以发送一条mq消息,通知消费者,信息有变动,消费者感知到后,立刻调用刷新缓存的接口,把数据涮新到中央缓存里。这里有三个点要注意一下:
1、如果缓存中的数据存在依赖关系,那么必须级联的进行刷新,不然会出现,数据在缓存中不一致。
2、MQ可能挂掉,得使用其他辅助方案来刷新中央缓存。比如说,定时任务全量刷,增量刷。
3、如果应用中Mysql使用一主多从,那么一定要注意主从延迟的问题,如下图:
这里写图片描述

一旦消息消费者判断数据已经从master库同步到slave1的时候,就开始调用调用刷缓存的接口,刷新缓存的应用这个时候读取的是slave2,那么可能数据还未从master同步到slave2,那么这个时候读取的数据其实还是旧的,刷到缓存的数据也是旧的。

基于这种情况,有一种办法,就是保证消息消费者和刷新缓存的应用读取的db必须是同一个。这样即使出现主从延迟,也没问题。

备注:一主一从不会出现这种情况。

全量刷中央缓存

可以使用一个job,每天凌晨把所有

热点数据

刷新到中央缓存里。

增量刷中央缓存

全量刷,有个缺点,就是得等到晚上凌晨,数据才能被刷到中央缓存里。如果想让数据快点刷到中央缓存里,可以使用一个增量的job,每隔两个小时,把最新的热点数据刷到缓存里。使用增量job也注意一个问题,避免高峰期刷。

比如说,你的应用是早上十点,晚上八点流量最大,那么这个时候,就不要去刷缓存了,给应用多留一些资源,应付大流量。

使用哨兵机制

有些情况下,中央缓存也会缓存外部其他系统的数据,如果这些数据访问比较频繁,那么可以使用

哨兵机制,当这些数据快要过期的时候,主动调用外部系统,把数据刷新到中央缓存里。个人认为这是一个相当不错的技巧。因为调用一次外部系统的接口,开销还是很大的,而且也需要时间,如果能提前调用的话,那么将大大提高本系统接口的响应速度。

使用本地缓存

使用本地缓存的时候,有几点要注意
1、本地缓存的选型,到底是使用堆外缓存还是堆内缓存。
堆外缓存有:
OHC、ehcache、OpenHFT Chronicle Map 2、OpenHFT Chronicle Map 3。
堆内的有:ConcurrentHashMap、Google Loading Cache
缓存的数据量比较大的话,使用堆外的,量小的,使用堆内的。

2、注意同一个key的防穿透,就是说,有相同的key并发的访问到本地缓存,那么应该只是让其中一个key穿透过去,其他的key只能等待,防止大量的key穿透过去,对中央缓存或者db造成压力。

本地缓存刷新策略

1、自动过期。这种方式非常的简单,就是设置本地缓存数据的失效时间,比如说,设置5分钟,5分钟后自动失效,请求穿透过去。
如果使用数据过期这种方式的话,要注意,当系统有大流量的时候,

要延迟本地缓存数据的失效时间,比如说设置20分钟失效,避免穿透的数据太多

2、发布订阅的方式,在每个应用中部署一个监听者,写数据的一方,一旦把数据写到db后,就通知每个应用的监听者,刷新本地缓存。这种方式稍微有点难度,也不是特别可控。目前我参与的应用,本地缓存数据的刷新策略是自动失效。

统计命中率

为了能知道缓存的命中率,分析缓存框架的效果,最好用程序输出缓存的命中率。如果缓存命中不高的话,就得分析原因了。可能是算法有问题,缓存key的维度有问题等等。

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

1 收藏 评论

关于作者:Sam哥哥

互联网技术爱好者,目前就职于广州唯品会担任JAVA高级开发。个人的csdn技术博客如下:http://blog.csdn.net/linsongbin1本人伯乐在线的文章,都出自这个csdn博客 个人主页 · 我的文章 · 15

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部