• トップ
  • ブログ一覧
  • Solr で commitWithin を使ってみた
  • Solr で commitWithin を使ってみた

    はじめに

    今回はSolrにおいて、アプリケーション側からコミット制御を行う際に使われるcommitWithinの挙動について紹介します。

    Solrではドキュメントを追加(add)しても即座に検索に反映されず、データをいつ検索できる状態にするかを制御する必要があります。この反映タイミングを決める仕組みがcommitcommitWithinです。

    業務で大量のデータを扱う中で、アプリケーション側から明示的にcommitを多発すると、タイムアウトやパフォーマンス低下 を引き起こすケースがありました。

    そこで今回は、commitWithinを使ってSolr に「◯秒以内に commit してね」と任せる方法をシンプルなコード例で紹介します!

    commitとcommitWithinの違い

    Solrではデータを追加しても、すぐには検索結果に反映されません。その反映タイミングを決めるのがcommitcommitWithin です。

    項目commitcommitWithin
    タイミング即時反映指定時間以内に反映
    処理方式同期非同期
    向いている場面少量データ大量データ・バッチ処理

    commit は「今すぐ検索に反映して!」という命令。

    一方 commitWithinは「今すぐじゃなくていいから、◯秒以内に反映してね」とSolrに任せる命令です。

    大量データを扱うときは、アプリケーション側で細かくcommitを制御するよりも、commitWithinでSolrに任せる方が安定して動作し、一定時間後には確実に反映 されます。

    commitWithinがHard CommitではなくSoft Commitなのか

    commitWithinは「一定時間以内に検索可能にする」ための機能であり、検索反映の保証を目的としています。

    一方で、Hard Commitはディスクへの永続化を伴う重い処理であり、頻繁に実行するとSolr全体のパフォーマンスが大きく低下してしまいます。

    そのため、commitWithinは検索反映に適したSoft Commitを使用され永続化はautoCommit(定期的に実行されるHard Commit)が担当するという明確な役割分担になっています。

    コード例:commitWithinを10秒で指定してみる

    commitWithin を使うと、Solrに「◯秒以内に検索可能にしてね」と伝えることができます。
    以下のコードは、commitWithin=10000(10秒)を指定して動作を確認する簡単な例です。

    1namespace :solr do
    2  desc 'commitWithin の動作確認'
    3  task commit_within_demo: :environment do
    4    logger = Logger.new($stdout)
    5    solr = RSolr.connect(url: 'http://solr_blog_2:8983/solr/blog_2_core')
    6
    7    logger.info('==============[START] commitWithin デモ開始==============')
    8
    9    # ① 初期登録
    10    solr.add({ id: 1, title: '初期登録' })
    11    solr.commit
    12    logger.info('初期データ登録 & commit 完了')
    13
    14    # ② 登録内容確認
    15    initial = solr.get('select', params: { q: 'id:1' })['response']['docs']
    16    logger.info("現在の検索結果: #{initial}")
    17
    18    # ③ commitWithin で非同期更新
    19    solr.add({ id: 1, title: '値更新' }, params: { commitWithin: 10000 })
    20    logger.info('commitWithin=10000ms で add 送信')
    21
    22    # ④ 即時検索(未反映想定)
    23    now = solr.get('select', params: { q: 'id:1' })['response']['docs']
    24    logger.info("即時検索結果: #{now}")
    25
    26    # ⑤ 5秒待って再検索(未反映想定)
    27    sleep 5
    28    later = solr.get('select', params: { q: 'id:1' })['response']['docs']
    29    logger.info("5秒後の検索結果: #{later}")
    30
    31    # ⑥ 更に6秒待って再検索(反映想定)
    32    sleep 6
    33    later = solr.get('select', params: { q: 'id:1' })['response']['docs']
    34    logger.info("6秒後の検索結果: #{later}")
    35
    36    logger.info('==============[FINISH] commitWithin デモ完了!==============')
    37  end
    38end

    反映までの流れ
    実際に実行してみると、以下のようなログが出力されました👇

    1I, [2025-10-20T07:19:41.282601 #140] INFO -- : ==============[START] commitWithin デモ開始==============
    2I, [2025-10-20T07:19:41.510604 #140] INFO -- : 初期データ登録 & commit 完了
    3I, [2025-10-20T07:19:41.520535 #140] INFO -- : 現在の検索結果: [{"id"=>"1", "title"=>["初期登録"], "_version_"=>1846484435064586240, "_root_"=>"1"}]
    4I, [2025-10-20T07:19:41.539103 #140] INFO -- : commitWithin=10000ms で add 送信
    5I, [2025-10-20T07:19:41.543181 #140] INFO -- : 即時検索結果: [{"id"=>"1", "title"=>["初期登録"], "_version_"=>1846484435064586240, "_root_"=>"1"}]
    6I, [2025-10-20T07:19:46.557352 #140] INFO -- : 5秒後の検索結果: [{"id"=>"1", "title"=>["初期登録"], "_version_"=>1846484435064586240, "_root_"=>"1"}]
    7I, [2025-10-20T07:19:52.573803 #140] INFO -- : 6秒後の検索結果: [{"id"=>"1", "title"=>["値更新"], "_version_"=>1846484435237601280, "_root_"=>"1"}]
    8I, [2025-10-20T07:19:52.574023 #140] INFO -- : ==============[FINISH] commitWithin デモ完了!==============

    結果として、即時では反映されず約10秒後に更新が反映されました。

    このように、SolrはcommitWithin=10000と指定すると指定時間内にSoft Commitを実行してくれます。アプリケーション側で commitを毎回呼ばなくても、「◯秒以内に検索できるようにする」動きをSolrが保証してくれる 形です

    commitwithin=1ms(0.001秒)を指定した場合

    次に、commitWithin1msという非現実的な短い値を指定した場合の挙動を見てみます。

    1namespace :solr do
    2  desc 'commitWithin の動作確認(極端な値を指定した場合の挙動検証)'
    3  task commit_within_demo_2: :environment do
    4    logger = Logger.new($stdout)
    5    solr = RSolr.connect(url: 'http://solr_blog_2:8983/solr/blog_2_core')
    6
    7    logger.info('==============[START] commitWithin デモ開始==============')
    8
    9    # ① 初期登録(基準データ)
    10    solr.add({ id: 1, title: '初期登録' })
    11    solr.commit
    12    initial = solr.get('select', params: { q: 'id:1' })['response']['docs']
    13    logger.info("初期登録完了 → 検索結果: #{initial}")
    14
    15    # ② commitWithin に1msを指定して add 送信
    16    solr.add({ id: 1, title: '値更新(commitWithin=1ms)' }, params: { commitWithin: 1 })
    17    logger.info('commitWithin=1ms で add 送信')
    18
    19    # ③ 即時検索
    20    now = solr.get('select', params: { q: 'id:1' })['response']['docs']
    21    logger.info("即時検索結果: #{now}")
    22
    23    # ④ 数秒待って再検索
    24    sleep 2
    25    later = solr.get('select', params: { q: 'id:1' })['response']['docs']
    26    logger.info("2秒後の検索結果: #{later}")
    27
    28    logger.info('==============[FINISH] commitWithin デモ完了!==============')
    29  end
    30end

    反映までの流れ
    実際に実行してみると、以下のようなログが出力されました👇

    1I, [2025-10-20T07:34:29.126061 #142]  INFO -- : ==============[START] commitWithin デモ開始==============
    2I, [2025-10-20T07:34:29.479756 #142]  INFO -- : 初期登録完了 → 検索結果: [{"id"=>"1", "title"=>["初期登録"], "_version_"=>1846485366087876608, "_root_"=>"1"}]
    3I, [2025-10-20T07:34:29.502203 #142]  INFO -- : commitWithin=1ms で add 送信
    4I, [2025-10-20T07:34:29.509730 #142]  INFO -- : 即時検索結果: [{"id"=>"1", "title"=>["初期登録"], "_version_"=>1846485366087876608, "_root_"=>"1"}]
    5I, [2025-10-20T07:34:31.585763 #142]  INFO -- : 2秒後の検索結果: [{"id"=>"1", "title"=>["値更新(commitWithin=1ms)"], "_version_"=>1846485366324854784, "_root_"=>"1"}]
    6I, [2025-10-20T07:34:31.589721 #142]  INFO -- : ==============[FINISH] commitWithin デモ完了!==============

    結果として、エラーは発生せず正常に反映されました。
    ただし、実際の反映は約1〜2秒後であり、1msで即時反映されませんでした。

    ⚠️ 注意:commitWithinはSoft Commit(永続化はされない)

    commitWithin が実行するのはSoft Commitであり、これは「検索結果に反映させるための更新」であって、ディスクへの永続化(Hard Commit)ではありません。

    Soft Commit後すぐにSolrを再起動すると、反映済みに見えていたデータが失われる可能性があります。

    本番環境では通常、autoCommit(例:15秒ごとなど)で定期的にHard Commitが走る設定になっていますが、もし commitWithin のみで運用している場合は、永続化の保証がない点に注意が必要です。

    まとめ

    今回紹介したコードは、commitWithinの動きを理解するためのシンプルなデモです。実際の業務シナリオでも、Solrへの更新頻度やデータ量に応じてcommitcommitWithin を使い分けることで、安定したパフォーマンスと反映タイミングの最適化 が実現できます。

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!カジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background