こんにちは、2004 年から phpBB を利用しています。ある程度規模の大きいフォーラムの移行を行っています。現在、2 日経過し、303139/2167314(14%)、分間 446 のペースです。これをどのように高速化できますか?Digital Ocean を使用しており、CPU 使用率はわずか 4% です。Redis がタイムアウトを繰り返しています。添付ファイル機能は無効にしています。
絞り込むために、いくつかの有用な詳細情報があると役立ちます:
- Droplet のサイズ:RAM、vCPU 数、ディスクの種類/サイズ
- 実行している正確なインポートコマンド
- 機密情報を除外した
app.ymlのリソース関連設定、特に以下の項目:UNICORN_WORKERSdb_shared_buffersdb_work_mem
- インポートが標準的な Discourse Docker コンテナ内で実行されているかどうか
- Redis のタイムアウトメッセージやログ抜粋の有無
- データベースが同じコンテナ内のローカルか、外部にあるか
一点、注意点として:UNICORN_WORKERS を増やしてもインポート速度はあまり向上しない可能性があります。phpBB インポーターは主に Web ワーカーを通じて提供されるわけではないためです。増やしても単に RAM を多く消費するだけになるかもしれません。重要なのは PostgreSQL のメモリ設定とディスク I/O です。
CPU 使用率が約 4% しかない場合、これは CPU の不足ではなく、I/O 待ち、データベース待ち、あるいは 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 を停止しても問題ないかもしれませんが、インポータ自体の大幅な高速化にはつながらないでしょう。
- アタッチメントとアバターの無効化により、処理の遅い部分の 2 つが排除されるはずです。それでも約 440 投稿/分しか処理できていない場合、ボトルネックはデータベースの I/O、ソース側の phpBB MySQL クエリ、あるいは Redis/PostgreSQL の待機時間にある可能性があります。
- ログ行は注意深く監視する価値があります。
Exception while creating post 304683. Skipping.
インポートは継続していますが、少なくともその投稿はスキップされたことを意味します。これが繰り返し発生する場合、最終的な移行で投稿が欠落する可能性があります。
Redis 関連の部分は、PostCreator が投稿を作成している間に、Discourse の分散ミューテックスロックで Redis クライアントの 1 秒タイムアウトが発生しているように見えます。Redis が実際に過負荷になっているのか、それとも長時間のインポート中にタイムアウト設定が厳しすぎるのかを確認してください。
次に確認すべき有用なコマンドは以下の通りです。
free -h
df -h
iostat -xz 1
vmstat 1
redis-cli INFO memory
redis-cli INFO stats
redis-cli SLOWLOG GET 20
また、phpBB の MySQL データベースは同じ Droplet 上にローカルにあるのか、それともネットワーク経由で読み取られているのでしょうか?スタックトレースが mysql2 を介して反復処理を行っていることから、ソースデータベースが遅い場合やディスクが遅い場合、インポータが待機している間は CPU 使用率が低く抑えられることがあります。
現在の速度(333919 / 2167314、約 441 件/分)では、残り約 69 時間程度で完了する可能性がありますが、問題となるのは、これらの Redis タイムアウト例外によって投稿がスキップされていないかどうかです。
UNICORN_WORKERS を増やすことは推奨しません。インポート専用実行の場合、Unicorn はほとんど関係ありません。重要なのは、インポートが継続しているものの投稿がスキップされているという点であり、これが私が懸念する部分です。