Привет, я использую phpBB с 2004 года, поэтому сейчас переносим форум довольно крупного размера. Сейчас я нахожусь на этапе 303139/2167314 (14%), скорость — 446 записей в минуту. Как можно ускорить процесс? Я работаю на Digital Ocean, загрузка CPU составляет всего 4%. Redis постоянно выдаёт таймауты. Вложения отключены.
Несколько полезных деталей помогут сузить круг поиска:
- Размер Droplet: объем RAM, количество vCPU, тип и размер диска
- Точная команда импорта, которую вы выполняете
- Настройки ресурсов в файле
app.yml(с удаленными секретами), особенно:UNICORN_WORKERSdb_shared_buffersdb_work_mem
- Запущен ли импорт внутри стандартного Docker-контейнера Discourse
- Любые сообщения о таймауте Redis или фрагменты логов
- Расположение базы данных: локально в том же контейнере или внешняя
Одно важное замечание: параметр UNICORN_WORKERS, скорее всего, не ускорит импорт значительно, поскольку импорт phpBB не обслуживается в основном через веб-воркеры. Его увеличение может лишь привести к большему потреблению RAM. Настройки памяти PostgreSQL и операции ввода-вывода диска, вероятно, имеют большее значение.
Поскольку загрузка процессора составляет всего около 4%, проблема может быть связана с ограничением ввода-вывода, производительностью базы данных или ожиданием Redis, а не с нехваткой вычислительной мощности. Таймауты Redis стоит исследовать отдельно.

