guava cache本地缓存的使用
程序开发
2023-09-10 14:43:50
1 本地缓存简单介绍
本地缓存因为少了网络传输环节,所以读取速度比分布式缓存要快一些。HashMap、ConcurrentHashMap也能用作本地缓存,但是因为缺少必要的过期机制、容量限制、数据淘汰策略,不太合适。本文介绍guava cache本地缓存的用法,重点介绍下两种过期机制的区别:refreshAfterWrite和expireAfterWrite。
2 guava cache
guava cache的过期机制:
两种过期策略在过期时都不会主动刷新缓存,只有下一次请求到来时才会刷新。
示例:缓存过期时间设置为3s,启动3个线程,其中Thread-1、Thread-2并发获取缓存,每5s获取一次,Thread-3每秒查询一次缓存内容,缓存load时休息5s,模拟下load缓存的延时。
2.1 expireAfterWrite
package cache.guava;import com.google.common.cache.*;import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;/*** @Description guava本地缓存* @Author lilong* @Date 2019-03-14 19:55*/
public class GuavaCacheService {private static LoadingCache localCache = CacheBuilder.newBuilder().maximumSize(5) // 缓存容量设为5,实际上只用到1个.expireAfterWrite(3, TimeUnit.SECONDS) // 一个线程load,其他线程阻塞等待.removalListener((removalNotification) -> { // 匿名内部类RemovalListenerSystem.out.println(Thread.currentThread().getName() + ":已移除");}).build(new CacheLoader() {@Overridepublic String load(String key) throws InterruptedException {System.out.println(Thread.currentThread().getName() + ":开始移除key..." + key);Thread.sleep(5000);LocalDateTime dateTime = LocalDateTime.now();String time = dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);System.out.println(Thread.currentThread().getName() + ":移除成功key..." + key);return "key_" + key + "_" + time;}});public static void main(String[] args) {new Thread(new GetCache(), "Thread-1").start();new Thread(new GetCache(), "Thread-2").start();new Thread(() -> {while (true) {System.out.println(localCache.asMap());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}, "Thread-3").start();}static class GetCache implements Runnable {@Overridepublic void run() {while (true) {try {String val = localCache.get("a");System.out.println(Thread.currentThread().getName() + ":" + val);Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}}}}
}
运行看下打印,可以看到:
1)缓存存活时间3s,到期自动删除;
2)在获取缓存新值时,所有线程阻塞等待、直到有一个线程load成功;
3)获取到的新值时间戳比旧的延后10s,而不是load的延时5s,还没搞懂为什么
2.2 过期机制:refreshAfterWrite
把上面代码的expireAfterWrite换成refreshAfterWrite,打印日志,看到
1)缓存过期后不会清除;
2)在一个线程load阻塞住时,其他线程仍然能返回旧值,不会阻塞住。
3)获取到的新值时间戳比旧的延后也是10s,而不是load的延时5s
3 解决分布式环境下本地缓存不一致问题
(1)kafka:
(2)zk:
每台机器注册到zk上面去,类似dubbo服务注册的方式,所有机器都注册一个watch,一有变化全部通知,然后大家再去那一台机器取缓存。
标签:
上一篇:
在浏览器地址栏输入URL,按下回车后究竟发生了什么?
下一篇:
相关文章
-
无相关信息