首先,咱们都有一共识,即可以使用缓存来提升系统的访问速度!
现如今,分布式缓存这么强大,所以,大部分时候,我们可能都不会去关注本地缓存了!
而在一起高并发的场景,如果我们一味使用nosql式的缓存,如 redis, 那么也是好的吧!
但是有个问题我们得考虑下: redis 这样的缓存是快,但是它总有自己的瓶颈吧,如果什么东西我们都往里面存储,则在高并发场景下,应用瓶颈将受限于其缓存瓶颈吧!
所以,针对这种问题,在一些场景下,咱们可以使用本地缓存来存储一些数据,从而避免每次都将请求击穿到 redis 层面!
本文考虑的是使用 本地缓存 作为二级缓存存在,而非直接的充当缓存工具!
而使用本地缓存,则有几个讲究:
1. 缓存一致性问题;
2. 并发安全问题;
所谓缓存一致性问题,就是本地缓存,是否和redis等缓存中间件的数据保持一致,如果不一致的表现超过了可接受的程度,则要这访问速度也就没啥意义了!
所谓并发安全问题,即是,当使用本地缓存时,本地的缓存访问线程安全性问题,如果出现错乱情况,则严重了!
使用本地缓存,有什么好处?
1. 减少访问远程缓存的网络io,速度自然是要提升的;
2. 减少远程缓存的并发请求,从而表现出更大的并发处理能力;
本地缓存,都有什么应用场景?
1. 单机部署的应用咱们就不说了;
2. 读多写少的场景;(这也缓存的应用场景)
3. 可以容忍一定时间内的缓存不一致; (因涉及的本地缓存,分布式机器结果必可能不一致)
4. 应用对缓存的请求量非常大的场景; (如果直接打到redis缓存, 则redis压力巨大, 且应用响应速度将变慢)
所以,如果自己存在这样的使用场景,不防也考虑下,如何使用这本地缓存,来提升响应速度吧!
如果要求自己来实现这两级缓存功能,我想应该也是不能的!只要解决掉两个问题即可:
1. 缓存过期策略;
2. 缓存安全性;
其中一最简单直接的方式,就是使用一个定时刷新缓存的线程,在时间节点到达后,将缓存删除即可; 另一个安全问题,则可以使用 synchronized 或 并发包下的锁工具来实现即可。
但是真正做起来,可能不一定会简单,这也不是咱们想特别考虑的。
咱们主要看下 guava 是如何来解决这种问题的?以其思路来开拓自己的设想!
如何 guava 来作为我们的二级缓存?
1. 首先,咱们得引入 guava 的依赖
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency>