#caching #redis #language-agnostic
#кэширование #redis #не зависит от языка
Вопрос:
Я использую Redis в качестве своего сервера кэша. Для наглядности я сохраняю пары ключ-значение, подобные 'S0007226_2005-07-09': '[15.3462, -1]'
. Запросы касаются конкретных ключей, а не основаны на диапазоне. Для запроса я использую клиент pyredis.
Мне часто приходится извлекать ~ 1 миллион ключей из кэша. Этот тип запроса слишком тяжелый для redis и занимает до 10 секунд. Загвоздка здесь в том, что MGET для n ключей в запросе — это операция O (n) (n — количество ключей в запросе). Я добавил таблицу для времени запроса из журналов.
| Keys | time(ms)|
| 703732 | 6869.66 |
| 26806 | 277.21 |
| 13180 | 137.41 |
| 400 | 5.83 |
| 2589 | 29.04 |
| 180 | 3.6 |
| 98413 | 1009.84 |
| 151994 | 1524.12 |
Это кажется очень нормальным, так как с увеличением количества ключей время увеличивается в O (n) направлении. Кроме того, я использую конвейер redis, разбивающий список ключей на куски по 10 Тыс.
Я хочу сократить время запроса до ~ 1 секунды или меньше. Если бы это был не Redis, я мог бы попытаться запросить параллельно и объединить результаты. Но, учитывая, что redis может работать только на одном ядре, в моем понимании это нецелесообразный вариант. Возможный выход:
- Внесите некоторые изменения в дизайн, чтобы мне не приходилось запрашивать миллион ключей в первую очередь.
- Используйте какой-либо другой инструмент вместо Redis для обработки нагрузки.
- Некоторая оптимизация в самой текущей настройке для лучшей обработки.
Предположим, мне нужно выбрать что-то из 2 и 3. Каковы мои варианты. Должен ли я попробовать какой-либо другой сервер кэширования, который предназначен для более высокой пропускной способности, или есть какая-то оптимизация, которую я могу сделать, либо в запросе / хранилище, либо в настройке, чтобы получить лучшие результаты.
Комментарии:
1. Просто что-то, что следует иметь в виду при отправке команд 10K в одном конвейере: когда вы используете конвейерную обработку, Redis будет помещать ответы в очередь на стороне сервера перед их отправкой обратно, что увеличит используемую память.
2. Здесь всего 100 команд, каждая с 10 тысячами ключей, но я понимаю вашу точку зрения. Однако, даже если я не использую конвейер, разве он не сохранит значения ключей в памяти перед их отправкой, которые в конечном итоге будут использовать тот же объем памяти?
3. Давайте рассмотрим приблизительную оценку в качестве примера: если у нас есть 100 ключей по 1 МБ каждый, мы используем около 100 МБ оперативной памяти. Если мы запустим конвейер и запросим эти 100 ключей в том же конвейере, мы будем использовать 100 МБ ключей плюс 100 МБ буферизованных ответов, поэтому использование оперативной памяти увеличится до ~ 200 МБ. После закрытия конвейера буферизованные 100 МБ сбрасываются, а использование оперативной памяти возвращается к ~ 100 МБ.
Ответ №1:
«Если бы это был не Redis, я мог бы попробовать запросить параллельно и объединить результаты».
Вы все еще можете запрашивать параллельно. Создайте настройку с несколькими мастерами и разделите / распределите свои ключи по нескольким мастерам. Затем вы можете параллельно запрашивать данные у нескольких основных устройств.
Я также могу сказать вам по опыту, что нет ничего быстрее, чем redis, поскольку это полностью однопоточный процесс в памяти. Итак, # 2 в вашем вопросе крайне маловероятен.
Я бы предпочел изменить дизайн, т. Е. # 1. Если нет, то выполните настройку с несколькими мастерами и запрос параллельно.
Ответ №2:
Я не думаю, что вам следует запрашивать 1 миллион ключей одновременно. Вы должны создать кэш с кешем в памяти и кешем Redis.
Вы должны запросить как:
- Поиск в локальном кэше
- Запрашивайте Redis только для ключей, которые недоступны.
Всегда используйте TTL, TTL поможет вам распределять ключевые запросы с течением времени, если вы считаете, что срок действия многих ключей может истечь одновременно, тогда добавьте случайную дельту в TTL.
Даже после выполнения этого, если вы видите проблему с производительностью с одним узлом Redis, используйте master-replica. Учитывая количество имеющихся у вас ключей, вам нужно иметь более 10 сегментов или около того.