Shogo's Blog

Oct 16, 2014 - 1 minute read - perl redis

Redis::Fast 0.13をリリースしました

Redis::Fast 0.13をリリースしました。 主な変更点は以下のとおりです。

  • passwordオプションの対応
  • maxclientsに達した場合に、deep recursion することがある問題の修正
  • トランザクション内で再接続処理が行われる問題の修正

passwordオプションの対応

今更感のある機能ですね。昔は対応してたんです。 対応してたんですが、Sentinel対応のために接続開始周りをごそっと入れ替えて、そのときに間違ってパスワード認証機能を削除しちゃってたっぽいです(・ω<) なんというかごめんなさい。

実際実装してテストしてみると、認証失敗したときにdouble freeで落ちてちょっとハマりました。 hiredisを使う場合はredisAsyncSetConnectCallbackに指定する関数内で、コネクションを切断するような処理(password認証とか)はしないようにしましょう。

maxclientsに達した場合に、deep recursion することがある問題の修正

Redis::Fastでは、接続処理の中で、コネクションに名前をつけたり、パスワード認証したり、その他独自の処理を実行しています。 この処理の途中でも再接続処理が走ってしまい、 再接続処理の中で再接続処理が実行されて、その再接続処理の中で再接続が… というような無限ループに突入する場合があります。 maxclientsに達した場合、一度コネクションの確立に成功したあとに接続が切られるので、この無限ループに入ってしまうようです。

接続処理中は再接続処理を行わないようにすることで対応しました。

トランザクション内で再接続処理が行われる問題の修正

Redis::Fast 0.07以降、MULTI-EXECコマンドを遣ったトランザクションの中にいるときは再接続処理が行わないようになっています。 その仕組みを作るにあたって、トランザクションの中にいるか外にいるかを表すフラグをコマンド送信前に更新していました。

  1. 再接続を禁止する
  2. MULTI コマンドを送る
  3. 結果を受け取る
  4. 必要なコマンド発行を行う
  5. 再接続を許可する
  6. EXECコマンドを実行する
  7. 結果を受け取る

しかしこれだと 5 と 6 の間で再接続が起こってしまいます。 EXECコマンドがまだ実行されていないので、ここはまだトランザクションの中ですね。

Redis::Fast 0.13ではフラグの更新はコマンドが成功したときに変更してあります。

  1. MULTIコマンドを送る
  2. 結果を受け取る
  3. 再接続を禁止する
  4. 必要なコマンド発行を行う
  5. EXECコマンドを実行する
  6. 結果を受け取る
  7. 再接続を許可する

これでトランザクション中に再接続処理が走ることは無いはずです。