XNUMXつの理由 NCache よりも良い Redis

録画されたウェビナー
イクバル・カーン

方法を学びます Redis & NCache 機能レベルで相互に比較します。 このウェビナーの目的は、XNUMX つの製品を比較するタスクをより簡単かつ迅速に行うことです。

ウェビナーでは次の内容について説明します。

  • さまざまな製品の機能領域。
  • サポートは何をするのか Redis & NCache 各機能領域に提供しますか?
  • の強みは何ですか NCache が Redis およびその逆?

NCache は、.NET 用の一般的なオープン ソース (Apache 2.0 ライセンス) インメモリ分散キャッシュです。 NCache 一般に、アプリケーション データ キャッシュ、ASP.NET セッション状態ストレージ、イベントを通じたパブリッシュ/サブスクライブ スタイルのランタイム データ共有に使用されます。

Redis また、データベース、キャッシュ、メッセージ ブローカーとして使用される、人気のあるオープン ソース (BSD ライセンス) インメモリ データ構造ストアでもあります。 Redis は Linux で非常に人気がありますが、最近では Microsoft がそれを推進しているため、Azure でも注目を集めています。

概要

皆さん、こんにちは。私の名前はイクバル カーンです。 Alachisoft. Alachisoft はサンフランシスコ ベイエリアに拠点を置くソフトウェア会社で、人気のある NCache これは、.NET 用のオープンソース分散キャッシュです。 Alachisoft のメーカーでもあります NosDBこれは、.NET 用の SQL を使用しないオープン ソース データベースです。 今回はそのXNUMXつの理由についてお話します。 NCache よりも優れている Redis .NETアプリケーション用。 Redisご存知のとおり、によって開発されました。 Redis ラボで開発され、Microsoft によって Azure に採用されました。 選んだ主な理由は、 Redis マルチプラットフォームのサポートとさまざまな言語を提供しますが、 NCache は純粋に .NET に焦点を当てています。 それでは、始めましょう。

分散キャッシュ

比較に入る前に、分散キャッシュとは何なのか、なぜ必要なのか、そして分散キャッシュによってどのような問題が解決されるのかについて簡単に説明します。 分散キャッシュは実際には、アプリケーションのスケーラビリティを向上させるために使用されます。 ご存知のとおり、Web アプリケーション、Web サービス アプリケーション、またはその他のサーバー アプリケーションがある場合は、アプリケーション層にサーバーを追加できます。 通常、アプリケーション アーキテクチャでは、これを非常にシームレスに実行できます。 ただし、特にリレーショナル データベースまたは従来のメインフレーム データを使用している場合は、データベース層で同じことを行うことはできません。 SQL を使わずにこれを行うことができます。 ただし、ほとんどの場合、技術的理由とビジネス上の理由から、リレーショナル データベースを使用する必要があります。

分散キャッシュアーキテクチャ

したがって、リレーショナル データベースやレガシー メインフレームがもたらすスケーラビリティのボトルネックを分散キャッシュを通じて解決する必要があります。その方法は、アプリケーション層とデータベースの間にキャッシュ層を作成することです。 このキャッシュ層は XNUMX つ以上のサーバーで構成されます。 これらは通常、低コストのサーバーです。 の場合には NCacheの一般的な構成は、16 ~ 32 ギガビットの RAM と 1 ~ 10 ギガビットの速度の XNUMX ~ XNUMX 枚のネットワーク カードを備えたデュアル CPU、クアッドコア マシンです。 これらのキャッシュ サーバーは、次の場合に TCP ベースのクラスターを形成します。 NCache そして、これらすべてのサーバーのリソースを 4 つの論理容量にプールします。 そうすることで、アプリケーション層が成長するにつれて、たとえばトラフィックやトランザクション負荷がますます増加する場合、アプリケーション層にサーバーを追加できます。 キャッシュ層にサーバーを追加することもできます。 通常は、アプリケーション層とキャッシュ層の比率を 1 対 5 または 1 対 XNUMX に維持します。

そのため、分散キャッシュがボトルネックになることはありません。 したがって、ここでアプリケーション データのキャッシュを開始し、データベースへのトラフィックを削減できます。 目標は、トラフィックの約 80% がキャッシュに送られ、トラフィックの約 20% (通常は更新) がデータベースに送られるようにすることです。 そうすれば、アプリケーションがスケーラビリティのボトルネックに直面することはなくなります。

分散キャッシュの一般的な使用法

さて、分散キャッシュの利点を念頭に置きながら、あなたが知っているさまざまな使用例、分散キャッシュを使用できるさまざまな状況について話しましょう。

アプリケーションデータのキャッシュ

XNUMX つ目はアプリケーション データ キャッシュです。これは、パフォーマンスとスケーラビリティを向上させるために、データベースに存在するデータをキャッシュする場所に先ほど説明したものと同じです。 アプリケーション データ キャッシュに関して留意すべき主な点は、データが XNUMX つの場所に存在することです。 これはマスター データ ソースであるデータベースに存在し、キャッシュ層にも存在します。その場合、心に留めておく必要がある最も重要なことは、最大の心配事は次のとおりです。 、キャッシュが古くなってしまうのでしょうか? データベース内のデータが変更された場合でも、キャッシュには古いバージョンのデータが含まれることになりますか。 そのような状況が発生した場合は、もちろん大きな問題が発生します。多くの人は、データの整合性の問題を恐れて、読み取り専用データのみをキャッシュします。 読み取り専用データは、キャッシュする必要があるデータ全体の非常に小さなサブセットであり、データの約 XNUMX ~ XNUMX% です。

本当の利点は、トランザクション データのキャッシュを開始できる場合にあります。 これは、顧客、アクティビティ、履歴など、実行時に作成され、非常に頻繁に変更されるあらゆる種類のデータです。そのデータは引き続きキャッシュする必要がありますが、常にキャッシュされる方法でキャッシュする必要があります。新鮮なままです。 これが最初の使用例であり、それに戻ります。

ASP.NET固有のキャッシュ

