要点: 動画プレイヤーが送るすべての進捗通知を、個別のDBトランザクションにする必要はありません。
この記事の用語: Write-behind:変更をまとめて後からDBへ保存する方式。冪等:繰り返しても結果が変わらない性質。
現場の課題
15秒ごとの小さな更新も、利用者が数千人になればロック、インデックス、レプリケーションへ大きな負荷を与えます。一方で、業務上必要なのは多くの場合、最新の安全な進捗だけです。
学習進捗は更新頻度が高い一方、価値は各書き込みではなく安全な最新状態にあります。複数端末、オフライン、ワーカー停止を含めても進捗が戻らないマージ規則が中心です。
設計と実装
- 進捗をRedisへ安全にマージできた時点でリクエストへ応答します。
- 再送されても進捗が戻らない、決定的なマージ規則を使います。
- 一定間隔でバッチ保存し、失敗したレコードだけを再試行します。
実装例
incoming = { userId, lessonId, position, completed, seq }
state = redis.HGET(progressKey)
if incoming.seq <= state.seq then return state end
next.position = incoming.position
next.completed = state.completed OR incoming.completed
next.seq = incoming.seq
redis.HSET(progressKey, next)
redis.ZADD(dirtyKey, now(), progressKey)
DB UPSERT ... WHERE stored_seq < next.seq本番導入の進め方
既存の書き込み経路を正として残し、Write-behindを並行実行して講座、セッション、端末ごとの差分を比較します。差分の理由と復旧手順を確認してから切り替えます。
まとめ
Write-behindは、マージ結果が決定的で、進捗が後退せず、保存遅延を測れる場合に有効です。
