Предложения по оптимизации Redis

Redis

Некоторые предложения по оптимизации

1. Попробуйте использовать короткие клавиши

Конечно, в то же время рационализации, не заканчивайте ключ "видеть имя и знать значение". Для значения некоторые из них также могут быть упрощены, например, пол с использованием 0, 1.

2. Избегайте использования ключей*

keys *, эта команда является блокирующей, т. е. никакие другие команды не могут быть выполнены в вашем экземпляре, пока выполняется операция. Когда количество ключевых данных в redis мало, это не беда, а количество данных очень плохое. Поэтому нам следует избегать использования этой команды. Вместо этого вы можете использовать SCAN.

3. Сжимайте данные перед их сохранением в Redis

Redis предоставляет два внутренних метода кодирования для каждого типа данных, и Redis автоматически настраивает соответствующий метод кодирования в различных ситуациях.

4. Установите срок действия ключа

Мы должны максимально использовать срок действия ключа. Например, некоторые временные данные (код подтверждения по СМС), Redis автоматически очистит для вас по истечении срока годности!

5. Выберите политику восстановления (maxmemory-policy)

Когда пространство экземпляра Redis заполнено, он попытается восстановить некоторые ключи. В зависимости от того, как вы его используете, настоятельно рекомендуется использовать стратегию volatile-lru (по умолчанию) — при условии, что вы установили тайм-аут для ключа. но если вы запустите что-то вродеcacheвещи, и для ключа нет механизма тайм-аута, вы можете рассмотреть возможность использования механизма перезапуска allkeys-lru, подробности см. maxmemory-samples 3 означает, что каждый раз при выполнении исключения будут случайным образом выбираться 3 ключа для исключения наименее часто используемых (опция по умолчанию)

maxmemory-policy шестью способами:

  • volatile-lru: выполнять LRU только для ключей с установленным сроком действия (значение по умолчанию)
  • allkeys-lru : удалить редко используемые ключи из всех ключей
  • volatile-random: случайным образом удалить ключ с истекающим сроком действия
  • allkeys-random: удалить случайным образом
  • volatile-ttl : удалить с истечением срока действия
  • noeviction : никогда не истекает, возвращает ошибку

6. Используйте операции на уровне битов и операций на уровне байтов, чтобы уменьшить ненужное использование памяти.

  • битовые операции: GETRANGE, SETRANGE, GETBIT и SETBIT
  • байтовые операции на уровне байтов: GETRANGE и SETRANGE

7. По возможности используйте хэши для хранения хэшей.

8. Когда бизнес-сценарий не требует сохраняемости данных, закрытие всех методов сохранения может обеспечить наилучшую производительность.

9. Вы можете использовать конвейеры, если хотите добавить несколько фрагментов данных за раз.

10. Ограничьте размер памяти Redis (64-битная система не ограничивает память, 32-битная система по умолчанию использует до 3 ГБ памяти)

Если объем данных непредсказуем, а память ограничена, попробуйте ограничить объем памяти, используемый Redis, чтобы избежать использования Redis с разделами подкачки или ошибками OOM. (Производительность раздела подкачки низкая. Если память ограничена, данные не могут быть добавлены после достижения указанной памяти, в противном случае будет сообщено об ошибке OOM. Вы можете установить политику maxmemory для удаления данных при нехватке памяти.)

11. SLOWLOG [получить/сбросить/удлинить]

  • slowlog-log-slower-than Определяет, сколько микросекунд (микросекунда, 1 секунда = 1 000 000 микросекунд) регистрируются команды.
  • slowlog-max-len Определяет максимальное количество журналов, которые может сохранить slowlog.Когда вы обнаружите, что производительность Redis снижается, вы можете проверить, какие команды вызывают это.

Анализ вариантов оптимизации

Тестирование производительности конвейера

Функция конвейера redis недоступна в командной строке, но redis поддерживает конвейеры и может использоваться в клиенте java (jedis):

img

образец кода

    //注:具体耗时,和自身电脑有关(博主是在虚拟机中运行的数据)
    /**
     * 不使用管道初始化1W条数据
     * 耗时:3079毫秒
     * @throws Exception
     */
    @Test
    public void NOTUsePipeline() throws Exception {
        Jedis jedis = JedisUtil.getJedis();
        long start_time = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            jedis.set("aa_"+i, i+"");
        }
        System.out.println(System.currentTimeMillis()-start_time);
    }

    /**
     * 使用管道初始化1W条数据
     * 耗时:255毫秒
     * @throws Exception
     */
    @Test
    public void usePipeline() throws Exception {
        Jedis jedis = JedisUtil.getJedis();

        long start_time = System.currentTimeMillis();
        Pipeline pipelined = jedis.pipelined();
        for (int i = 0; i < 10000; i++) {
            pipelined.set("cc_"+i, i+"");
        }
        pipelined.sync();//执行管道中的命令
        System.out.println(System.currentTimeMillis()-start_time);
    }

применение хеша

Пример: мы хотим сохранить данные объекта информации о пользователе, включая следующую информацию: ключ — идентификатор пользователя, значение — объект пользователя (имя, возраст, день рождения и т. д.). Если мы используем для хранения обычную структуру ключ/значение, в основном следующие два метода хранения:

  • Используйте идентификатор пользователя в качестве ключа поиска и инкапсулируйте другую информацию в объект для хранения в сериализованном виде.
    Недостатки: Увеличиваются накладные расходы на сериализацию/десериализацию.Когда для модификации одной информации вводится сложная адаптивная система (CAS), необходимо извлекать весь объект, а операция модификации должна защищать параллелизм.

