Guava本地缓存通过滑动时间窗口算法缓存热数据
# Guava 通过滑动时间窗口算法缓存热数据
本文介绍了如何使用Guava库实现滑动时间窗口算法,以检测并缓存热点数据。
## 1. 引入guava依赖
```xml
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
```
## 2. 新建HotSpotDetector.java
接下来,创建一个名为HotSpotDetector.java的类。该类使用Guava的缓存功能,并通过滑动时间窗口算法来检测和缓存热点数据。
```java
package com.bs.hotkey;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class HotSpotDetector {
//sku_1 1000 5 10
private final int WINDOW_SIZE = 10; // 滑动窗口大小,单位为秒
private final int THRESHOLD = 5; // 阈值,达到该条件即视为热点数据
private final Cache<String, Object> hotCache = CacheBuilder
.newBuilder()
.expireAfterWrite(5, TimeUnit.SECONDS)
.maximumSize(1000).build(); // 缓存热点数据
private Map<String, Queue<Long>> window = new HashMap<>();
private Map<String, Integer> counts = new HashMap<>();
// 判断是否为热点数据
public boolean isHot(String data) {
//如果缓存中有数据,直接返回ture
if (hotCache.getIfPresent(data)!=null){
return true;
}
// 获取当前数据在计数器中的统计次数
int count = counts.getOrDefault(data, 0);
// 如果统计次数大于等于阈值,将该数据加入热点缓存,清空队列并返回true
if (count >= THRESHOLD) {
hotCache.put(data, 1); // 将热点数据放入缓存
clear(data); // 处理完毕后将队列清空
return true;
} else {
// 如果统计次数小于阈值,则更新计数器,维护时间窗口,并返回false
counts.put(data, count + 1);
// 获取对应数据的时间队列
Queue<Long> queue = window.get(data);
// 如果该队列为null,创建一个新的LinkedList队列
if (queue == null) {
queue = new LinkedList<Long>();
window.put(data, queue);
}
// 获取当前时间(秒级)
long currTime = System.currentTimeMillis() / 1000;
queue.add(currTime);// 将当前时间加入时间队列中,用于后面数据滑动窗口的统计
// 如果队列中数据的时间超过了滑动窗口的时间区间,则将该时间从队列中移除
while (!queue.isEmpty() && currTime - queue.peek() > WINDOW_SIZE) {
queue.poll();
counts.put(data, counts.get(data) - 1); // 统计次数-1
}
return false;
}
}
// 清除指定数据的队列和计数
private void clear(String data) {
window.remove(data);
counts.remove(data);
}
//添加数据到本地缓存
public void set(String key , Object value){
hotCache.put(key , value);
}
public Object get(String key){
return hotCache.getIfPresent(key);
}
public static void main(String[] args) throws InterruptedException {
HotSpotDetector detector = new HotSpotDetector();
Random random = new Random();
String[] testData = {"A", "B", "C", "D", "E", "F"};
// 模拟数据访问
detector.isHot("A");
detector.isHot("A");
detector.isHot("A");
detector.isHot("A");
detector.isHot("A");
boolean isHotspot = detector.isHot("A");
if (isHotspot) {
System.out.println("A是热数据");
detector.get("C");
}else{
System.out.println("A不是热数据");
}
}
}
```