XNUMX 番目の使用例は、ASP.NET 固有のキャッシュ用で、セッション状態、ビュー状態、および MVC フレームワークとページ出力がない場合にキャッシュします。 この状況では、キャッシュはデータベースよりもはるかに高速でスケーラブルなストアであるため、セッション状態をキャッシュします。そうでない場合は、これらのセッションや Microsoft が提供する他のオプションをキャッシュします。この場合、データは一時的な。 一時的とは、本質的に一時的なものであることを意味します。 これは短期間のみ必要となり、その後は破棄するだけで、データはキャッシュ内にのみ存在します。 キャッシュはマスター ストアです。 したがって、この使用例では、キャッシュをデータベースと同期する必要があるということが心配ではなく、キャッシュ サーバーがダウンした場合にデータの一部が失われるということが心配になります。 なぜなら、これはすべてメモリ内ストレージであり、ご存知のとおり、メモリは揮発性だからです。 したがって、優れた分散キャッシュは、インテリジェントなレプリケーション戦略を提供する必要があります。 つまり、すべてのデータが複数のサーバーに存在することになります。 いずれかのサーバーがダウンしてもデータは失われませんが、レプリケーションにはコストがかかり、パフォーマンスが低下します。 したがって、レプリケーションは超高速である必要があります。 NCache ちなみに、そうです。

ランタイムデータ共有

XNUMX 番目のユース ケースは、ランタイム データ共有のユース ケースで、本質的にデータ共有プラットフォームとしてキャッシュを使用します。 そのため、さまざまなアプリケーションがキャッシュに接続され、Pub/Sub モデルでデータを共有できます。 したがって、XNUMX つのアプリケーションがデータを生成し、それをキャッシュに置き、イベントを起動すると、そのイベントに関心を登録している他のアプリケーションに通知が届くため、そのデータを利用できるようになります。 ということで、他にもイベントがあります。 キーベースのイベント、キャッシュレベルのイベント、継続的なクエリ機能があります。 NCache もっている。 したがって、分散キャッシュを使用できる方法はいくつかあります。 NCache 異なるアプリケーション間でデータを共有します。 この場合も、データがデータベース内のデータから作成されたとしても、それが共有される形式はキャッシュ内にのみ存在する可能性があります。 したがって、キャッシュがデータを複製していることを確認する必要があります。 したがって、懸念事項は ASP.NET キャッシュの場合と同じです。 以上が、分散キャッシュを使用する一般的な XNUMX つの使用例です。 機能を比較する際には、これらのユースケースを念頭に置いてください。 NCache 提供する Redis ではない。

理由 1 – キャッシュを最新の状態に保つ

それでは、最初の理由、なぜ使用する必要があるのか NCache が Redis それは、 NCache キャッシュを最新の状態に保つための非常に強力な機能を提供します。 これについて説明したように、キャッシュを最新の状態に保つことができない場合、読み取り専用データをキャッシュする必要がありますが、読み取り専用データをキャッシュしても、それは本当の利点ではありません。 したがって、ほぼすべてのデータをキャッシュできる必要があります。 10 ~ 15 秒ごとに変化するデータでも。

絶対有効期限 / スライド有効期限

したがって、キャッシュを最新の状態に保つ最初の方法は、有効期限を設けることです。 有効期限は両方に関係するものです NCache & Redis 提供。 たとえば、絶対有効期限があり、10 分、2 分、または 1 分後にこのデータを期限切れにするようにキャッシュに指示します。 その時間が経過すると、キャッシュはそのデータをキャッシュから削除します。そして、あなたは推測をしています。つまり、このデータをこれほど長期間キャッシュに保持しても安全だと思います。データベース内の変更。 したがって、その推測に基づいて、キャッシュにデータを期限切れにするように指示していることになります。

Expiration は次のようになります。 ちょっとお見せします。 の場合には NCache、インストールすると NCache ちなみに、サンプルがたくさん提供されます。 そこで、サンプルの XNUMX つが基本操作と呼ばれるもので、それをここで公開しました。 基本的な操作として、典型的な .NET アプリケーションが使用するものを簡単に説明します。 NCache 見える。

あなたはとリンクします NCache 実行時に NCache.Web アセンブリを使用する場合は、 NCache。ランタイム 名前空間、 NCache.Web.キャッシング 名前空間にアクセスし、アプリケーションの開始時にキャッシュに接続します。 すべてのキャッシュには名前が付けられます。

using System;
using Alachisoft.NCache.Runtime;
using Alachisoft.NCache.Web.Caching;
using Alachisoft.NCache.sample.data;

