redis热key的发现管理淘汰
场景
本地–> nginx —> web服务 ----DB —> dfs —> 网络代理
npm的tgz包请求特点: 高并发、热点包、读多写少
需要发现热点包,缓存到本地,减少web服务和db、dfs的交互,减少网络链路。直接从本地ssd下载文件
热key的发现
1.系统预热,载入业务预估的热key
2.热key自动发现
热key主动发现:基于时间窗口的计数器
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
import java.util.Set;
/**
* 思路: 基于每个key存储统计,在窗口的时间范围内的key值
*
**/
public class RedisHotKeyWindowCounter {
private Jedis jedis;
public RedisHotKeyWindowCounter(String host, int port) {
this.jedis = new Jedis(host, port);
}
/**
* 记录一次关键字key的访问
*
* @param key 关键字
* @param windowSizeInSeconds 时间窗口大小(秒)
*/
public void recordAccess(String key, long windowSizeInSeconds) {
long timestamp = System.currentTimeMillis() / 1000; // 当前时间戳
long cutoff = timestamp - windowSizeInSeconds; // 时间窗口的右端点
String zsetKey = key; // 存储访问记录的ZSET的key
jedis.zadd(key, timestamp, timestamp); // 将时间戳加入set,做file和分数
// 移出已经不在时间窗口右端的记录
jedis.zremrangeByScore(zsetKey, 0, cutoff);
}
/**
* 获取某个关键字在时间窗口内的访问次数
*
* @param key 关键字
* @param windowSizeInSeconds 时间窗口大小(秒)
* @return 访问次数
*/
public int getWindowCount(String key, long windowSizeInSeconds) {
long timestamp = System.currentTimeMillis() / 1000; // 当前时间戳
long cutoff = timestamp - windowSizeInSeconds; // 时间窗口的右端点
// 通过分数返回有序集合指定区间内的成员
Set<Tuple> results = jedis.zrangeByScoreWithScores(key, cutoff, timestamp);
// 遍历ZSET中的所有成员,并累加score,最后返回累加结果
int count = 0;
for (Tuple tuple : results) {
if (tuple.getElement().equals(key)) {
count ++
}
}
return count;
}
}
热key处理
基于上面我们发现的热key,来写伪代码处理
public class NpmDowndload {
public void download(string url, HttpServletResponse) {
long windowSizeInSeconds = 60 * 60 ;
// 认为是热点包
int hotDownCount = 100;
recordAccess(url, windowSizeInSeconds);
int count = getWindowCount(url, windowSizeInSeconds);
if (count >= hotDownCount) {
// 1. 达到热点
// 1.1 本地ssd是否缓存
// 1.1.1 本地有直接从本地下载
// 1.1.2 本地没有,从网络DFS下载,并且缓存到本地
//2. redis记录已经被认为是热点包, 定时任务,处理,如果不是热点了,清理缓存
} else {
// 没有达到热点要求,走网络DFS下载
}
}
}
key的淘汰
redis有提供几种key的淘汰策略如下,根据上面我们的业务场景,使用上面我们手动管理过期 + 根据maxMemorry的淘汰策略
1.被动删除
2.主动删除
3.当使用内存达到maxMemory时根据配置淘汰规则
3.1 TTL
3.2 LRU
3.2.1 只对设置了过期时间的key进行lru算法删除
3.2.2 对所有key进行lru算法删除
3.3 LFU
3.3.1 只对设置了过期时间的key进行LFU算法删除
3.3.2 对所有key进行lFU算法删除
3.4 random
3.4.1 随机删除设置了过期时间的key
3.4.2 随机删除key
3.5 noeviction 永不过期,返回异常(默认的淘汰策略)