Обновление образа Docker: Redis 6 и уменьшение размера образа на 25%

Мы только что выпустили новый образ контейнера, который будет использоваться при следующем запуске команды ./launcher rebuild app. Как всегда, вам не нужно изменять вашу конфигурацию, если вы следовали нашей официальной стандартной инструкции по установке Discourse. Тем не менее, появились новые функции, которые помогут некоторым установкам.

Redis 6

Мы активно используем Redis во многих компонентах Discourse: для кэширования, Sidekiq, MessageBus, распределённых блокировок, ограничения скорости и так далее. В целом, это был надёжный выбор для нас.

Однако при определённых рабочих нагрузках Redis может стать узким местом. Из-за однопоточной природы Redis, а также невозможности использовать несколько экземпляров из-за наших LUA-скриптов, это стало серьёзным ограничением, которое трудно обойти.

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

Таким образом, если вы работаете на машине с большим количеством ядер процессора и метрики показывают, что Redis не справляется с нагрузкой, теперь вы можете включить использование потоков для операций записи через секцию параметров в файле app.yml:

params:
  redis_io_threads: "4" # 1 отключает, n > 1 использует n-1 дополнительных потоков для записи операций ввода-вывода

Уменьшенный размер образа

На раннем этапе проекта мы решили выпускать большой образ контейнера, чтобы облегчить запуск Discourse нетехническим пользователям и обеспечить поддержку всех необходимых зависимостей, версионирование, обновления и т. д.

Тем не менее, недавно размер сжатого образа превысил 1 ГБ, что стало слишком много.

Чтобы смягчить постоянно растущий размер образа, мы переместили исходный код Discourse из образа: вместо полной копии кода теперь используется “shallow clone”, содержащий только самую последнюю версию кода.

Это изменение уменьшило размер сжатого образа на 25%, что привело к снижению требований к дисковому пространству на сервере и ускорению пересборки при выпуске нового образа. Также это должно контролировать рост размера образа со временем.

Мы протестировали изменения на ветках tests-passed/beta/stable как при пересборках, так и при обновлениях через веб-интерфейс, и стандартные пути не нарушаются. Однако пользователи, выполняющие нестандартные операции с git в хуках app.yml, возможно, смогут адаптировать свои настройки.

42 лайка

Что происходит с опытом работы в браузере после такого обновления Redis? Оказывает ли это какое-либо влияние на кэшированные ресурсы? Очищается ли кэш в результате обновления?

3 лайка

Ничего.

Ресурсы сохраняются на локальном диске или в объектном хранилище и кэшируются в CDN. Redis на это не влияет.

Данные Redis сохраняются во время обновления.

10 лайков

Какое значение по умолчанию? 1?

5 лайков

Да. Это значение берется из собственного конфигурационного файла Redis, где 1 означает один поток, как в старой версии.

8 лайков

У меня возник случай, когда я добавил:

after_redis:
  - replace:
      filename: "/etc/redis/redis.conf"
      from: /^databases.*/
      to: "databases 50"

И пересборка не удаётся, потому что:

25:M 01 Dec 2020 20:21:08.830 # FATAL: Data file was created with a Redis server configured to handle
 more than 16 databases. Exiting

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

Хм. А теперь после, казалось бы, неудачной пересборки я вижу в логах docker следующее:

chgrp: invalid group: ‘syslog’
2 лайка

Зачем вам нужно больше одной базы данных?

3 лайка

Мультисайт. Несколько экземпляров используют один Redis. Вероятно, следовало бы использовать более универсальный контейнер Redis, но я решил придерживаться вашего.

2 лайка

:face_with_raised_eyebrow:

Разве multisite использует одну базу данных и стандартные пространства имён ключей Redis? Насколько я знаю, базы данных Redis — это тонкий слой, и у нас есть команды, работающие через их границы, поэтому полагаться на это не стоит.

6 лайков

Да, мультисайт использует одну базу данных

3 лайка

А, понятно. Значит, не мультисайт, а несколько экземпляров, работающих на одной машине, где каждому нужен отдельный Redis. Я просто увеличил значение по умолчанию с 16 до 50, потому что мне было лень тщательно следить за тем, какие базы данных Redis используются.

Получается, мне стоит запускать отдельный контейнер Redis для каждого экземпляра, да?

2 лайка

Да, иначе вы можете столкнуться с перекрёстным взаимодействием.

5 лайков

Ох. Черт.

К счастью, я узнал об этом на сервере, который используется только для тестирования.

А что делать с другими сайтами? Просто предоставить им новый Redis и выбросить запланированные задачи? Сделать резервную копию и восстановить?

Кстати, за последний год или около того я не заметил никаких проблем с перекрестными помехами. :man_shrugging: И к тому же есть способ настроить базу данных.

РЕДАКТИРОВАНИЕ: Ну, хорошая новость в том, что я могу зайти в контейнер, отредактировать redis.conf, перезапустить его, и всё снова заработает.

Если у вас есть подсказка, как перенести сайт с DISCOURSE_REDIS_DB: 12 из одного контейнера Redis в другой, буду рад услышать. Или, может быть, просто не стоит беспокоиться о запланированных задачах?

3 лайка

Верно. Discourse должен нормально пережить очистку Redis. Что-то теряется, но ничего критичного.

7 лайков

Вот что я думал, так как не знаю способа, которым резервные копии пытаются его восстановить (хотя я многое не знаю). Похоже, я мог бы сделать это так: https://stackoverflow.com/questions/23222616/copy-all-keys-from-one-db-to-another-in-redis, и, похоже, это сработало в только что проведённом мною тесте, но будет гораздо проще настроить мой playbook так, чтобы он просто создавал новый контейнер Redis и использовал его.

Спасибо.

Теперь нужно решить, запускать ли эти Redis на сервере базы данных или на веб-сервере…

3 лайка

Тогда что означает db_id: 2 в конфигурации мультисайта?

2 лайка

Устаревший параметр:

5 лайков

ЛОЛ. Да, это действительно запутанно!

Спасибо. Я работаю над темой «настройка мультисайта с Let’s Encrypt и без внешнего обратного прокси», и когда я закончу, я также приведу в порядок другую тему.

4 лайка

Просто убедитесь, что перезапустите Unicorn сразу после этого, чтобы он воссоздал запланированные задачи.
Вы потеряете всё, что находится в очереди, поэтому нужно выбрать подходящий момент для этого.

6 лайков

Работает ли это всё ещё как положено? Есть ли простая однострочная команда, чтобы узнать размер сжатого образа?

1 лайк