Uncategorized

[AppFabric Caching] A to Z

Azure における最新の Redis Cache サービスについては「Azure Redis Cache の使用 (.NET, PHP, Node.js)」に記載しました。(以下は、古い記事です。)

関連ナンバー

こんにちは。

Tech Ed Japan ではかなりお茶を濁した表現になってしまいましたが、先日開催された PDC 10 で、Windows Azure AppFabric Caching が遂にアナウンスされました。( ゆっくりとですが、Windows Server AppFabric と Windows Azure AppFabric の垣根が低くなってきました . . .)

Windows Azure AppFabric SDK V2.0 CTP – October 2010 Update (英語) :

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=d89640fc-c552-446e-aead-b1e0d940f31b

Windows Azure AppFabric Labs (ベータ用) :

http://portal.appfabriclabs.com/

まずは、Tech Ed Japan 2010 の復習になりますが、この AppFabric の Caching (Windows Server AppFabric の Cache Services) について、どのような機能が使えるのかをザッと復習しておきましょう。
なお、基本的な AppFabric caching の使用方法 (チュートリアル) については、以前 こちら に掲載しましたので、ご参照ください。

補足 : なお、Windows Azure caching では、セキュリティも、ACS トークンを使用した方法が採用されています。また、下記の Region、Tag、Notification (通知)、HA などについても、現在の Windows Azure caching には実装されていないので注意してください。(使用できる API も、一部、制限されています。) 2012/06 削除

 

Region と Tag

Region と Tag を使用して、格納する Key-Value ペアのキャッシュ アイテム (データ) に対して、検索用のグループ化をおこなうことができます。
まず、Region (領域) は、「グループ化」という表現がまさにふさわしく、アイテムを排他的に分類します。一方、Tag (タグ) は、検索用のタグ付けに相当し、Region と異なり、1 つのアイテムに対して複数のタグを設定できます。

例えば、下図を参照してください。さまざまな購入品のアイテムが登録されている場合、下記の通り、PC (パソコン) というグループ化された Region を作成し、この中に、「ビジネス用」、「ノート型」などの Tag を設定できます。

Region と Tag を設定すると、下記の通り、その単位で一括検索やバルク削除などをおこなうことができます。(Tag では、GetObjectsByAllTags、GetObjectsByAnyTag などを使用した And / Or 検索も可能です。ただし、ノードをたどった取得になるため、重複検索などがおこなわれる点に注意してください。)

. . .cache.CreateRegion("PC");cache.Add("prod1", "notebook", "PC");PCItem obj = (PCItem) cache.Get("prod1", "PC");var cache = factory.GetCache("HogeHoge");cache.CreateRegion("PC");DataCacheTag tag1 = new DataCacheTag("note");DataCacheTag tag2 = new DataCacheTag("business");cache.Add("prod1",obj1,new List<DataCacheTag> {tag1},"PC");cache.Add("prod2",obj2,new List<DataCacheTag> {tag2}, "PC");cache.Add("prod3",obj3,new List<DataCacheTag>{tag1,tag2}, "PC");IEnumerable<KeyValuePair<string, object>> result =    cache.GetObjectsByTag(tag1, "PC"); // prod1, prod3. . .

なお、Region は パーティション化の対象となり、同じ Region のアイテムは同じホストに配置されます。このため、異なる Region に対して同じ Tag を付けても、結局、Region ごとにしか検索できないので注意してください。

キャッシュ アイテムのバージョン

アイテムには「バージョン」が付与されます。ただし、このバージョンの概念は、「世代すべての管理」とはやや異なる概念ですので注意してください。

通常、「バージョン管理」というと、過去のすべてのバージョンのアイテムが管理され、過去のアイテムへのロールバックなども可能な場合が多いでしょう。しかし、Velocity における「バージョン」は、こうしたバージョン管理ではなく、単に、アイテムに対してバージョン キーを付与するというものです。このため、例えば、いつの世代のアイテムであるかアプリケーションから検証する場合などに使用できます。
以下に、サンプルを掲載します。

. . .DataCacheItemVersion ver1 = cache.Add("Foo", obj1);DataCacheItemVersion ver2 = cache.Put("Foo", obj2);DataCacheItemVersion ver = default(DataCacheItemVersion);MyObj res = (MyObj) cache.Get("Foo", out ver);if (ver.CompareTo(ver1) == 0)    Console.WriteLine("res is Version1"); // not hitelse if(ver.CompareTo(ver2) == 0)    Console.WriteLine("res is Version2"); // hit !. . .

