【93期】经典面试题:Redis 内存满了怎么办?
阅读本文大概需要 6 分钟。
来自:juejin.im/post/5d674ac2e51d4557ca7fdd70
Redis占用内存大小
1、通过配置文件配置
//设置Redis最大占用内存大小为100M
maxmemory 100mb
2、通过命令修改
//设置Redis最大占用内存大小为100M
127.0.0.1:6379> config set maxmemory 100mb
//获取设置的Redis能使用的最大内存大小
127.0.0.1:6379> config get maxmemory
Redis的内存淘汰
noeviction(默认策略):对于写请求不再提供服务,直接返回错误(DEL请求和部分特殊请求除外)
allkeys-lru:从所有key中使用LRU算法进行淘汰
volatile-lru:从设置了过期时间的key中使用LRU算法进行淘汰
allkeys-random:从所有key中随机淘汰数据
volatile-random:从设置了过期时间的key中随机淘汰
volatile-ttl:在设置了过期时间的key中,根据key的过期时间进行淘汰,越早过期的越优先被淘汰
如何获取及设置内存淘汰策略
127.0.0.1:6379> config get maxmemory-policy
maxmemory-policy allkeys-lru
127.0.0.1:6379> config set maxmemory-policy allkeys-lru
LRU算法
什么是LRU?
public class LRUCache<k, v> {
//容量
private int capacity;
//当前有多少节点的统计
private int count;
//缓存节点
private Map> nodeMap;
private Nodehead;
private Nodetail;
public LRUCache(int capacity) {
if (capacity < 1) {
throw new IllegalArgumentException(String.valueOf(capacity));
}
this.capacity = capacity;
this.nodeMap = new HashMap<>();
//初始化头节点和尾节点,利用哨兵模式减少判断头结点和尾节点为空的代码
Node headNode = new Node(null, null);
Node tailNode = new Node(null, null);
headNode.next = tailNode;
tailNode.pre = headNode;
this.head = headNode;
this.tail = tailNode;
}
public void put(k key, v value) {
Nodenode = nodeMap.get(key);
if (node == null) {
if (count >= capacity) {
//先移除一个节点
removeNode();
}
node = new Node<>(key, value);
//添加节点
addNode(node);
} else {
//移动节点到头节点
moveNodeToHead(node);
}
}
public Nodeget(k key) {
Nodenode = nodeMap.get(key);
if (node != null) {
moveNodeToHead(node);
}
return node;
}
private void removeNode() {
Node node = tail.pre;
//从链表里面移除
removeFromList(node);
nodeMap.remove(node.key);
count--;
}
private void removeFromList(Nodenode) {
Node pre = node.pre;
Node next = node.next;
pre.next = next;
next.pre = pre;
node.next = null;
node.pre = null;
}
private void addNode(Nodenode) {
//添加节点到头部
addToHead(node);
nodeMap.put(node.key, node);
count++;
}
private void addToHead(Nodenode) {
Node next = head.next;
next.pre = node;
node.next = next;
node.pre = head;
head.next = node;
}
public void moveNodeToHead(Nodenode) {
//从链表里面移除
removeFromList(node);
//添加节点到头部
addToHead(node);
}
class Node<k, v> {
k key;
v value;
Node pre;
Node next;
public Node(k key, v value) {
this.key = key;
this.value = value;
}
}
}
LRU在Redis中的实现
近似LRU算法
maxmemory-samples 10
Redis3.0对近似LRU的优化
LRU算法的对比
浅灰色是被淘汰的数据
灰色是没有被淘汰掉的老数据
绿色是新加入的数据
LFU算法
volatile-lfu:在设置了过期时间的key中使用LFU算法淘汰key
allkeys-lfu:在所有的key中使用LFU算法淘汰数据
问题
推荐阅读:
【92期】面试官:你说你精通Java并发,那给我讲讲J.U.C吧
【91期】面试官:Spring 用了哪些设计模式?说三种即可
【90期】面试官:说一下使用 Redis 实现大规模的帖子浏览计数的思路
微信扫描二维码,关注我的公众号
朕已阅
评论