Ingo [email protected]
Verteiltes Caching mit Windows Server AppFabric
Ingo Rammer und thinktecture
Unterstützung und Consulting von Software-Entwicklern und –Architekten im Windows- und .NET-Umfeld
• Entwickler-Coaching und –Mentoring• Architektur-Consulting und –Prototyping• Architektur- und Code-Reviews• Anwendungsoptimierung, Troubleshooting, Debugging
http://[email protected]
Caching in 30 Seconds
•AppFabric Caching (Velocity) is a Windows Service for highly scalable distributed caching•Multiple physical nodes are combined to form one big virtual cache
So first … let‘s start the virtual machines …
WebServer #1
WebServer #2
WebServer #3
WebServer #n
Load Balancer
Data
User
Web Server
Data
Application
Session State
LocalCaching
Today‘s Issues
Session stateInProc, Session server, database?Availability, Single-Point-Of-Failure, Performance
CachingCache consistency when using multiple servers
WebServer
#1
WebServer
#2
WebServer
#3
WebServer
#n
Load Balancer
CacheServer
#1
CacheServer
#2
AppFabric Caching
WebServer
#1
WebServer
#2
WebServer
#3
WebServer
#n
Load Balancer
CacheServer #1
CacheServer
#2
Configuring AppFabric
AdministrationPowershellCluster config centrally in XML file or in SQL Server
Notebook directly: Windows 7 with IIS and Visual StudioFour virtual machines:
VCacheDC
Domain ControllerSQL Server
VCache01
AppFabric
VCache02
AppFabric
VCache03
AppFabric
Named Caches
VCache01 VCache02 VCache03Cache: default
Cache: sessiondata
Additional caches … with different configuration
Cache Administration
Administration via PowershellLoading the module
Import-Module DistributedCacheAdministrationGet-CacheHelp
Creating a new cache: New-Cache democacheStarting the Cluster: Start-CacheClusterStatus: Get-CacheHost
AppFabric Caching w/o Security
Export-CacheClusterConfig c:\test.xmlAdd advancedProperties
Import-CacheClusterConfig c:\test.xml
<dataCache> <advancedProperties> <securityProperties mode="None" protectionLevel="None" /> </advancedProperties> <caches>…</caches> <hosts>…</hosts></dataCache>
AppFabric Caching „Hello World“
Configuring the client
<configuration> <configSections> <section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /></configSections>
<dataCacheClient> <hosts> <host name="VCache01" cachePort="22233“ /> </hosts> <securityProperties mode="None" protectionLevel="None"/></dataCacheClient>
AppFabric Caching „Hello World“
•Adding References from C:\Windows\System32\AppFabricMicrosoft.ApplicationServer.Caching.Client and Microsoft.ApplicationServer.Caching.CoreHave to be copied first
DataCacheFactory fact = new DataCacheFactory();DataCache myCache = fact.GetCache("democache2");
string someKey = "myKey";string someValue = "testing"; // anything [Serializable]
myCache.Put(someKey, someValue);
string result = (string) myCache[someKey];
VCache01 VCache02 VCache03
Cache: default
Storing and Distribution.NET Client
Prod-1Prod-2
Prod-4 Prod-3
DataCache defaultcache = GetCache("default");Product prod = GetProduct(...);defaultcache.Put("Prod-1",prod);
defaultcache.Put("Prod-2",prod2);defaultcache.Put("Prod-3",prod3);defaultcache.Put("Prod-4",prod4);
Other named caches …
Scaling the Cache
Scaling sizeMore machines == more memory
Scaling throughputMore machines == higher throughput
„Local Cache“Directly at client == massively lower latencyHigher throughput when readingBut also: items are older, can get stale
Item Routing
Velocity #1 Velocity #2 Velocity #3
Prod-1
.NET ClientDynamic Routing
Table
Prod-2Prod-4
Prod-3
defaultcache.Put("Prod-1",prod);
Node Failure
Velocity #1 Velocity #2 Velocity #3
Prod-1
.NET ClientDynamic Routing
Table
Prod-2
Prod-4Prod-3
object p1 = defaultcache["Prod-1"];object p1 = defaultcache["Prod-1"];
if (p1==null){ p1 = GetProductFromDatabase(...) defaultcache.Put("Prod-1", p1);}
Prod-1
Regions and Tags
•Optional•All elements in a region live on the same node•Can be tagged•Allow BulkGet and bulk delete
Kinds of Data
Reference Data: "never" changes (catalog data, price lists, …)Activity data: non-concurrent changes (session data, shopping cart, …)Resource data: high concurrency data, constantly changing (inventory level, …)
Analysing DataPerformance – Throughput and latencyConsistency – Guaranteed or eventualRecoverability – Can the data be restored from DB (cache eviction?)Availability – What happens at node failure
Local CacheChosen in config or codeIn practice: often code, because only specific parts should be cached locally (DataCacheFactory)Good for reference dataSynchronization
Age of itemsNotification
Notifications
Pub/sub on cache item changesCallbacks for complete cache, for a region or for a single itemAre currently (beta 2) queued at server side and regularily polled by the clientCache has to be configured for notifications
New-Cache <name> -NotificationsEnabled true
Concurrency
•Optimistic and pessimistic locking
DataCacheItemVersion ver = default(DataCacheItemVersion);object itm = defaultCache.Get("region", "key", ref ver);
// after change (throws an exception if modified in meantime)defaultCache.Put("region","key", itm, ver);
DataCacheLockHandle lockHandle;object itm = defaultCache.GetAndLock("region", "key", TimeSpan.FromSeconds(30), out lockHandle);
// after change:defaultCache.PutAndUnlock("region", "key", itm, lockHandle, null);
Session State
<sessionState mode="Custom" customProvider="Velocity"> <providers> <add name="Velocity" type="Microsoft.ApplicationServer.Caching.DataCacheSessionStoreProvider, Microsoft.ApplicationServer.Caching.Client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" cacheName="sessiondata" retryCount="5"/>
</providers></sessionState>
High Availability
Velocity #1 Velocity #2 Velocity #3
Sess-1(Primary)
sessionCache.put("Sess-1", se1);
Sess-1 (Secondary)
Sess-2(Primary)
Sess-2 (Secondary)
sessionCache.put("Sess-1", se1);sessionCache.put("Sess-2", se2);
Failover with High Availability
Velocity #1 Velocity #2 Velocity #3
Sess-1(Primary)
sessionCache.put("Sess-1", se1);
Sess-1 (Secondary)
Sess-2(Primary)
Sess-2 (Secondary)
sessionCache.put("Sess-1", se1);sessionCache.put("Sess-2", se2);
Sess-2(Primary)Sess-2 (Secondary)
Sess-1(Secondary)
Configuring High Availability
•Powershell• New-Cache <name> -Secondaries 1 •Maybe also:• –Eviction None • –NotExpirable trueStarting with Beta2: Only supported on Enterprise (and Data Center) operating system editions