namespace BasicOperations
{
    public class BasicOperations
    {
        public static void Main(string[] args)
        {
            try
            {
            //Initialize cache via 'initializeCache' using 'Cache Name'
            //to be initialized. 
            Cache cache = NCache.InitializeCache("mypartitionedcache");
            cache.Clear();

            //Another method to add item(s) to cache is via CacheItem  object
            Customer customer = new Customer();
            customer.Name = "David Johnes";
            customer.Age = 23;
            customer.Gender = "Male";
            customer.ContactNo = "12345-6789";
            customer.Address = "Silicon Valley, Santa Clara, California";

            DateTime calendar = new DateTime();
            calendar.AddMinutes(1);

            //Adding item with an absolute expiration of 1 minute
            cache.Add("Customer:DavidJohnes", customer, calendar, Cache.NoSlidingExpiration, CacheItemPriority.Normal);
            Customer cachedCustomer = (Customer) cache.Get("Customer:DavidJohnes");
            ...

キャッシュの作成方法については、こちらをご覧ください。 入門ビデオ。 それは私たちのウェブサイトで入手できます。 ただし、このキャッシュに接続し、キャッシュ ハンドルを取得したとします。 次に、オブジェクトの束であるデータを作成します。 キャッシュ.追加. キャッシュ.追加 文字列であるキーと、オブジェクトである実際の値があり、この場合は XNUMX 分の絶対有効期限を指定しています。 つまり、今から XNUMX 分後にこのオブジェクトを期限切れにすると言っているのです。 NCache このオブジェクトを期限切れにします。 これが有効期限の仕組みです。もちろん、先ほども言いましたが、 Redis も提供します。

キャッシュをデータベースと同期する

しかし、有効期限の問題は、正しくない可能性や正確でない可能性がある推測を行っていることです。 では、指定した XNUMX 分より XNUMX 分前にデータが変更された場合はどうなるでしょうか。 そこで、キャッシュをデータベースと同期するという別の機能が必要になります。 これが特徴です NCache と Redis 持っていない。

そう、 NCache それはさまざまな方法で行われます。 最初の番号は SQLの依存関係。 SQL 依存関係は、ADO.NET を介した SQL サーバーの機能であり、基本的に SQL ステートメントを指定し、SQL サーバーに「このデータ セットを監視してください。このデータ セットが変更された場合は、行が追加されたことを意味します」と指示します。このデータセット基準に一致する更新または削除が行われた場合は、私に通知してください。 したがって、データベースはデータベース通知を送信し、その後、適切なアクションを実行できます。 それで、その方法は NCache これはそうですか、 NCache SQL 依存関係を使用しますが、Oracle で同じことを行う Oracle 依存関係もあります。 どちらもデータベース イベントを処理します。 それで、 NCache SQL 依存関係を使用します。 ここでそのコードをお見せしましょう。 したがって、SQL の依存関係コードに進むことにします。 繰り返しますが、同じ方法でいくつかのアセンブリにリンクします。 キャッシュ ハンドルを取得したので、項目を追加したので、ここで定義に進みます。 したがって、このデータを追加しているので、追加の一環として SQL 依存関係を指定します。 したがって、キャッシュの依存関係は、 NCache データベースへの接続文字列を受け取るクラス。 SQL ステートメントが必要です。 この場合、製品 ID がこの ID である SQL ステートメントが必要だとします。 したがって、製品オブジェクトをキャッシュしているので、それを製品テーブル内の対応する行と照合することになります。 それで、あなたは言っています、あなたは言っています NCache SQL サーバーと通信し、SQL 依存関係を使用して SQL サーバーがこのステートメントを監視できるようにし、このデータが変更された場合に SQL サーバーに通知します。 NCache.

これで、キャッシュ サーバーがデータベースのクライアントになりました。 したがって、キャッシュ サーバーは SQL サーバーに、このデータ セットが変更された場合は通知してほしいと要求し、そのデータセットが変更されると SQL サーバーはキャッシュ サーバーに通知し、 NCache その後、サーバーはそのアイテムをキャッシュから削除します。削除する理由は、アイテムが削除されると、次回必要になったときにキャッシュ内で見つけることができなくなり、データベースから強制的に取得することになるためです。 それで、それを一種のリフレッシュする方法です。 アイテムを自動的にリロードできる別の方法があります。これについては後ほど説明します。

したがって、SQL 依存関係により、 NCache キャッシュをデータベースおよび Oracle 依存関係と実際に同期するには、SQL サーバーではなく Oracle で動作する点を除いて、まったく同じように動作します。 SQL の依存関係は非常に強力ですが、おしゃべりでもあります。 たとえば、10,000 個のアイテムまたは 100,000 個のアイテムがある場合、100,000 個の SQL 依存関係を作成することになり、SQL サーバー データベースにパフォーマンスのオーバーヘッドが生じます。これは、SQL サーバー データベースが SQL 依存関係ごとにデータ構造を作成し、サーバーそのデータを監視するため、余分なオーバーヘッドが発生します。

したがって、同期するデータが大量にある場合は、DB 依存関係のみを使用する方がよいでしょう。 DB 依存関係は、SQL ステートメントとデータベース イベントを使用する代わりに、 NCache 実際にデータベースをプルします。 あなたが作成した特別なテーブルがあります。 NCache DB 同期を行ってからトリガーを変更し、このキャッシュされたアイテムに対応する行のフラグを更新します。 NCache このテーブルは、デフォルトでは 15 秒ごとに頻繁にプルされ、変更された行が見つかった場合は、対応するキャッシュされたアイテムをキャッシュから無効にすることができます。 したがって、これらの両方と、もちろん DB 依存関係は、どのデータベースでも機能します。 SQL サーバーや Oracle だけでなく、DB2 や MySQL、その他のデータベースがある場合も同様です。

したがって、これらの機能を組み合わせることで、キャッシュが常にデータベースと同期され、ほぼすべてのデータをキャッシュできることを確信できます。 XNUMX 番目の方法は CLR ストアド プロシージャで、実際に CLR ストアド プロシージャを実装できます。 そこから、 NCache 電話。 そのため、データベース トリガーからストアド プロシージャを呼び出します。 customer テーブルがあり、実際には更新トリガー、削除トリガー、さらには追加トリガーがあるとします。 CLR手順の場合は、新しいデータを追加することもできます。 つまり、CLR プロシージャがトリガーによって呼び出され、CLR プロシージャによって NCache これにより、データベースがデータを追加したり、キャッシュにデータを更新したりすることができます。

したがって、これら XNUMX つの異なる方法により、 NCache データベースと同期する必要があり、これが使用する非常に強力な理由です。 NCache が Redis なぜなら Redis 有効期限のみを使用するように強制されますが、これでは不十分です。 実際に脆弱になるか、読み取り専用データをキャッシュする必要があります。

キャッシュを非リレーショナル データベースと同期する

キャッシュを非リレーショナル データベースと同期することもできます。 したがって、レガシー データベース、メインフレームをお持ちの場合は、キャッシュ サーバー上で頻繁に実行されるコードであるカスタム依存関係を持たせることができます。 NCache コードを呼び出してデータ ソースを監視します。Web メソッド呼び出しを行うか、その他の操作を行ってカスタム データ ソースを監視すると、キャッシュされたアイテムとそのカスタム データ ソース内のデータ変更を同期できます。 したがって、データベースの同期は非常に強力な理由であり、なぜそれを使用する必要があるのか​​というと、 NCache が Redis なぜなら、実質的にすべてのデータをキャッシュできるからです。 一方、次の場合は、 Redis 読み取り専用のデータ、または非常に自信を持って推測できるデータをキャッシュする必要があります。 有効期限.

理由 2 – SQL 検索

理由その XNUMX、わかりました。 たとえば、データベース機能との同期を使用し始めて、実質的に大量のデータをキャッシュできるようになりました。 したがって、キャッシュするデータが増えるほど、キャッシュはデータベースのように見え始めますが、キーに基づいてデータをフェッチするオプションしかない場合、それは何ですか Redis そうなると、それは非常に制限的になります。 したがって、他のこともできるようにする必要があります。 したがって、データをインテリジェントに検索できる必要があります。 NCache では、オブジェクト属性またはグループとサブグループに基づいてデータをグループ化したり、データを検索したり、タグや名前タグを割り当てたりするさまざまな方法が提供されます。 したがって、これらはすべて、データのコレクションを取り戻すためのさまざまな方法です。 たとえば、SQL クエリを発行する場合、ここで SQL クエリを実行するとします。 したがって、たとえば、customer.city がニューヨークであるすべての顧客を探しに行きたいと思います。 そこで、SQL 状態を発行します。選択した顧客を指定します。つまり、完全な名前空間、顧客の this.City が疑問符で、値として New York を指定します。そのクエリを発行すると、この基準に一致する顧客オブジェクトのコレクションが返されます。

したがって、これはデータベースのように見えます。 つまり、これが意味するのは、実際にデータのキャッシュを開始できるということです。 データ セット全体、特にアプリケーションがデータベース内のクエリに対して SQL クエリを発行するために使用されていたルックアップ テーブルやその他の参照データ、および発行できる同じ種類の SQL クエリをキャッシュできます。 NCache。 唯一の制限は、次の場合に結合を実行できることです。 NCache しかし、これらの多くは実際にジョイントを行う必要はありません。 SQL検索 キャッシュは、探しているデータを実際に検索して見つけるのに非常に使いやすいものになります。

グループ化とサブグループ化 グループ化の例を見てみましょう。 したがって、たとえばここでは、多数のオブジェクトを追加することも、それらすべてを追加することもできます。 つまり、それらをグループとして追加することになります。 これがキー、値、これがグループ名、これがサブグループ名で、後でエレクトロニクス グループに属するものをすべてくださいと言うことができます。 これによりコレクションが返され、コレクションを反復処理して内容を取得できます。

namespace GroupsAndTags
{
    public class Groups
    {

    public static void RunGroupsDemo()
    {
        try
        {
            Console.WriteLine();

            Cache cache = NCache.InitializeCache("mypartitionedcache");
            cache.Clear();

            //Adding item in same group
            //Group can be done at two levels 
            //Groups and Subgroups.          

            cache.Add("Product:CellularPhoneHTC", "HTCPhone", "Electronics", "Mobiles");
            cache.Add("Product:CellularPhoneNokia", "NokiaPhone", "Electronics", "Mobiles");
            cache.Add("Product:CellularPhoneSamsung", "SamsungPhone", "Electronics", "Mobiles");
            cache.Add("Product:ProductLaptopAcer", "AcerLaptop", "Electronics", "Laptops");
            cache.Add("Product:ProductLaptopHP", "HPLaptop", "Electronics", "Laptops");
            cache.Add("Product:ProductLaptopDell", "DellLaptop", "Electronics", "Laptops");
            cache.Add("Product:ElectronicsHairDryer", "HairDryer", "Electronics", "SmallElectronics");
            cache.Add("Product:ElectronicsVaccumCleaner", "VaccumCleaner", "Electronics", "SmallElectronics");
            cache.Add("Product:ElectronicsIron", "Iron", "Electronics", "SmallElectronics");

            // Getting group data
            IDictionary items = cache.GetGroupData("Electronics", null); // Will return nine items since no subgroup is defined;
            if (items.Count > 0)
            {
                Console.WriteLine("Item count: " + items.Count);
                Console.WriteLine("Following Products are found in group 'Electronics'");
                IEnumerator itor = items.Values.GetEnumerator();
                while (itor.MoveNext())
                {
                    Console.WriteLine(itor.Current.ToString());
                }
                Console.WriteLine();
            }

グループに基づいてキーを取得することもできます。 グループに基づいて他のことも行うことができます。 したがって、グループとタグは同様に機能します。 ネームタグ キー値の概念であることを除けば、タグと同じです。 たとえば、フリーフォーム テキストをキャッシュしていて、インデックス付けされたテキストのメタデータの一部を取得したい場合は、名前タグでキーと値の概念を使用できます。その方法で、所有しているグループ タグと名前タグを一度だけ使用できます。その後、それらを SQL クエリに含めることができます。

発行することもできます LINQクエリ。 LINQ に慣れている場合は、LINQ クエリを発行できます。 たとえば、LINQ の場合、次のようにします。 NCache。 それで、あなたは次のようにします NCache 製品オブジェクトを使用してクエリを実行します。 それはあなたに IQueryable インターフェイスを使用すると、他のオブジェクト コレクションに対して行うのと同じように LINQ クエリを発行でき、実際にキャッシュを検索します。

do
{
    Console.WriteLine("\n\n1> from product in products where product.ProductID > 10 select product;");
    Console.WriteLine("2> from product in products where product.Category == 4 select product;");
    Console.WriteLine("3> from product in products where product.ProductID < 10 && product.Supplier == 1 select product;");
    Console.WriteLine("x> Exit");
    Console.Write("?> ");
    select = Console.ReadLine();

    switch (select)
    {
        case "1":
            try
            {
                var result1 = from product in products
                         where product.ProductID > 10
                         select product;
                if (result1 != null)
                {
                    PrintHeader();
                    foreach (Product p in result1)
                    {
                        Console.WriteLine("ProductID : " + p.ProductID);
                    }
                }
                else
                {
                    Console.WriteLine("No record found.");
                }
            }

したがって、このクエリを実行すると、実際にはキャッシュ層に移動してオブジェクトが検索されます。 ご存知のとおり、利用できるインターフェイスは非常にシンプルで非常にフレンドリーですが、舞台裏では実際にキャッシュ クラスター全体をキャッシュまたは検索しています。 理由 XNUMX は、キャッシュを検索でき、グループやサブグループ、タグや名前付きタグを通じてデータをグループ化でき、フレンドリーな方法でデータを検索できるためです。これは、これらの機能のいずれにも存在しないものです。 Redis.

データのインデックス作成 これのもう XNUMX つの側面は、これらの属性に基づいて検索する場合、キャッシュがインデックスを作成することが不可欠であり、これらの属性にインデックスを作成することが非常に重要であるということです。 そうしないと、それらを見つけるプロセスが非常に遅くなります。 それで、 NCache データのインデックスを作成できます。 たとえば、すべてのグループとサブグループ、タグ、名前タグには自動的にインデックスが付けられますが、オブジェクトにインデックスを作成することもできます。 したがって、たとえば、市属性の顧客オブジェクトにインデックスを作成できます。 したがって、都市属性で検索することがわかっているため、都市属性を選択します。 あなたは、その属性をその方法でインデックス付けしたいと言いました NCache それをインデックスします。

理由 3 – サーバー側のコード

理由その XNUMX は、 NCache 実際にサーバーサイドのコードを書くことができます。 では、そのサーバー側のコードとは何ですか、そしてなぜそれがそれほど重要なのでしょうか。 それを見てみましょう。 それは、リードスルー、ライトスルー、ライトビハインド、およびキャッシュローダーです。 それで、 既読スルー は基本的にユーザーが実装するコードであり、キャッシュ サーバー上で実行されます。 では、実際に朗読会がどのようなものかを紹介しましょう。 したがって、たとえば、 IReadThruProvider インタフェース。

public void LoadFromSource(string key, out ProviderCacheItem cacheItem)
{
    cacheItem = new ProviderCacheItem(sqlDatasource.LoadCustomer(key));
    cacheItem.ResyncItemOnExpiration = true;
    cacheItem.ResyncProviderName = sqlDatasource.ConnString;
}
/// <summary>
/// Perform tasks like allocating resources or acquiring connections
/// </summary>
/// <param name="parameters">Startup paramters defined in the configuration</param>
/// <param name="cacheId">Define for which cache provider is configured</param>
public void Init(IDictionary parameters, string cacheId)
{
    object connString = parameters["connstring"];
    sqlDatasource = new SqlDatasource();
    sqlDatasource.Connect( connString == null ? "" : connString.ToString() );
}
/// <summary>
///  Perform tasks associated with freeing, releasing, or resetting resources.
/// </summary>
public void Dispose()
{
    sqlDatasource.DisConnect();
}

このインターフェースには 1000 つのメソッドがあります。 キャッシュの開始時に呼び出される init メソッドがあり、その目的はリードスルー ハンドラーをデータ ソースに接続することです。また、キャッシュの停止時に呼び出されてデータ ソースから切断できる処分と呼ばれるメソッドがあります。そして、キーを渡すソースメソッドからのロードがあり、キャッシュアイテム、プロバイダーキャッシュアイテムオブジェクトの出力を期待します。 したがって、キーを使用して、データベースから取得する必要があるオブジェクトを決定できるようになりました。 したがって、先ほど述べたように、キーは顧客、顧客 ID 1000 である可能性があります。つまり、オブジェクトの種類が顧客、キーが顧客 ID、値が XNUMX であることがわかります。したがって、そのような形式を使用する場合は、次のようにすることができます。それに基づいて、データ アクセス コードを考え出すことができます。

したがって、このリードスルー ハンドラーは実際にはキャッシュ サーバー上で実行されます。 したがって、実際にはこのコードをすべてのキャッシュ サーバーにデプロイします。 の場合には NCache かなりシームレスです。 それは、 NCache マネージャーツール。 したがって、そのリードスルー ハンドラーをキャッシュ サーバーにデプロイすると、そのリードスルー ハンドラーがキャッシュによって呼び出されます。 たとえば、アプリケーションが次のことを行うとします。 キャッシュ.取得 そしてそのアイテムはキャッシュにありません。 NCache リードスルーハンドラーを呼び出します。 リードスルー ハンドラーはデータベースに行き、その項目をフェッチし、それを返します。 NCache. NCache それをキャッシュに入れてからアプリケーションに返します。 そのため、アプリケーションはデータが常にキャッシュ内にあるように感じます。 したがって、データがキャッシュにない場合でも、キャッシュはデータベースからデータを取得する機能を備えています。 それが輪読の第一のメリットです。

リードスルーの 5 番目の利点は、有効期限が切れたときです。 絶対的な有効期限があったとします。 このアイテムを今から 2 分後または XNUMX 時間後に期限切れにすると言ったのですが、その時点ではそのアイテムをキャッシュから削除するのではなく、 NCache リードスルー ハンドラーを呼び出して、そのアイテムを自動的に再ロードします。 また、リロードとは、アイテムがキャッシュから削除されないことを意味します。 これは更新されるだけであり、これは非常に重要です。なぜなら、多くの参照ルックアップ テーブルでは、そのデータを読み取るだけで大​​量のトランザクションが発生し、そのデータがたとえ短期間であっても削除されると、データベースに対して大量のトランザクションが発生するからです。同時にそのデータを取得するために作成されます。 したがって、キャッシュ内で更新できれば、はるかに優れています。 つまり、これは XNUMX つの使用例です。

XNUMX 番目の使用例は、データベースの同期です。 したがって、データベースの同期が発生し、その項目が削除されるとき、削除するのではなく、データベースから再ロードしてみてはどうでしょうか。 NCache 意思。 設定できます NCacheしたがって、データベースの同期が開始されると、 NCache その項目をキャッシュから削除する代わりに、リードスルー ハンドラーを呼び出して、その項目の新しいコピーを再読み込みします。 繰り返しますが、期限切れと同じように、アイテムは削除されません。 キャッシュから削除されることはありません。 したがって、リードスルーは非常に強力な機能です。

リードスルーのもう XNUMX つの利点は、アプリケーションが簡素化されることです。キャッシュ層にコードを永続化すると、どんどん移動することになります。また、同じデータにアクセスする複数のアプリケーションがある場合、アプリケーションが行う必要があるのは、 キャッシュ.取得。 A キャッシュ.取得 これは非常に単純な呼び出しであり、適切な ADO.NET タイプのコーディングを実行します。

したがって、リードスルーによりアプリケーション コードが簡素化されます。 また、キャッシュに常にデータが存在することも保証されます。 有効期限が切れたときやデータベースの同期時に自動的にリロードが行われます。

次の機能はライトスルーです。 ライトスルーは、更新のためであることを除けば、リードスルーと同じように機能します。 ライトスルーがどのようなものかを説明しましょう。 ということで、これは既読スルーでした。 とりあえず書き進めてみましょう。 そこで、ライトスルー ハンドラーを実装します。 繰り返しますが、init メソッドがあります。 リードスルーと同様に破棄メソッドがありますが、データソースへの書き込みメソッドとデータソースへの一括書き込みメソッドが追加されました。 つまり、これは既読スルーとは異なるものです。

//region IWriteThruProvider Members
public OperationResult WriteToDataSource(WriteOperation operation)
{
    bool result = false;
    OperationResult operationResult = new OperationResult(operation, OperationResult.Status.Failure);
    Customer value = (Customer)operation.ProviderCacheItem.Value;
    if (value.GetType().Equals(typeof(Customer)))
    {
        result= XmlDataSource.SaveCustomer((Customer)value);
    }
    if (result) operationResult.DSOperationStatus = OperationResult.Status.Success;
    return operationResult;
}
public OperationResult[] WriteToDataSource(WriteOperation[] operation)
{
    throw new Exception("The method or operation is not implemented.");
}

ライトスルーの場合は、オブジェクトと操作も取得します。この操作は、追加、更新、または削除の可能性があります。 なぜなら、あなたはできるからです キャッシュ.追加、キャッシュ.挿入、キャッシュ.削除、これらすべてにより、ライトスルー呼び出しが行われることになります。 これで、データベース内のデータを更新できるようになります。

同様に、一括操作、一括更新を行う場合は、データベースの一括更新も実行できます。 したがって、ライトスルーには、より多くの永続化コードがキャッシュ層に移動されるため、アプリケーションを簡素化できるというリードスルーと同じ利点もあります。

ただし、ライトスルーのバリエーションであるライトビハインド機能もあります。 ライトビハインドでは基本的に、キャッシュを更新すると、キャッシュがデータ ソースを非同期的に更新します。 基本的には後から更新します。 したがって、アプリケーションは待つ必要がありません。

ライトビハインドはアプリケーションを本当に高速化します。 ご存知のとおり、データベースの更新はキャッシュの更新ほど高速ではないからです。 つまり、ライトビハインド機能を備えたライトスルーを使用すると、キャッシュがすぐに更新されます。 アプリケーションは戻ってその処理を実行し、ライトビハインド方式でライトスルーが呼び出され、データベースを更新します。もちろん、データベースの更新が失敗した場合は、アプリケーションに通知されます。

したがって、キューが作成されている場合は常に、そのサーバーがダウンした場合にそのキューが失われるリスクがあります。 さて、の場合は、 NCache ライトビハインドキューも複数のサーバーにレプリケートされるため、キャッシュサーバーがダウンしてもライトビハインドキューは失われません。 それで、そのようにして NCache 高可用性を確保します。 したがって、ライトスルーとライトビハインドは非常に強力な機能です。 これらによりアプリケーション コードが簡素化され、また、ライトビハインドの場合はデータベースが更新されるのを待つ必要がなくなるため、アプリケーションが高速化されます。

XNUMX 番目の機能はキャッシュ ローダーです。 アプリケーションがデータベースにアクセスする必要がないように、キャッシュにプリロードしておきたいデータがたくさんあります。 キャッシュ ローダー機能がない場合は、そのコードを記述する必要があります。 そのコードを記述する必要があるだけでなく、それをプロセスとしてどこかで実行する必要もあります。 実際に複雑になるのは、プロセスとしての実行です。 したがって、キャッシュ ローダーの場合は、キャッシュを登録するだけです。 キャッシュ ローダー インターフェイスを実装し、コードを次のように登録します。 NCache, NCache は、キャッシュが開始されるたびにコードを呼び出します。これにより、キャッシュに常にその量のデータがプリロードされるようにすることができます。

したがって、これら XNUMX つの機能、リードスルー、ライトスルー、ライトビハインド、およびキャッシュローダーは、非常に強力な機能です。 NCache があります。 Redis にはそのような機能はありません。 したがって、次の場合には、 Redis この能力をすべて失います NCache それ以外の場合は規定します。

理由 4 – クライアント キャッシュ (ニア キャッシュ)

理由その4は、 クライアントキャッシュ。 クライアント キャッシュは非常に強力な機能です。 実際には、これはアプリケーション サーバー ボックスにあるローカル キャッシュですが、分離されたキャッシュではありません。 これはアプリケーションに対してローカルです。 インプロセスの場合もあります。 したがって、このクライアント キャッシュは、ヒープ上に保持されるオブジェクトである可能性があります。 NCache In-Proc オプションを選択すると、 NCache データとオブジェクトの形式を維持します。 シリアル化された形式ではなく、クライアント キャッシュ内にあります。 クラスター化されたキャッシュでは、シリアル化された形式で保持されます。 ただし、クライアント キャッシュではオブジェクト形式で保持されます。 なぜ? したがって、フェッチするたびに、オブジェクトに逆シリアル化する必要はありません。 したがって、フェッチや取得の速度が向上します。

クライアント キャッシュは非常に強力な機能です。 キャッシュの上にキャッシュを重ねたものです。 したがって、スタンドアロンのインプロセス キャッシュから分散キャッシュに移行すると失われるものの XNUMX つは、分散キャッシュでは、たとえ別のサーバー上であってもキャッシュがデータを別のプロセスに保持し、プロセス間が存在することです。通信が行われていると、シリアル化と逆シリアル化が行われるため、パフォーマンスが低下します。 そのため、インプロセスのオブジェクト フォーム キャッシュと比較すると、分散キャッシュは少なくとも XNUMX 倍遅くなります。 したがって、クライアント キャッシュを使用すると、両方の長所を活用できます。 なぜなら、クライアント キャッシュがなく、スタンドアロンの分離キャッシュだけがあった場合、キャッシュのサイズに関して他にも多くの問題があり、そのプロセスがダウンしたらどうなるでしょうか? その場合、キャッシュが失われますが、複数のサーバー間での変更とキャッシュの同期を維持するにはどうすればよいでしょうか。 これらすべての問題に対処するのは、 NCache クライアントキャッシュ内にあります。

したがって、スタンドアロンのインプロセス キャッシュのメリットを享受できますが、キャッシュ クラスターに接続されています。 したがって、このクライアント キャッシュに保持されているものはすべてクラスター化キャッシュにもあり、いずれかのクライアントがここでそれを更新すると、キャッシュ層がクライアント キャッシュに通知します。 すぐに更新できるようになります。 したがって、これにより、クライアント キャッシュが常にキャッシュ層と同期され、その後データベースと同期されることを確認したり、安心したりすることができます。

したがって、次の場合には、 NCache クライアント キャッシュは、追加のプログラミングを行わずに接続するだけで使用できるものです。 キャッシュ層と通信しているかのように API 呼び出しを行うと、クライアント キャッシュは構成変更にプラグインするだけで、クライアント キャッシュにより 10 倍高速なパフォーマンスが得られます。 これは、 Redis 持っていない。 したがって、パフォーマンスに関するあらゆる主張にもかかわらず、 Redis ご存知のとおり、これらは高速な製品ですが、それも同様です NCache。 そう、 NCache ~とパフォーマンスで真っ向から対決している Redis クライアントキャッシュなし。 ただし、クライアント キャッシュをオンにすると、 NCache 10倍高速です。 つまり、これがクライアント キャッシュを使用する本当の利点です。 これが、使用する理由 XNUMX 番目です。 NCache が Redis.

理由 5 - マルチデータセンターのサポート

理由そのXNUMXは、 NCache マルチデータセンターのサポートを提供します。 最近では、高トラフィックのアプリケーションを使用している場合、ディザスタ リカバリ DR のために複数のデータセンターですでに実行しているか、負荷分散または DR と負荷分散の組み合わせのために XNUMX つのアクティブ/アクティブ データセンターでそのアプリケーションを実行している可能性が非常に高くなります。 、あるいはおそらく地理的な負荷分散です。 つまり、地方のトラフィックに対応するために、ロンドンやニューヨークにデータセンターがあるかもしれませんし、東京などにデータセンターがあるかもしれません。 ご存知のように、複数のデータセンターがある場合、データベースはレプリケーションを提供します。これがなければ、複数のデータセンターを持つことができないからです。 なぜなら、データは複数のデータセンター間で同じだからです。 データが同じでない場合は、別のものなので問題はありませんが、多くの場合、データは同じであり、それだけでなく、トラフィックの一部を XNUMX つのデータからオフロードできるようにしたいと考えます。データセンターを他のデータセンターにシームレスに接続します。 では、データセンター間でデータベースをレプリケートしている場合、なぜキャッシュを使用しないのでしょうか? Redis そのような機能は提供していませんが、 NCache 非常に強力な機能を提供します。

マルチデータセンターのサポート

したがって、次の場合には、 NCache すべてのデータセンターには独自のキャッシュ クラスターがありますが、 ブリッジトポロジ その間。 このブリッジは基本的に各データセンターのキャッシュ クラスターを接続し、非同期レプリケーションを可能にします。 したがって、これがアクティブなデータセンター、これがパッシブなデータセンターである、アクティブ/パッシブ ブリッジを使用できます。 アクティブ/アクティブ ブリッジを使用することもできます。また、XNUMX つ以上のデータセンターのアクティブ/アクティブまたはアクティブ/パッシブ構成もリリースしています。たとえば、XNUMX つまたは XNUMX つのデータセンターを持つことができ、キャッシュはそれらすべてにレプリケートされます。アクティブ-アクティブ方式またはアクティブ-パッシブ方式のいずれかで。 アクティブ/アクティブでは、更新が非同期で実行されるか、レプリケーションが非同期で実行されるため、両方のデータセンターで同じ項目が更新されるという競合が発生する可能性があります。

そう、 NCache は、競合解決を処理するための XNUMX つの異なるメカニズムを提供します。 XNUMX つは最終更新が優先と呼ばれます。 どちらの項目が最後に更新されたかは、両方の場所に適用されます。 たとえば、あなたがここでアイテムを更新し、別のユーザーがここでアイテムを更新したとします。 両方とも他のキャッシュへの伝播を開始します。 したがって、彼らがブリッジに来ると、ブリッジは両方の場所で更新されたことを認識します。 したがって、タイムスタンプをチェックし、最後に更新されたタイムスタンプが他の場所に適用され、他の場所によって行われた更新は破棄されます。 このようにして、アクティブ/アクティブの最後の更新が優先される競合解決が行われます。 それが十分でない場合は、競合解決ハンドラーを実装できます。 それがあなたのコードです。 したがって、競合が発生した場合、ブリッジは実際にコードを呼び出し、オブジェクトの両方のコピーを渡すため、コンテンツベースの分析を行うことができ、その分析に基づいてどのオブジェクトを更新するのがより適切かを判断できます。両方のデータセンターに適用されます。 XNUMX つ以上のデータセンターがある場合にも、同じルールが適用されます。

だから、 マルチデータセンターのサポート 非常に強力な機能です NCache 箱から出してすぐに提供されます。 購入したら NCache、すべてそこにあります、 Redis 複数のデータセンターを持つ計画がある場合、または単に柔軟性が必要な場合でも、現在は複数のデータセンターを持っていないが、複数のデータセンターにアクセスできる柔軟性が必要な場合でも、レプリケーションをサポートしていないデータベースを今すぐ購入しますか? たとえデータセンターが XNUMX つしかないとしても、おそらくそうは思わないでしょう。 では、なぜ WAN 経由のレプリケーションをサポートしないキャッシュを使用するのでしょうか。 したがって、これは非常に強力な機能です NCache.

したがって、これまでは主に、優れた分散キャッシュに必要な機能について説明してきました。 NCache、光りますね。 それは圧倒的に勝利します Redis. Redis 非常に基本的な単純なキャッシュです。

理由 6 – プラットフォームとテクノロジー (.NET アプリ用)

.NET と Windows 対 Linux

理由 XNUMX は、おそらくあなたにとって最も重要な理由の XNUMX つであり、プラットフォームとテクノロジーです。 .NET アプリケーションをお持ちの場合は、完全な .NET スタックが必要になるでしょう。 ほとんどの場合、.NET と Java、または Windows と Linux を混在させたくないと思います。 場合によってはそうかもしれませんが、ほとんどの場合、.NET アプリケーションを開発している人は Windows プラットフォームを使用することを好み、可能であればスタック全体をすべて .NET にすることを好みます。 良い、 Redis .NET 製品ではありません。 これは、C/C++ で開発された Linux ベースの製品です。

プラットフォームとテクノロジー (.NET アプリ用)

少しお見せしましょう。 こちらが Redis を作っている会社であるlabsのウェブサイトです。 Redis。 ダウンロード ページにアクセスすると、Windows のオプションすら提供されていないことがわかります。 つまり、Microsoft が Azure にそれらを選んだという事実にもかかわらず、Windows をサポートするつもりはまったくありません。 それで、これまでのところ、 Redis Labsは懸念している、 Redis Linux 専用です。 Microsoft オープン テクノロジー グループが移植しました Redis Windowsに。 つまり、Windows バージョンがあります Redis 利用可能。 これはオープン ソースでサポートされていませんが、バグが多く不安定であり、その証拠は明らかですが、Microsoft 自体が Azure でこれを使用していません。 それで、 Redis Azure で使用しているものは実際には Linux ベースです Redis Windows ベースではありません。 したがって、組み込みたい場合は、 Redis アプリケーションスタックに組み込むと、油と水を混ぜることになります。 一方、次の場合は、 NCache すべてがネイティブの .NET です。 Windowsをお持ちですね。 100% .NET を使用できます。 NCache C Sharp (C#) で開発されました。 Windows Server 2012 R2 に対して認定されており、オペレーティング システムの新しいバージョンがリリースされるたびに、その認定を受けます。 ご存知のとおり、私たちはもうすぐ ASP を開始する予定です.NET Core サポート。 したがって、.NET クライアントが正式にリリースされました。 公式には Java クライアントもあります。 それで、私が思うに、あなたが使用するなら、 NCache そしてまた NCache もオープンソースです。 したがって、お金がない場合は、オープンソースバージョンを使用してください。 NCache。 ただし、プロジェクトが重要な場合は、より多くの機能と両方のサポートを提供する Enterprise バージョンを使用してください。 ただし、使用することを強くお勧めします NCache .NET と Windows の両方の組み合わせ用の .NET アプリケーションがある場合。

オンプレミスサポート

XNUMXつ目のメリットは、 NCache クラウドを使用していない場合、たとえば、クラウドに移行することを決めておらず、独自のアプリケーションをホストしている場合、基本的にはオンプレミスになります。 つまり、それは独自のデータセンター内にあります Redis Microsoft が提供するものは Azure でのみ使用できます。 つまり、オンプレミスのものには、 Redis オンプレミスで利用できるのは、 Redis Labs ですが、それは Linux だけであり、Windows 上の唯一のオンプレミスはオープン ソースであり、サポートが提供されず、バグが多く不安定で、バグが多すぎるため Microsoft 自体が Azure で使用していないものです。

オンプレミスサポート

一方、次の場合は、 NCache お金がない場合は、無料のオープンソースを使い続けることもできますが、もちろんサポートされていません。 ただし、すべてネイティブ .NET であるか、ビジネスにとって重要なプロジェクトがある場合は、 エンタープライズ版 より多くの機能があり、サポートが付属しており、永久ライセンスです。 ご存知のように、それを所有するにはかなり手頃な価格です。また、お客様にとって重要な場合に備えて、年中無休のサポートも提供します。

したがって、オンプレミスで完全にサポートされています。 ハイエンド顧客である当社の顧客のほとんどはまだ使用しています NCache オンプレミスの状況では。 NCache 10年以上市場に出回っています。 つまり、非常に安定した製品です。

クラウドサポート

クラウド対応に関しては、 Redis クラウド内のサービス モデルを提供します。これは、Microsoft が実装した Redis サービス。 良い、 Redis サービスは、キャッシュ サーバーにアクセスできないことを意味します。 ご存知のとおり、それはあなたにとってブラックボックスです。 サーバー側のコードはありません。 したがって、すべてのリードスルー、ライトスルー、ライトビハインド、キャッシュローダー、カスタム依存関係、その他の多くのものは、次のようなものでは実行できません。 Redis。 ご存知のとおり、基本的なクライアント API しかありません。先ほども述べたように、Azure では Microsoft が提供する Redis サービスとして。

クラウドサポート

NCache、意図的に VM モデルを選択しました。 なぜなら、キャッシュをアプリケーションの近くに置き、キャッシュを完全に制御できるようにしたいからです。 私たちは長年の経験があり、お客様が非常に敏感であることを知っているため、これは非常に重要なことです。 たとえば、たとえ小さなものであっても、 Redis サービスとして使用すると、毎回キャッシュにアクセスするために XNUMX つの余分なホップを作成する必要があります。これでは、キャッシュを持つ目的全体が無効になります。 一方、次の場合は、 NCache VM の一部として含めることができます。 クライアントキャッシュを持つことができます。 これは実際にはアプリケーションのデプロイメント内に組み込まれています。 したがって、サーバー側のコードはすべて実行できます。

NCache も実行されます Azure。 それは上で実行されます アマゾンAWS そして他の主要な クラウドプラットフォーム BYOLモデルで。 つまり、基本的に VM を取得できます。 実際、あなたは NCache 市場で。 あなたは、 NCache VM を当社からライセンスを購入すると、使い始めることができます。 NCache.

したがって、非常に異なるアプローチです。 ただし、これは、アプリケーションが本当に重要で、アプリケーションのあらゆる側面を制御し、アプリケーション レベルのインフラストラクチャの一部を管理する他の誰かに依存する必要がない場合に意図されたアプローチです。 VM とその下にあるハードウェアを管理することは別のことですが、上に進み始めると、当然、キャッシュの場合は制御できなくなります。 NCacheサービス モデルを使用すると、その制御だけでなく、多くの機能も失われます。

したがって、理由 6 はプラットフォーム テクノロジーです。 .NETアプリケーションの場合、 NCache よりもはるかに適切なオプションです Redis。 言ってないよ Redis これは悪い選択肢ですが、.NET アプリケーション向けだと思います NCache よりもはるかに優れたオプションです Redis.

NCache 歴史

簡単に歴史を紹介させてください NCache. NCache 2005 年半ばから存在しています。つまり 11 年間になります。 NCache 市場に出回っています。 これは、市場で最も古い .NET キャッシュです。 2015 年 2.0 月にオープンソースになりました。 これで、Apache XNUMX ライセンスが取得されました。 私たちの エンタープライズ版 はオープンソースの上に構築されています。 したがって、オープンソースは安定した信頼できるバージョンです。 たくさんの機能があります。 もちろん、Enterprise の方が機能は豊富ですが、オープンソースは非常に使いやすい製品です。 基本的なことは、お金がないならオープンソースを使うということです。 ビジネス アプリケーションが重要で、予算がある場合は、Enterprise Edition を選択してください。 サポートが付属しており、より多くの機能も提供します。

我々は持っています 何百もの顧客、キャッシュを必要とするほぼすべての業界で。 つまり、金融業界の顧客もいますし、ウォルマートやその他の小売業界も顧客です。 航空会社、保険業界、自動車/自動車など、あらゆる業界があります。

これで私の話は終わりです。 どうぞ、Enterprise Edition をダウンロードしてください。 NCache。 実際に私たちのウェブサイトへご案内しましょう。 したがって、基本的には、 ダウンロードのページ Enterprise Edition をダウンロードすることを強くお勧めします。最終的にオープンソース版を使用する場合でも、Enterprise Edition をダウンロードしてください。これは完全に機能する 30 日間の試用版であり、簡単に延長して試すことができます。

オープンソースをダウンロードしたい場合は、オープンソースをダウンロードしてください。 GitHub にアクセスして確認することもできます NCache GitHub で。 のようにしてほしい場合は、お問い合わせください。 パーソナライズされたデモ。 アプリケーションのアーキテクチャについて話したり、質問に答えたりすることもできます。 この講演をご覧いただきまして誠にありがとうございます。

次はどうする?

 

お問い合わせ(英語)

電話
©著作権 Alachisoft 2002 - . All rights reserved. NCache はダイヤテック株式会社の登録商標です。