- - PR -
Flyweightパターンで取得したキャッシュの更新
1
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-04-16 12:42
お世話になります。
Flyweightパターンで取得したインスタンスの更新について、よい実装方法をご存知の方ありましたら教えて頂けないでしょうか。 現在開発中のシステム(C/S型、c#で開発)で、処理を軽くするためにDBサーバから取得したマスタデータ(例えば、分類や区分マスタなど)をクライアントアプリがFlyweightパターンでクラス内部に格納して共有しようと考えています。 パフォーマンスのボルトネックがDBサーバへ接続するネットワーク負荷の可能性が高いためです。 これらのデータは滅多に変更や削除されないのですが、その可能性がないとも言えません。 そこで、それらのデータが変更された場合に各クライアントPCがそれを知ってクラス内部に格納しているインスタンスを更新する、といったことは可能なのでしょうか。 (DBに接続して、毎回レコードの更新日時などを見れば簡単に分かりますが、それだとパフォーマンスの向上が見込めません) それとも、少しでも変更の可能性があるデータに対しては、Flyweightパターンを絶対に用いるべきではないのでしょうか。 よろしくお願いいたします。 public class ItemType { private Dictionary<int, ItemType> mItemTypeList = new ・・・・・・; private int mNo; public int No { ・・・ } private string mName; public string Name { ・・・ } public static ItemType Get(int no) { //更新があったという何らかの通知を受けている //もしデータが変更されていた場合は //新しいインスタンスを生成して返す if(mItemTypeList.ContainKey(no) == true) { return mItemTypeList[no]; } //DB接続処理 //・・・ //・・・ } } | ||||||||||||||||
|
投稿日時: 2008-04-16 16:54
ネットワーク負荷?そうなんですか?(わからないですが考えにくいです)
Push的なのは、ちょと渋いと思います。 たまにPolling位で更新でよいのでは。。。 あと 最後はDBの言う所の楽観同時実行制御で勘弁していただく。。。 参考になればと思います。 | ||||||||||||||||
|
投稿日時: 2008-04-16 17:13
なぜ、Flyweight パターンを使おうと思ったのでしょうか?
ネットワーク負荷がボトルネックかどうかは確かめましたか? すなおにDB参照した場合のレスポンスタイムは、要件に見合わないほど遅いのですか?
パフォーマンスは、後回しでよいので、要件を確認しましょう。 - どの程度の頻度で、それらのデータが更新されるのですか? - アプリケーションの実行中に変更されるのですか? - 変更されたとき、入力途中のデータはどう扱うのですか? - すでににDBなどに永続化されているデータは、どう扱うのですか?
Flyweight の対象オブジェクトは、Immutable にするのが普通だと思います。 Immutable でないと使う側が楽できないので、Flyweight パターンの意図するメリットは受けられないでしょうね。 - 対象のデータは、enum で十分だったりしませんか? - データを永続化するときに、楽観ロックを利用するだけで十分ではありませんか? | ||||||||||||||||
|
投稿日時: 2008-04-16 18:17
「絶対」かどうかは分かりませんが、使わないほうが良いと思います。 私は Flyweight パターンというものは、あまり意識して使ったことはないのですが、おっしゃるような場合に意識して使うのは Observer パターンでしょう。 ただし、この場合、あるインスタンスが Observer でもあり Observable でもある、というようになってしまい、ややこしくなります。昔から、こういうようにややこしくなる原因は、DBMS を主体に考えているためだと思います。DBMS が Observable になれれば良いのですが、多くの場合、DBMS が自身の変更を外へ通知してくれるということはないからです。一部の DBMS 用の API にはそういう機能もあるのですが、あまり一般的ではないと思います。 Observable になれるデーター管理用のサーバーインスタンスを建てて、それがクライアントとやりとりし、サーバーインスタンスがトランザクションデーターを DBMS にコミットする、という作りにしたほうがツブシがきくと思います。 | ||||||||||||||||
|
投稿日時: 2008-04-16 18:22
ただ、こうすると、脇から、そのサーバーインスタンスをバイパスして、ダイレクトに DBMS にアクセスされると、データーに矛盾が生じてしまいます。DBMS を使う限り、この問題がつきまとってしまいます。ファイルだとアプリケーション以外のものがアクセスすることなんて考えなくても良いのですが、なぜだか DBMS だと、脇からアクセスされてしまうことを気にしなくてはならなくなるのも不思議です。DBMS を自分のアプリケーションでロックして使えれば良いのでしょうけど、将来そうできない可能性が少しでもあるならば、そのようなキャッシュの仕組みははじめからやらないようにしたほうが良いのかもしれません。 | ||||||||||||||||
|
投稿日時: 2008-04-16 22:36
・DBのデータを変更や削除するのはこのSだけ ・DBへの接続はボトルネックだが、C/S間の接続自体はボトルネックではない という前提があれば、Sが「インスタンスを更新する必要があるか」の情報を管理していれば Cは、必要ないときはC/S間のやり取りだけ、必要な場合はBDに接続、という風に作れますね。 | ||||||||||||||||
|
投稿日時: 2008-04-17 12:44
unibon様が仰っておられる通り、Observerパターンを使おうとも検討しましたが、システム自体が複雑な設計になったり、直接DBにアクセスされたりすると対処しようがありません。
また、holic様、indigo-x様、べる様から教えて頂いたように、要求をよく確認してどういう仕様になるのか再検討したいと思います。 皆様、大変参考になるご意見を多数頂き、まことにありがとうございます。 | ||||||||||||||||
|
投稿日時: 2008-04-25 21:15
(既に解決済みで見られていないかもしれませんが)
ADO.NET 2.0 のクエリ通知 http://www.microsoft.com/japan/msdn/vs05/adonet/querynotification.aspx があったのを思い出したので。。。。 参考になればと思います。 |
1