キャッシュ アイテムのセキュリティ

Velocity で管理されるアイテムは、セキュリティ モード (Security Mode) と保護レベル (Protection Level) という 2 つの概念で保護できます。

セキュリティ モード (Security Mode)
Noneいかなるクライアントもアクセス可能です
Transport (既定)許可された Windows アカウント(ユーザー、グループ、マシン) のみが接続可能です
保護レベル (Protection Level)
None保護しないモード
Signデータの整合性チェックをおこない、データの不正操作や改ざんを防止します
(Security Mode が Transport の場合のみ有効です)
EncryptAndSign (既定)上記の改ざん防止に加え、データを暗号化することで外部からの読み取りも防止します
(Security Mode が Transport の場合のみ有効です)

このセキュリティの設定は、サーバー側とクライアント側の双方でおこないます。(クライアント側は、.config に記載する方法と、プログラムを使用して securityProperties に設定する方法があります。)

このセキュリティ設定ですが、既定では、上記の通り EncryptAndSign になっていますが、無論、セキュリティ設定によるオーバーヘッドも無視できない場合があるので、注意してください。下記は、PowerShell を使って、サーバー側のセキュリティ設定を無効にする場合の例です。

Set-CacheClusterSecurity -SecurityMode None -ProtectionLevel None

キャッシュ アイテムのライフサイクル

アイテムは、既定では揮発的なものです。
そして、以下の Expiration と Eviction の概念の組み合わせで、この生存方針を設定できます。

Expiration
ExpirableFalse にすると下記の Eviction のみが評価され、True にすると有効期限 (時間) が評価されます
(既定は True です)
default TTLTime To Live (生存時間) を設定します
(既定は 10 分です)
Eviction
EvictionTypeここは、現在、None (Eviction なし) か LRU (least recently used, 使用頻度が高いアイテムを優先するアルゴリズム) しか指定できません
(既定は LRU です)

このライフサイクルは、PowerShell やサーバー上の構成を使ってキャッシュごとに設定しますが、キャッシュ アイテムごとに生存時間 (TTL) を上書きできます。

なお、Expiration と Eviction を無効にすると、生存状態をすべてアプリケーションで管理できます。(下記は、PowerShell での設定例です。) しかし、それでも、ホストが停止した場合 (かつ、HA オプションが有効でない場合) など、アイテムが消滅する可能性は常にあるので、基本的に、揮発的なデータを管理するものとして使用してください。

New-Cache HogeHoge -Expirable false -Evication None

ローカル キャッシュ

キャッシュ アイテム (の Primary) は、分散された (サーバーの) ホスト上のどこか 1 箇所に必ず存在し、クライアント (Web アプリケーションなど) からアイテムを取得する場合、この問い合わせはルーティングされ、該当のホストからアイテムが取得されます。(この既定の状態を Partitioned Cache と呼びます。)
ここで紹介するローカル キャッシュでは、参照系データなどの場合に、このアイテムをクライアント側にキャッシュすることで、さらに効率化 (呼び出しのオーバーヘッドの低減) をおこなうことができます。また、アイテムは、シリアライズされず、参照が使用されるため、大きなデータなどではスループットはさらに向上します。(なお、ローカルにアイテムがない場合は、サーバーからアイテムが取得され、逆シリアライズされます。)

このローカル キャッシュには、時限方式の TimeoutBased と、ポーリングベースの NotificationsBased が使用できます。下記の構成 (クライアント側の .config) は、NotificationBased を使用している設定例です。

. . .<dataCacheClient>  <localCache isEnabled="true" sync="NotificationBased" objectCount="100000" ttlValue="300" />  <!--(optional) キャッシュ更新通知のポーリング間隔 -->  <clientNotification pollInterval="300" />  . . .

localCache (上記) には、以下の属性を設定できます。

isEnabledTrue に設定することで、ローカル キャッシュを有効化します
sync上述した TimeoutBased  (時限方式によるキャッシュ無効化) と NotificationsBased  (時限方式に加え、通知方式によるキャッシュ無効化) の設定です
(既定では、300 秒ごとにポーリングをおこないます)
objectCountクライアント側にキャッシュできるデータの個数を指定します
(既定値は 100000 です)
ttlValue無効化の時間設定 (単位は秒) です
(既定値は 300 です)