img

  • Существует столько пар ключ-значение, сколько членов в объекте информации о пользователе.
    Хотя накладные расходы на сериализацию и проблемы параллелизма устранены, идентификатор пользователя сохраняется многократно.

img

  • Хеш, предоставленный Redis, очень хорошо решает эту проблему и предоставляет интерфейс для прямого доступа к этому члену карты. Ключ по-прежнему является идентификатором пользователя, значение — это карта, ключ этой карты — это имя атрибута члена, а значение — это значение атрибута. (Внутренняя реализация: существуют две разные реализации Value of Redis Hashd. Когда членов Hash немного, Redis будет использовать метод одномерного массива для компактного хранения, чтобы сэкономить память, вместо использования реального HashMap. структура, соответствующее значение redisObject. Кодировка — zipmap, и при увеличении количества членов она будет автоматически преобразована в настоящую HashMap, а кодировка — ht).

img

Оптимизация памяти в Instagram

Инстаграм может быть знаком каждому, нынешнее популярное приложение для фото имеет 300 миллионов активных пользователей в месяц. Четыре года назад, когда в Instagram хранилось более 300 миллионов изображений, нам нужно было решить проблему: мы хотели знать, кто автор каждого изображения (обратно проверить UID пользователя через идентификатор изображения), и скорость запроса должен был быть сопоставимым.Если вы поместите его в память, используйте структуру String как ключ-значение в:

HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
"939"

Тест: 1 миллион данных займет 70 МБ памяти, 300 миллионов фотографий займут 21 ГБ памяти. В то время (четыре года назад) для хранения лучше всего было использовать модель EC2 с большим объемом памяти (17 ГБ или 34 ГБ, 68 ГБ было слишком расточительно), но этого было недостаточно, чтобы поставить ее в модель 16G.

Разработчики Instagram спросили Питера Нордхуиса, одного из разработчиков Redis, о решении для оптимизации, и ответом было использование структуры Hash. Конкретный метод заключается в сегментации данных, и каждый сегмент сохраняется в хэш-структуре.

Поскольку структура хэша будет сжата и сохранена, когда один элемент хэша меньше определенного числа, это может сэкономить много памяти. Этого нет в приведенной выше структуре String. И это определенное число контролируется параметром hash-zipmap-max-entries в файле конфигурации. После экспериментов, когда для параметра hash-zipmap-max-entries установлено значение 1000, производительность выше, после того как команда HSET превысит 1000, потребление ЦП станет очень большим.

HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
"939"

Тест: 1 миллион потребляет 16 МБ памяти. Общее использование памяти также снизилось до 5 ГБ. Конечно, мы также можем оптимизировать и убрать медиабакет: длина ключа уменьшится на 12 байт.

HSET "1155" "315" "939"
HGET "1155" "315"
"939"

ВНИМАНИЕ оптимизация при запуске

Когда мы запускаем Redis, по умолчанию появляются следующие три предупреждения:

img

  • 1. МодификацияlinuxМаксимальное количество прослушивателей TCP в
WARNING: The TCP backlog setting of 511 cannot be enforced because 
/proc/sys/net/core/somaxconn is set to the lower value of 128.

В среде с высокой степенью параллелизма вам нужно большое значение невыполненной работы, чтобы избежать проблем с медленным подключением клиента. Обратите внимание, что ядро ​​Linux незаметно уменьшает это значение до значения /proc/sys/net/core/somaxconn, поэтому обязательно увеличьте somaxconn и tcp.maxsyn_backlog два значения для достижения желаемого эффекта.

echo 511 > /proc/sys/net/core/somaxconn

Примечание. Этот параметр не ограничивает максимальное количество подключений к Redis. Если вы хотите ограничить максимальное количество подключений Redis, вам нужно изменить maxclients, максимальное количество подключений по умолчанию равно 10000.

  • Во-вторых, изменить стратегию распределения памяти ядра Linux.
错误日志:WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. 
To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or 
run the command 'sysctl vm.overcommit_memory=1'

Причина: Когда Redis выполняет резервное копирование данных, он разветвляет дочерний процесс. Теоретически память, занимаемая дочерним процессом, такая же, как и у родительского. Например, память, занимаемая родителем, составляет 8 ГБ. В настоящее время 8G памяти также должно быть выделено дочернему элементу.Если память не может быть предоставлена, это часто приводит к отключению сервера Redis или слишком высокой нагрузке ввода-вывода, что снижает эффективность. Таким образом, политика выделения памяти должна быть установлена ​​на 1 (это означает, что ядро ​​позволяет выделять всю физическую память независимо от текущего состояния памяти).

Существует три стратегии распределения памяти.

Дополнительные значения: 0, 1, 2.

  • 0 означает, что ядро ​​проверит, достаточно ли доступной памяти для процесса приложения; если памяти достаточно, приложение памяти разрешено; в противном случае приложение памяти дает сбой и процессу приложения возвращается ошибка.
  • 1. Сколько бы памяти ни требовалось, ее можно применить.
  • 2. Разрешается выделять только размер физической памяти и памяти подкачки (память подкачки обычно составляет половину физической памяти).
  • 3. Закройте прозрачные огромные страницы (THP)

THP приведет к тому, что блокировки памяти повлияют на производительность Redis, рекомендуется закрыть

Transparent HugePages :用来提高内存管理的性能
Transparent Huge Pages在32位的RHEL 6中是不支持的
执行命令 echo never > /sys/kernel/mm/transparent_hugepage/enabled
把这条命令添加到这个文件中/etc/rc.local

первоисточник

xiaoxiaomo -> http://blog.xiaoxiaomo.com/2016/05/02/Redis-%E4%BC%98%E5%8C%96%E8%AF%A6%E8%A7%A3/