NCache、 インメモリ分散キャッシュ、読み取りおよび書き込み操作を高速化するために、データを一時ストレージにそのまま保持します。 私たちは見てきました NCache パフォーマンスに関しては驚異的なスピードを発揮します キャッシュ ストアに対する操作。 ただし、維持 NCache データの一貫性に関しては、メイン データ ソースとの同期が大きな課題となります。 データ ソースには任意のデータベースを使用できます。 ただし、このブログはキャッシュを PostgreSQL と同期させることを目的としています。
XNUMX つの別々のデータ コピー – 課題
アプリケーションのスタックは次のように動作します NCache キャッシュなどは、データベースとアプリケーションの間にキャッシュ層として存在します。 アプリケーションはキャッシュに直接接続されているため、読み取りや書き込みなどのすべての操作呼び出しがキャッシュに直接送信されます。 別のユーザーがキャッシュに通知せずにデータベース内の何かを変更したと仮定します。 これで、データベース内のデータはキャッシュに存在するデータとは異なります。 データの XNUMX つの別々のコピーにより、データの不整合が発生し、大きな課題となります。
NCache 詳細 NCache ドキュメント PostgreSQL とキャッシュを同期する
NCache データの同期を保つ
データの不整合という課題を考慮すると、 NCache 他のものと同じように、それに対する修正が急襲されます。 必要なのは、次を使用してキャッシュをデータベースと同期することです。 NCache データベースの同期 テクニック。 前述したように、このブログで説明するデータベースは PostgreSQL です。これは、よく開発された機能セットと高いパフォーマンスと信頼性を備えたオープン ソースのオブジェクト リレーショナル データベースです。 ソリューションを作成し、GitHub にアップロードしました。 キャッシュを PostgreSQL と同期する これは、キャッシュのスケーラビリティとデータの一貫性をどのように改善できるかを示しています。
以下の図は、その仕組みを示しています。 NCache データを PostgreSQL データベースと同期した状態に保つのに役立ちます。
同期しています NCache PostgreSQLデータベースを使用した場合
NCache を使用してデータを PostgreSQL と同期させます。 NotifyExtensibleDependency、これは、によって提供される同期技術です。 NCache キャッシュとデータベースの同期を維持します。 NotifyExtensibleDependency は、PostgreSQL 依存関係通知システムを使用したデータ無効化手法を実装するために使用されます。 PostgreSQL の依存関係は、次のような LISTEN/NOTIFY メカニズムに基づいて構築されています。 パブリッシュ/サブスクライブ モデル。
データベースへの依存に加えて、 リードスループロバイダー データソースと直接通信するために使用されます。 NCache プロバイダーを呼び出して、カスタム ロジックを使用してデータ ソースからデータを直接ロードします。 これにより、データの同期と最新性が保たれ、古いデータなどの問題が回避されるとともに、スケーラビリティが向上し、読み取り操作が高速化されます。
したがって、関係する基本コンポーネントは次のとおりです。
-
- NotifyExtensibleDependency: NCache NotifyExtensibleDependency 内で LISTEN を呼び出すことにより、特定のチャネルに登録します
Initialize
方法。 データベース上では、ペイロードをチャネルに送信する TRIGGER 関数が呼び出され、リッスン時にデータの不整合が発生した場合、データがキャッシュから削除されます。 - ReadThruProvider: このプロバイダーは、データベース内のデータが変更されると、更新されたデータをデータベースから直接自動的に取得します。
- NotifyExtensibleDependency: NCache NotifyExtensibleDependency 内で LISTEN を呼び出すことにより、特定のチャネルに登録します
NotifyExtensibleDependency を使用してキャッシュを同期する
NotifyExtensibleDependency PostgreSQL 依存関係のメカニズムを使用してデータを無効にするために使用されます。 Pub/Subメッセージング このモデルは Listen/Notify と呼ばれます。 このメカニズムによれば、データベース内の更新は、情報を含む追加のペイロードとともに NOTIFY コマンドを通じて特定のチャネルをリッスンしているクライアントに渡されます。 私たちの具体的なケースにおけるクライアントは次のとおりです NCache データベース内の変更について通知を受けると、対応する項目がキャッシュから削除されます。
以下のコードを見て、PostgreSQL の依存関係を使用して項目がどのように追加されるかを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
const string connectionString = "your-connection-string"; var customer = new Customer(); var cacheItem = new CacheItem(customer) { Dependency = new PostGreSQLDependency(connectionString, customer.customerid, "public", "customers", "customer_channel") }; var key = customer.customerid; var cache = CacheManager.GetCache("democache"); cache.Insert(key, cacheItem); |
ただし、実装については理解する必要があります。 PostgreSQLDependency
以下のコードが役に立ちます。 の Initialize
メソッドには、データベースに接続するための接続文字列が含まれており、特定のデータのデータ変更時に通知を登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public PostGreSQLDependency(string connectionString, string dependencyKey, string schema, string table, string channel) { _connectionString = connectionString.Trim(); _dependencyKey = dependencyKey.Trim(); _schema = schema.Trim(); _table = table.Trim(); _channel = channel.Trim(); } public override bool Initialize() { connection = new NpgsqlConnection(_connectionString); connection.Open(); ((NpgsqlConnection)connection).Notification += (o, e) => { var entity = JsonConvert.DeserializeObject(e.AdditionalInformation); if (entity.DependencyKey == _dependencyKey && entity.Table == _table && entity.Schema == _schema) { done = true; } }; using (var cmd = new NpgsqlCommand($"LISTEN {_channel};", (NpgsqlConnection)connection)) { cmd.ExecuteNonQuery(); } task = Task.Run(() => { while (true) { ((NpgsqlConnection)connection).Wait(); if (done) { break; } } this.DependencyChanged.Invoke(this); }); return true; } |
NCache 詳細 NCache ドキュメント PostgreSQL とキャッシュを同期する
リードスルーを使用したデータの自動リロード
依存関係を使用すると、データ ソース内でデータが変更されるたびに、そのデータがキャッシュからクリアされます。 ただし、そのデータもキャッシュに再ロードする必要があります。 NCache と呼ばれる機能があります バッキングソース。 実装にカスタム ロジックを自由に追加できるリードスルー プロバイダーを提供します。 指定された場合、リードスルー プロバイダーは PostgreSQL データベースからデータを読み込みます。 必要がある リードスループロバイダーを構成する 以前に管理ツールを使用していました。
リードスルー プロバイダーで再同期オプションを使用すると、データとデータベースの同期が維持されます。 ただし、内部では、 ProviderCacheItem
、CacheItem には依存関係が追加されています。これは、キャッシュに追加された新しい項目には、すでに追加された依存関係が含まれていることを意味します。 依存関係を何度も追加する手間が省けます。 見てください LoadFromSource
Read-Through プロバイダー内のメソッドを使用して実装を確認します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public ProviderCacheItem LoadFromSource(string key) { var query = $"SELECT customerid, address, country, city FROM customers WHERE customerid = '{key}'"; // Define a query returning a single row result set NpgsqlCommand command = new NpgsqlCommand(query, _connection as NpgsqlConnection); var reader = command.ExecuteReader(); ProviderCacheItem providerCacheItem = null; while (reader.Read()) { if (providerCacheItem == null) { var customer = new Customer() { customerid = reader[0] as string, address = reader[1] as string, country = reader[2] as string, city = reader[3] as string, }; providerCacheItem = new ProviderCacheItem(customer) { Dependency = new PostGreSQLDependency(_connectionString, customer.customerid, "public", "customers", "customer_channel"), ResyncOptions = new ResyncOptions(true) }; } } } |
リードスルーを使用して項目を追加すると、次を使用して、変更された項目をキャッシュに直接ロードするだけです。 データベースの依存関係。 したがって、キャッシュは PostgreSQL データベースと同期されたままになり、古いデータの問題はすべて解消されます。
まとめ
ブログの内容を簡単に言うと、キャッシュとデータベースは相互に同期を保つ必要があります。 データベース内で行われた変更をキャッシュが認識しない場合、アプリケーションは動作を継続し、古いキャッシュ データを使用して動作する可能性があります。 この問題は次のように非常に効率的に解決されます NCache PostgreSQL の依存関係機能。 他にも素晴らしい機能がたくさんあります。 NCache ウェブサイト.
NCache 詳細 エディションの比較 NCache ダウンロード