ローカル キャッシュでは、そのメカニズムから、データ一貫性が犠牲になるという点に注意してください。
また、Tech Ed Japan 2010 でも説明したように、このローカル キャッシュは、キャッシュ ファクトリー単位で設定されます。(プログラム コードを使って、ファクトリーごとに設定することも可能です。詳細は、「Velocity における Partitioned キャッシュとローカルキャッシュの併用」 を参照してください。) このため、例えば、ASP.NET の Web アプリケーションなどで、毎回ファクトリーを作成しなおすようにプログラミングしている場合は、ローカル キャッシュが効かなくなってしまいますので注意してください。(ASP.NET の場合、キャッシュ ファクトリーを、Application、Session、static 変数などに保持します。)

悲観ロック (Pessimistic locking)

上述の通り、Partitioned Cache では、単一のホスト上のアイテムが使用されるため、アイテムの書き込み / 読み取りの一貫性が保証されます。しかし、例えば、データを読み込んでカウント アップするようなケースなど、一連の時間を伴う処理での一貫性は保証されません。
こうした場合には、下記の通り、悲観的ロックのための API (GetAndLock / PutAndUnlock / Unlock) が使用できます。

. . .obj1 = cache.GetAndLock("Foo", TimeSpan.FromSeconds(10),  out handle, true);任意の処理の実行 ...cache.PutAndUnlock("Foo", obj2, handle);. . .

この API ですが、現状は、「待機」の仕組みを持っていません。(このため、待機をおこなうには、例外を処理する必要があります。) また、ロック時には、他からの Put 処理なども保護されません。(あくまでも、アプリケーション側で、統一的に PutAndLock をおこなった場合に、ロックが有効になります。)
このため、悲観的ロックを使用する場合は、アプリケーション側でも、このロック メカニズムを意識した実装をおこなう必要があります。

通知 (Notification)

Velocity では、キャッシュ / Region / アイテムの各レベルの更新を通知できます。
例えば、以下は、キャッシュ全体で、アイテムと Region に発生した更新処理を通知するサンプルです。

. . .using Microsoft.ApplicationServer.Caching;static void Main(string[] args){    DataCacheOperations allCacheOperations =        DataCacheOperations.AddItem |        DataCacheOperations.ReplaceItem |        DataCacheOperations.RemoveItem |        DataCacheOperations.CreateRegion |        DataCacheOperations.ClearRegion |        DataCacheOperations.RemoveRegion;    var factory = new DataCacheFactory();    var cache = factory.GetCache("HogeHoge");    cache.AddCacheLevelCallback(allCacheOperations, delegate(        string myCacheName,        string myRegion,        string myKey,        DataCacheItemVersion itemVersion,        DataCacheOperations OperationId,        DataCacheNotificationDescriptor nd)        {            Console.WriteLine("Cache-Level Notification");            Console.WriteLine("tCache:{0}", myCacheName);            Console.WriteLine("tRegion:{0}", myRegion);            Console.WriteLine("tKey:{0}", myKey);            Console.WriteLine("tOperationId:{0}", OperationId.ToString());            Console.WriteLine("tDescriptor:{0}", nd.ToString());        });    Console.WriteLine("終了するには Enter");    Console.ReadLine();}
<configuration>  <configSections>    . . .  </configSections>  <dataCacheClient>    <hosts>      <host name="kkdeveva01" cachePort="22233"/>    </hosts>    <clientNotification pollInterval="10" />  </dataCacheClient>  . . .

この通知ですが、上記の構成 (.config) を見ていただくとわかるように、ポーリングによる通知メカニズムであるという点に注意してください。このため、現状は、キャッシュの更新処理をトリガするような Cache through feature のような目的で使用することはできません。
また Remove も通知されますが、expiration / eviction による通知は、非常に遅いタイミングで返ってきますので注意してください。

高可用性オプション (High Availability, HA)

AppFabric cache では、障害発生によるノード (マシン) の突然の停止の際に、キャッシュ内のデータをロストしないための設定が可能です。Windows PowerShell で、下記の通り設定します。

New-Cache HogeHoge -Secondaries 1

上記の設定をおこなうことで、Key-Value のアイテムは、常に、Primary と Secondary の双方が異なるノード上に配置されるようになります。(書き込みをおこなうと、Primary、Secondary の双方に、同期的に書き込みをおこないます。) そして、ノードがトラブルなどで停止した場合も、Primary、Secondary の再配置をして、引き続き、高可用性を保障します。

この動きのイメージを、下記のスライド ショーで示します。(下図を Click してください)

なお、Windows Server 2008 以降の Enterprise Edition / Datacenter Edition 以上のエディションが必要となるので、注意してください。

