Quantcast
Channel: ウィリアムのいたずらの、まちあるき、たべあるき
Viewing all articles
Browse latest Browse all 7270

セッション→Session in DB→NoSQL

$
0
0
ちょっとした温故知新



■セッションとその問題

 Webシステムにおいて、1つの取引情報(=ここでは、これをトランザクションとす

る)が数画面に渡るときが有る。このような場合、データ(ここでは取引情報)をセッ

ションに入れておく。この方法は、いまだに変わっていない。
 しかし以下のケースでは問題が起こる。

  ・負荷分散させた場合
  ・障害時
  ・タブブラウザ対応

●「負荷分散させた場合」について。
 例えばTomcatをA,B,Cという3台で走らせていたとする。そこに、Xさんがアクセスし

たとき、Xさんが、TomcatAにアクセスし、TomcatA上にセッションを作成した場合、次

からアクセスは、TomcatAにしかアクセスできない。B,CからAのセッションを見れない

から。つまり、セッションを作成した場合、トランザクション中は、他のマシンに分散

できなくなる。

●「障害時」について
 このとき、セッション情報も吹っ飛ぶ。
 したがって、TomcatをA,B,Cという3台で走らせていたとする。そこに、Xさんがアク

セスしたとき、Xさんが、TomcatAにアクセスし、TomcatA上にセッションを作成したの

ち、Aのマシンが壊れた場合、Aのマシンに有るXさんのセッションも吹っ飛ぶ。したが

って、B,Cが処理可能だとしても、Xさんは、データを入れなおさないといけない。

●「タブブラウザ対応」
 IEの場合、同一ブラウザでは、違うタブで開いても、同一のセッションになる。した

がって、ログイン後、「処理をいろいろした後」に、新しいタブを開いて、再度ログイ

ンしなおそうとしても、新しいタブは、「処理をいろいろした後」のセッション情報が

共有される



■問題解決としてのSession in DBと新たな問題

 この問題を解決する方法として、セッションデータをファイルまたはDBに落とすとい

う方法が考案された。

つまり、以下のようにする

・ログイン時に、唯一のIDを振る
  (今回は、これをトランザクションIDと呼ぶ。この説明用であり、
   一般的な言い方ではない)

 そして、ログイン時にセッションに入れたいような内容は、
   トランザクションIDをキーとして、(ファイルの場合ファイル名として)
   DB、ファイルに書き込む。
 次画面から、「必ず」このトランザクションIDをhiddenで送る。

・ログイン後、画面遷移する際、セッションを生成する箇所をラップし、

   セッションを生成するときに、
     トランザクションIDを引数から取り出し
       (hiddenで必ず送る=必ず引数に入っている)
     トランザクションIDを元に、前の画面のセッション内容を
        DB、ファイルから取り出し、
     セッション内容を、そのDB、ファイルの内容に書き換える

   セッションに何か書き込むところもラップし、
     セッションに書き込むと共に、
     トランザクションIDをもとに、セッション内容を
        DB、ファイルに書き込む
     →画面終了時に書きこんでも良い。

 このように、セッションを使うときのコーディング規約を決めて、
 守らせる

・ログアウト時、トランザクションIDを元に、データを削除する。
 また、一定時間アクセスのないものは、データを削除する
  →バッチで消してもいいし、だれかがセッションを生成したときに、
   いらないものを(他の人のものを含め消してしまう)

そして、セッションを書き込むファイルまたはDBは、どのTomcatでも
参照できるようにする。そうすると、

○TomcatAでXさんが作ったセッションは、トランザクションID 00001で
 ファイルに保存されたとすると、

・そのあと、負荷分散で、TomcatBでXさんのデータを処理しようとしたとき、
 送信内容にトランザクションID 00001と入っているので、XさんのAマシン
 でやった処理が継続される

・障害で、TomcatAからTomcatBで変わっても同じ

・タブブラウザの場合。
 はじめのタブでログインすると、トランザクションID 00001で処理
 される。タブを新たに開いてログインすると、トランザクションID
 00002とか、違う番号で振られる。セッションはトランザクションID
 に基づいて、サーバー側で入れ替えられるから、大丈夫・・・

  ・・・かって言うと、実はそうではなく、セッションは排他制御
  されない(たしか)。なので、この場合は、セッションに入れ替える
  のではなく、トランザクションIDをもとに、セッションを作り直したり、
  セッションに変わるデータ領域で頑張るなど、ちょっと工夫が居る。

 しかし、このような工夫はラップされているので、見えない
  →操作する人は、セッションと同じように操作できる。

ということで、めでたしめでたし。
とくにこのとき、DBにセッションデータを入れる方法を
Session in DBといった(と思う)

しかし、DBに入れる場合に問題が起きた

  ・DBに障害が起きたら?
  ・DBのアクセス数が増えることに問題はないのか?

つまり、この方法は、画面アクセスごとに、セッションデータの検索、
更新ごとに(ないしは画面アクセスごとに)セッションデータの保存
が起こる。検索時は検索データがネットワークに流れ、保存時は、
データがDBのほか、ログ(ジャーナル)にも書かれる。
この量がはんぱない場合、この手法は問題で、DBへのリスクを増やしかねない。

そして、DBに障害が起きたら、使えないジャン
という問題が起きた。
       


■NoSQLの利用

そこで、データを保存するDBとは別に、データを保管する場所を
持とうということになった。

この場合、NoSQLを利用して、単一の障害点をなくすようにしたり
することもできる。

インメモリDBだと、処理スピードもあがるとか期待できるかもしれない

Cassandraとかmemcachedの利用が考えられる。

しかし、この場合も問題がある。
CassandraのようなJavaで動くものの場合、
TomcatもCassandraもなんでもかんでもすべて・・・
となると、メモリが半端なく消費され、
フルガベージコレクションが起こる・・・と遅くなるし、
これを繰り返すと、最悪out of memoryになったりする。



■問題点と現状

フルガベージコレクションが起こることに対しては、
Interstageなどでは、予測して負荷分散する機能があるらしい。

ただ、遅くても大丈夫そうな場合、ファイルシステムをつかったり、

1箇所にデータアクセスが固まらないように、保存するセッションデータを
複数にわけて、シャーディングするなど、いろいろと、工夫の余地はありそうだ。


Viewing all articles
Browse latest Browse all 7270

Trending Articles