Redis занимает объем памяти
Мы знаем, что Redis — это база данных типа «ключ-значение» на основе памяти.Поскольку объем памяти системы ограничен, мы можем настроить максимальный объем памяти, который Redis может использовать при использовании Redis.
1. Настроить через конфигурационный файл
Установите размер памяти, добавив следующую конфигурацию в файл конфигурации redis.conf в каталоге установки Redis.
//设置Redis最大占用内存大小为100M
maxmemory 100mb
Файл конфигурации Redis не обязательно использует файл redis.conf в каталоге установки.При запуске службы Redis вы можете передать параметр, чтобы указать файл конфигурации Redis.
2. Изменить по команде
Redis поддерживает динамическое изменение размера памяти с помощью команд во время выполнения.
//设置Redis最大占用内存大小为100M
127.0.0.1:6379> config set maxmemory 100mb
//获取设置的Redis能使用的最大内存大小
127.0.0.1:6379> config get maxmemory
Если вы не установите максимальный размер памяти или установите для максимального размера памяти значение 0, размер памяти не будет ограничен в 64-разрядной операционной системе, а в 32-разрядной операционной системе будет использоваться максимум 3 ГБ памяти.
Устранение памяти Redis
Поскольку можно установить максимальный размер памяти Redis, сконфигурированная память будет израсходована. Затем, когда память закончится, если вы продолжите добавлять данные в Redis, не будет ли доступной памяти?
На самом деле Redis определяет несколько стратегий для решения этой ситуации:
Невыселение (политика по умолчанию): для запросов на запись услуга не предоставляется, и ошибка возвращается напрямую (за исключением запросов DEL и некоторых специальных запросов).
allkeys-lru: исключить использование алгоритма LRU из всех ключей
volatile-lru: Устранить с помощью алгоритма LRU из ключа с установленным сроком годности
allkeys-random: Произвольное удаление данных со всех ключей
volatile-random: Случайным образом исключается из ключа с установленным сроком действия
volatile-ttl: Среди ключей с установленным временем истечения они удаляются в соответствии со временем истечения срока действия ключа.Чем раньше время истечения, тем больший приоритет будет устранен
когда используешьvolatile-lru,volatile-random,volatile-ttlВ этих трех стратегиях, если ни один ключ не может быть устранен, иnoevictionвозвращает ту же ошибку
Как получить и установить политику исключения памяти
Получите текущую политику вытеснения памяти:
127.0.0.1:6379> config get maxmemory-policy
Задайте стратегию исключения через конфигурационный файл (модифицируйте файл redis.conf):
maxmemory-policy allkeys-lru
Измените стратегию устранения командой:
127.0.0.1:6379> config set maxmemory-policy allkeys-lru
Алгоритм LRU
Что такое ЛРУ?
Как упоминалось выше, максимальная память, которую может использовать Redis, исчерпана, и алгоритм LRU можно использовать для устранения памяти.Так что же такое алгоритм LRU?
LRU(Least Recently Used), наименее используемый в последнее время, представляет собой алгоритм замены кеша. При использовании памяти в качестве кеша размер кеша обычно фиксирован. Когда кеш заполнен, если вы продолжаете добавлять данные в кеш в это время, вам необходимо удалить некоторые старые данные и освободить место в памяти для хранения новых данных. В это время можно использовать алгоритм LRU. Основная идея заключается в следующем: если часть данных не использовалась в последний период, вероятность того, что она будет использована в будущем, также очень мала, поэтому ее можно исключить.
Реализуйте простой алгоритм LRU, используя java
public class LRUCache<k, v> {
//容量
private int capacity;
//当前有多少节点的统计
private int count;
//缓存节点
private Map<k, Node<k, v>> nodeMap;
private Node<k, v> head;
private Node<k, v> tail;
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) {
Node<k, v> node = nodeMap.get(key);
if (node == null) {
if (count >= capacity) {
//先移除一个节点
removeNode();
}
node = new Node<>(key, value);
//添加节点
addNode(node);
} else {
//移动节点到头节点
moveNodeToHead(node);
}
}
public Node<k, v> get(k key) {
Node<k, v> node = 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(Node<k, v> node) {
Node pre = node.pre;
Node next = node.next;
pre.next = next;
next.pre = pre;
node.next = null;
node.pre = null;
}
private void addNode(Node<k, v> node) {
//添加节点到头部
addToHead(node);
nodeMap.put(node.key, node);
count++;
}
private void addToHead(Node<k, v> node) {
Node next = head.next;
next.pre = node;
node.next = next;
node.pre = head;
head.next = node;
}
public void moveNodeToHead(Node<k, v> node) {
//从链表里面移除
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;
}
}
}
Приведенный выше код реализует простой LUR-алгоритм, код очень простой, к тому же он аннотирован, его легко понять, если внимательно посмотреть.
Реализация LRU в Redis
Приблизительный алгоритм LRU
Redis использует приблизительный алгоритм LRU, который отличается от обычного алгоритма LRU. Приближенный алгоритм LRU исключает данные путем случайной выборки, каждый раз случайным образом генерируя 5 ключей (по умолчанию) и удаляя из них последний использованный ключ.
Количество выборок может быть изменено параметром maxmemory-samples: Пример: maxmemory-samples 10 Чем больше конфигурация maxmenory-samples, тем ближе результат исключения к строгому алгоритму LRU.
Чтобы реализовать приблизительный алгоритм LRU, Redis добавляет к каждому ключу дополнительное 24-битное поле для хранения времени последнего доступа к ключу.
Redis3.0 оптимизация приблизительного LRU
Redis3.0 внесла некоторые оптимизации в приблизительный алгоритм LRU. Новый алгоритм будет поддерживать пул кандидатов (размер 16), данные в пуле сортируются по времени доступа, ключи, выбранные случайным образом в первый раз, будут помещены в пул, а ключи, выбранные случайным образом каждый раз, будут выбирается только тогда, когда время доступа меньше пула. Минимальное время будет помещено в пул, пока пул кандидатов не будет заполнен. Когда он заполнен, если необходимо ввести новый ключ, ключ с самым длительным временем доступа (самый последний доступ) в пуле будет удален.
Когда его необходимо устранить, просто выберите из пула ключ с наименьшим временем доступа (самый длинный недоступный) и удалите его.
Сравнение алгоритмов LRU
Мы можем сравнить точность каждого алгоритма LRU с помощью эксперимента.Сначала добавьте определенное количество данных n в Redis, чтобы израсходовать доступную память Redis, а затем добавьте n/2 новых данных в Redis. , нам нужно исключить его часть.Согласно строгому алгоритму LRU, должны быть исключены первые n/2 данных. Создайте сравнительную диаграмму следующих алгоритмов LRU (Источник изображения):
Вы можете видеть, что на графике есть три точки разного цвета:- Светло-серый - устранены данные
- Серый - старые данные, которые не были устранены
- Зеленый — недавно добавленные данные
Мы видим, что количество выборок Redis 3.0, равное 10, создает граф, наиболее близкий к строгому LRU. А также с использованием 5 образцов Redis3.0 также лучше, чем Redis2.8.
LFU-алгоритм
Алгоритм LFU — это новая стратегия исключения, добавленная в Redis 4.0. его полное названиеLeast Frequently Used, его основная идея состоит в том, чтобы исключить ключи в соответствии с частотой недавних обращений к ключам, те, к которым редко обращаются, удаляются в первую очередь, а те, к которым обращаются чаще, сохраняются.
Алгоритм LFU может лучше представить, насколько активен доступ к ключу. Если вы используете алгоритм LRU, к ключу долгое время не обращались, а обращались только изредка, то он считается горячими данными и не будет устранен, а некоторые ключи, вероятно, будут доступны в будущем. был ликвидирован. Это не тот случай, если используется алгоритм LFU, потому что его однократное использование не делает ключ горячими данными.
Есть две стратегии для LFU:
- volatile-lfu: Используйте алгоритм LFU для устранения ключа в ключе с установленным временем истечения срока действия.
- allkeys-lfu: использовать алгоритм LFU для удаления данных во всех ключах.
Установка и использование этих двух стратегий исключения такие же, как и предыдущая, но следует отметить, что двухнедельная стратегия может быть установлена только в Redis4.0 и выше, и будет сообщено об ошибке, если она будет установлена ниже Redis4. 0
проблема
Наконец, я оставлю небольшой вопрос. Некоторые люди могли заметить. Я не объяснял, почему Redis использует приблизительный алгоритм LRU вместо точного алгоритма LRU. Вы можете дать свой ответ в области комментариев, и мы можем обсудить и изучить вместе .
использованная литература:
Redis.IO/topics/например - ...