管理 / 監視

以前、「Windows Server AppFabric caching 入門」で解説したように、Windows PowerShell を使って、クラスター、キャッシュの操作 (開始/停止、キャッシュ作成、など) がおこなえますが、こうした「操作」以外の管理用途でも Windows PowerShell を活用することができます。
例えば、以下のコマンドでは、そのノードに配置されているアイテムの状況 (個数など) を確認できます。

Get-CacheStatistics -HostName machine1 -CachePort 22233

また、プログラミングを使って、構成 (config) の設定、オブジェクトの取得など、管理的な記述もおこなえます。例えば、下記では、すべての Region のすべてのアイテム (Key-Value) の内容を確認しています。(C# の例です。)

string cachename = Console.ReadLine();var factory = new DataCacheFactory();var cache = factory.GetCache(cachename);List<string> regions = (List<string>) cache.GetSystemRegions();foreach (string region in regions){  IEnumerable<KeyValuePair<string, object>> items =     cache.GetObjectsInRegion(region);  if (items.Count<KeyValuePair<string, object>>() > 0)    Console.WriteLine("Region:{0}", region);  foreach (KeyValuePair<string, object> item in items)  {    Console.WriteLine("Key:{0} Value:{1}",      item.Key, item.Value.ToString());  }}

Windows PowerShell の Get-CacheRegion (Region の一覧と、ホスト名が返ってきます) と上記を組み合わせれば、どのアイテムが、どのホストにあるか、一覧を取得することもできます。チューニングや状態確認などをおこなう上で、Windows PowerShell やプログラム コードが非常に役に立つことがおわかり頂けるでしょう。

また、サービス起動時のエラーなど基本的なものはイベント ビューアー (eventvwr) で確認できますが、キャッシュへの操作内容 (Get など) の監視など、細かな操作の監視をおこなう場合は、Windows SDK の tracelog.exe を使用して、以下の通り、ETW トレースをおこないます。

rem -- ETW トレースを開始して test.etl に出力tracelog -start debugtrace -f test.etl -guid "C:\Windows\System32\AppFabric\Manifests\Provider\GUID.txt" -level 5 -cir 512rem -- ETW トレースを終了tracelog -stop debugtracerem -- トレースの内容を CSV として出力tracerpt .test.etl -o test.csv -of CSV

アプリケーションへの応用

Velocity では、基本的には、Get/Put/Add/Remove などのプリミティブ (Primitive) な操作を提供するのみで、アプリケーション レベルの Abstraction は、開発者みずからが構築します。
しかし、いくつかの基本的な Abstration (アプリケーション) については、下記の通り、既にさまざまな形で提供されていますので、いくつかを紹介します。

  • ASP.NET Session での使用 :
    ASP.NET の Session データの格納先としてこのインメモリ キャッシュ (AppFabric Cache) を使いたい場合、実は、Velocity が提供しているアセンブリの中に、既にこのためのプロバイダー クラスが提供されています。以下は、このクラス (DataCacheSessionStoreProvider) を使って sessionState を構成したサンプルです。(Tech Ed Japan で説明したいくつかの注意点がありますが、ここでは、これらの説明は省略します。。。)
<sessionState mode="Custom" customProvider="MyVelocity">  <providers><add name="MyVelocity"  type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider, Microsoft.ApplicationServer.Caching.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3,856ad364e35"  cacheName="SessionTest"/>  </providers></sessionState>
  • OR マッパーの second level cache としての使用 :
    ADO.NET Entity Framework や NHibernate などの second level cache として使用する場合、CodePlexSourceForge に Velocity 用のライブラリが提供されています。
  • ASP.NET のキャッシュ プロバイダー :
    ASP.NET 4 では、System.Web.Caching.OutputCacheProvider クラスから派生して独自のキャッシュ プロバイダーを作成できます。
    この手法を使用して、Velocity を使用した出力キャッシュのプロバイダーを構築することも可能です。(なお、Windows Azure caching では、このプロバイダー クラスが既定で提供されています。)

補足 : ASP.NET Session で使用する際には、下記の通り、アプリケーション プールの Virtual Account にもキャッシュの利用権限を付与しておきましょう。
Grant-CacheAllowedClientAccount “IIS APPPOOLASP.NET v4.0”

 

以上、スタートされる方のために、まず、どのようなことが可能か大まかに解説しました。以降の詳細 (疑問等) は、是非 MSDN をご活用ください。

 

Categories: Uncategorized

Tagged as:

5 replies»

Leave a Reply