Мой обновленный лог
script/import_scripts/phpbb3.rb:15:in ‘’
302570 / 2167314 ( 14.0%) [448 элементов/мин] Исключение при создании поста 304683. Пропуск.
Ожидание 1,0 секунды
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection/buffered_io.rb:214:in ‘block in RedisClient::RubyConnection::BufferedIO#fill_buffer’
internal:kernel:168:in ‘Kernel#loop’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection/buffered_io.rb:197:in ‘RedisClient::RubyConnection::BufferedIO#fill_buffer’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection/buffered_io.rb:187:in ‘RedisClient::RubyConnection::BufferedIO#ensure_remaining’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection/buffered_io.rb:152:in ‘RedisClient::RubyConnection::BufferedIO#getbyte’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection/resp3.rb:113:in ‘RedisClient::RESP3.parse’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection/resp3.rb:50:in ‘RedisClient::RESP3.load’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/ruby_connection.rb:97:in ‘RedisClient::RubyConnection#read’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/connection_mixin.rb:37:in ‘RedisClient::ConnectionMixin#call’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client.rb:374:in ‘block (2 levels) in RedisClient#call_v’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client/middlewares.rb:16:in ‘RedisClient::BasicMiddleware#call’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client.rb:373:in ‘block in RedisClient#call_v’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client.rb:781:in ‘RedisClient#ensure_connected’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-client-0.28.0/lib/redis_client.rb:372:in ‘RedisClient#call_v’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-5.4.0/lib/redis/client.rb:90:in ‘Redis::Client#call_v’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/rack-mini-profiler-4.0.1/lib/mini_profiler/profiling_methods.rb:90:in ‘block in Redis::Client#profile_method’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-5.4.0/lib/redis.rb:152:in ‘block in Redis#send_command’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-5.4.0/lib/redis.rb:151:in ‘Monitor#synchronize’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-5.4.0/lib/redis.rb:151:in ‘Redis#send_command’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-5.4.0/lib/redis/commands/scripting.rb:110:in ‘Redis::Commands::Scripting#_eval’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/redis-5.4.0/lib/redis/commands/scripting.rb:97:in ‘Redis::Commands::Scripting#evalsha’
/var/www/discourse/lib/discourse_redis.rb:38:in ‘Kernel#public_send’
/var/www/discourse/lib/discourse_redis.rb:38:in ‘block in DiscourseRedis#method_missing’
/var/www/discourse/lib/discourse_redis.rb:29:in ‘DiscourseRedis.ignore_readonly’
/var/www/discourse/lib/discourse_redis.rb:38:in ‘DiscourseRedis#method_missing’
/var/www/discourse/lib/discourse_redis.rb:270:in ‘DiscourseRedis::EvalHelper#eval’
/var/www/discourse/lib/distributed_mutex.rb:82:in ‘DistributedMutex#get_lock’
/var/www/discourse/lib/distributed_mutex.rb:50:in ‘block in DistributedMutex#synchronize’
/var/www/discourse/lib/distributed_mutex.rb:49:in ‘Thread::Mutex#synchronize’
/var/www/discourse/lib/distributed_mutex.rb:49:in ‘DistributedMutex#synchronize’
/var/www/discourse/lib/distributed_mutex.rb:34:in ‘DistributedMutex.synchronize’
/var/www/discourse/lib/post_creator.rb:410:in ‘PostCreator#transaction’
/var/www/discourse/lib/post_creator.rb:200:in ‘PostCreator#create’
/var/www/discourse/script/import_scripts/base.rb:611:in ‘ImportScripts::Base#create_post’
/var/www/discourse/script/import_scripts/base.rb:555:in ‘block in ImportScripts::Base#create_posts’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/rack-mini-profiler-4.0.1/lib/patches/db/mysql2/alias_method.rb:8:in ‘Mysql2::Result#each’
/var/www/discourse/vendor/bundle/ruby/3.4.0/gems/rack-mini-profiler-4.0.1/lib/patches/db/mysql2/alias_method.rb:8:in ‘Mysql2::Result#each’
/var/www/discourse/script/import_scripts/base.rb:542:in ‘ImportScripts::Base#create_posts’
/var/www/discourse/script/import_scripts/phpbb3/importer.rb:212:in ‘block in ImportScripts::PhpBB3::Importer#import_posts’
/var/www/discourse/script/import_scripts/base.rb:943:in ‘block in ImportScripts::Base#batches’
internal:kernel:168:in ‘Kernel#loop’
/var/www/discourse/script/import_scripts/base.rb:942:in ‘ImportScripts::Base#batches’
/var/www/discourse/script/import_scripts/phpbb3/importer.rb:293:in ‘ImportScripts::PhpBB3::Importer#batches’
/var/www/discourse/script/import_scripts/phpbb3/importer.rb:208:in ‘ImportScripts::PhpBB3::Importer#import_posts’
/var/www/discourse/script/import_scripts/phpbb3/importer.rb:38:in ‘ImportScripts::PhpBB3::Importer#execute’
/var/www/discourse/script/import_scripts/base.rb:47:in ‘ImportScripts::Base#perform’
/var/www/discourse/script/import_scripts/phpbb3/importer.rb:22:in ‘ImportScripts::PhpBB3::Importer#perform’
script/import_scripts/phpbb3.rb:35:in ‘module:PhpBB3’
script/import_scripts/phpbb3.rb:16:in ‘module:ImportScripts’
script/import_scripts/phpbb3.rb:15:in ‘’
333919 / 2167314 ( 15.4%) [441 элементов/мин]
Похоже, работает, жалоб нет.
на данный момент
остановил unicorn
отключил вложения и аватары
Размер droplet выглядит достаточно мощным для такого импорта, поэтому я не ожидаю, что UNICORN_WORKERS станет здесь основным ограничителем.
Несколько наблюдений:
- Остановка Unicorn, вероятно, допустима для контейнера, предназначенного только для импорта или тестирования, но это вряд ли значительно ускорит сам процесс импорта.
- Отключение вложений и аватаров должно исключить два самых медленных этапа, поэтому, если вы всё ещё получаете лишь около 440 постов в минуту, узким местом может быть ввод-вывод базы данных, сторона запросов MySQL в исходном phpBB или задержки Redis/PostgreSQL.
- Строку лога стоит внимательно отслеживать:
Exception while creating post 304683. Skipping.
Хотя импорт продолжается, это означает, что как минимум этот пост был пропущен. Если это происходит repeatedly, финальная миграция может оказаться неполной.
Часть с Redis выглядит как тайм-аут клиента Redis в 1 секунду во время распределённой блокировки мьютекса в Discourse, пока PostCreator создаёт пост. Стоит проверить, действительно ли Redis перегружен, или же тайм-аут просто слишком агрессивен во время длительного импорта.
Полезными следующими шагами будут проверки:
free -h
df -h
iostat -xz 1
vmstat 1
redis-cli INFO memory
redis-cli INFO stats
redis-cli SLOWLOG GET 20
Также, находится ли база данных MySQL phpBB локально на том же droplet или читается по сети? Поскольку стек вызовов итерируется через mysql2, медленная исходная база данных или медленный диск могут удерживать использование CPU низким, пока импортёр ожидает.
При текущей скорости, от 333919 из 2167314 примерно по 441 элементу в минуту, у вас остаётся примерно 69 часов, так что импорт может завершиться, но меня в первую очередь беспокоит, не вызывают ли эти исключения тайм-аутов Redis пропуск постов.
Я не рекомендую увеличивать UNICORN_WORKERS. При запуске, предназначенном только для импорта, Unicorn в основном не имеет значения. Главное — импорт продолжается, но пропускает посты, и именно на это стоит обратить особое внимание.