私は、タイプ別に保持ポリシーを定義するファクトリ(例:絶対有効期限または有効期限有効期限)を持つ自作データエンティティリポジトリを構築しました。このポリシーでは、キャッシュタイプをhttpcontext要求、セッション、またはアプリケーションとして指定します。 MemoryCacheは、3つのキャッシュタイプすべてのキャッシュプロキシによって維持されます。とにかく、私はロードして私たちのプライマリデータエンティティのために保存するリポジトリに関連付けられているデータエンティティサービスがあります。アイデアは、エンティティリポジトリを使用し、エンティティがデータソース(この場合はdb)からキャッシュまたは取得されているかどうかを気にする必要はありません。MemoryCacheを使用したデータリポジトリ
データソースからエンティティをロードする前に、キャッシュされたエンティティを保存する必要があるため、ロード/セーブイベントを同期させる必要があることは明白です。
は、だから私は、私が読ん:)今日はMemoryCacheと発射CacheItemRemovedCallbackイベント(デフォルト20から削除されたエンティティとの間に良好な長いギャップが存在することができます...今日の生産にデータの整合性の問題を調査していました秒)。ロードの周りにあった単純なロックとデータ操作の保存は不十分でした。さらに、CacheItemRemovedCallbackはHttpContextの外部にあるため、興味深いものになっていました。つまり、イベントに配置されたインスタンスを割り当てる可能性があるため、コールバック関数を静的にする必要がありました。
私は一度、データエンティティがキャッシュに存在しなくなったが、データソースに保存されていない可能性があるため、5000のうち3つの破損した注文を説明する可能性があることを認識しました。プライマリデータエンティティ上のポリシーの20分のスライディング有効期限を超えて作業を実行するのは簡単です。つまり、期限切れの同じ瞬間に、ロード(要求コンテキスト経由)と保存(キャッシュ期限切れのコールバックによる)との間の興味深い競争状態が発生した場合に起こります。
シンプルなロックでは、サイコロのロールだったので、勝利を救いますか?明らかに、データソース(db)からの次のロードの前に保存が必要です。理想的には、アイテムがキャッシュから期限切れになると、データソースにアトミックに書き込まれます。エンティティがキャッシュから削除されたが、まだ呼び出されていないコールバックが期限切れになっていると、ロード操作が実行される可能性があります。この場合、エンティティはキャッシュ内に検出されないため、デフォルトでデータソースからロードされます。ただし、保存操作が開始されていない可能性があり、データの整合性が損なわれ、現在保存されているキャッシュデータが破損する可能性があります。
私はEventWaitHandleを解決するために、名前付きのシグナリングロックが必要です。ユーザーごとに名前付きロックが作成されます(< 5000)。これにより、エンティティ(スレッドがHttpContext外の独自のコンテキストに存在する)を保存する期限切れイベントからの信号を待機することができます。したがって、保存では、既存の名前ハンドルをつかんで、保存が完了したらロードを続行するように指示するのは簡単です。
私はまた、タイムアウトしてセーブ操作によって各10秒ブロックを記録する冗長性も持っています。私が言ったように、デフォルトは、フォームから削除されたエンティティと、エンティティをセーブするイベントを発生させることを意識しているエンティティとの間の20秒を意味します。
すべてのことを通して私の話題に従った誰にもありがとう。同期要件の性質を考えれば、EventWaitHandleは最良のソリューションをロックしていましたか?
おそらくMemoryCacheを使用していますが、この方法はあまり良いデザインではありません。 –
ある種の複雑さを克服して、何か悪いデザインと呼ぶのは常に魅力的です。しかし、私はスレッド間のキャッシュを扱うことは不合理ではなく、上記のスレッドを同期させる必要があることも不合理であると主張します。 MemoryCacheに関して、私はそれをより良いものを発明しようとする価値があるとは思っていません。私は、その逆、あるいは代替案、またはより良い同期メカニズムについての議論を聞きたいです。 – codinglifestyle
おそらく[redis](https://redis.io/topics/introduction)がお手伝いします。 –