キュー実装に見る
排他処理
CodeIgniter Night 2
2017-02-14 @noldorinfo
自己紹介
• 竹腰彰成(たけこしあきしげ)
• Twitter: @noldorinfo
• http://blog.noldor.info/
2
今日のテーマ
• CodeIgniter4でキュー実装中です
• 仕様変更や機能追加するならリリース前のいまのうち
• レビュー的な意味でツッコミお願いします
3
キューとは
Queue
4
キュー(Queue)
• 先入れ先出し: First In First Out: FIFO
• 対義語はスタック(Last In First Out)
• ここテストに出ます(※基本情報技術者試験)
5
図はWikiPediaより
https://ja.wikipedia.org/wiki/FIFO
キューの利用用途
• フレームワークの場合、メッセージキューイング用途に使う
• 例)
• メール送信のリクエストをため込む
• PDF生成を別スレッドに処理させる
• つまり相手の応答を待たずに次の処理に移るために使う
• 何か重い処理をしたいが、今すぐでなくてよい
• 一方でブラウザにはすぐに応答したい
• キューに入れてしまおう
6
※パンクするのでメッセージを溜め込んではいけません
処理が異常終了してメッセージが消える
7
処理始めるのでキューからメッセージ消しますー
Fatal Error!
メッセージを残すと二重処理
8
処理始めます、終わるまでメッセージ消しませんー
別のスレッドが同じメッセージ取り出しちゃった!
重い、終わらない……
そこで排他処理
9
処理始めます、作業中のマーキングしますー
次のメッセージをやるねー
重い、終わらない……
こんなライブラリがほしい!
キュー実装がhelp wantedに
10
リクエストされているキューの種類
• RabbitMQ
• ググると利用事例が結構あるキューのミドルウェア
• Local File
• ミドルウェアなしでも動かしたいらしい
• Local Database
• Webサーバが複数でもRDBで実装できていればいいよね
• Redis、Memcached
• Webサーバが複数でもKVSで実装できていればいいよね
11
RabbitMQでの排他処理
• Message Acknowledgment (ACK)
• RDBのトランザクションのようなもの
• 作業中はセッションつなげっぱなし、終わったらACKを投げる
• ACKが戻る前にセッションが切れたら異常終了とみなす
• セッションにタイムアウトはないので重い処理もできる
12
メッセージ取得
終わったら知らせる
セッション持ったまま処理
RDBでRabbitMQのマネはできない
• RDBならトランザクションでやれば楽だよね!
異常時にはロールバックできるし!
⇒行ロック・テーブルロック持ちっぱなし問題発生
13
メッセージ取得
終わったらcommit
セッション持ったまま処理
DBへの負荷が!
トランザクションを使わない排他処理
• UPDATEしてaffected rows > 0ならロックできた、とみなす
• SQLが1行で済むのでアトミック性は確保できている
• 異常終了は検知できないのでタイムアウト処理を作る必要あり
14
まだ確認できてないこと
• Radis/Memcachedで同じようなことできるの?
• 長時間セッション張っていいの?
• FIFOできるの?
• ググると実装はあるらしい
• ローカルファイルで汎用実装だとflock()だよね……
• flock()は信用ならんイメージがある
• mkdir()による代替実装って今どきやるのか?
アドバイスください!
15
ご清聴ありがとうございました
16

2017 02-14 キュー実装に見る排他処理