by shigemk2

当面は技術的なことしか書かない

メモ PerfectQueueはいかにパーフェクトか、あるいはRubyとMySQLでジョブキューを作る試みについて #tdtech

  • PerfectQueue
    • パーフェクトな分散キュー
  • worker scheduler consoleapiのやりとりで分散キュー
  • ジョブキューとは
    • first in frist out
  • At-least-once semantics
    • 最大1回実行
    • ジョブキューにRDBMSを使うべきか 使うべきなのでは
  • At-most-once

  • queueのテーブル構造 id timeout data created_at

    • created_atは完了したかどうかにしか使わないので。。。
  • dataへはJSONを入れること
  • タスクの取得はSQLでもできる

  • 実行中は定期的にハートビート

    • 途中で落ちたらやり直し
  • 完了したらcreated_at = NULLを入れる(っていうアーキはどうなの?という良心の呵責)

    • 一定期間物理削除しない
  • 完了済みタスクで、retention_timeを過ぎたら物理削除

  • 書く操作については、

  • Submit INSERTするだけ

  • Acquire 排他処理 すぐデッドロックされてしまう ジョブキューを作るときは気をつけよう MySQLの気持ちになりながらクエリを書くこと
    • FOR UPDATEを避ける
    • LOCK TABLES →全体をロックされるとパフォーマンスがやばい
    • get_lockがいちばん
    • と思うのですが、デッドロックされる
    • deleteとコンフリクトすること
      • 注意してクエリを書かないとデッドロックになる
  • Finish
  • Delete
    • 削除のタイミングでもGET_LOCK
    • すべてのワーカーを同時に起動するとしばらくのあいだ削除クエリが飛ばない
      • →削除待ちタスクが増えてスループットが低下するので、乱数分散してDELETEクエリを実行する
    • 削除待ちタスクと取得待ちタスクの存在する領域を分ける
      • 削除クエリのデッドロック対策が不要になること
      • 安定した速度でタスク処理が実行された
  • 突然発生したネットワーク遅延
    • スループットが3倍悪化する
    • →データ構造を変える
    • テーブル queueに、カラム ownerを追加する
    • select & markからmark & selectへ 性能が2.5倍へ
    • read lockとwrite lock
    • FOR UPDATE
  • MySQLの気持ちになって、どういうロックが使われているかを考えながら実装するとデッドロックになりづらい

まとめ

  • ジョブキューは重要だけど難しい
  • ロック絡みのSQLを書くときはMySQLの気持ちになって書くこと
  • ベンチマーク用にサンドボックスはひつよう

質疑

  • MySQLをジョブキューのインフラとして選んだこと
    • Amazonでサポートされているから
    • 自分であんまりメンテをしたくなかったから
    • ジョブキューを自前実装する必要性→Hiveの実行をジョブキューで制御したかった 他のライブラリではやりたいことが実現できなかった