This post originated from an RSS feed registered with .NET Buzz
by Udi Dahan.
Original Post: Caching won't save you from poor design
Feed Title: Udi Dahan - The Software Simplist
Feed URL: http://feeds.feedburner.com/UdiDahan-TheSoftwareSimplist
Feed Description: I am a software simplist. I make this beast of architecting, analysing, designing, developing, testing, managing, deploying software systems simple.
This blog is about how I do it.
During the break at last week's .Net user group, I talked with Gizi - one of the more senior developers that I've met. After my previous talk on caching, he asked for my opinion on certain issues and that sparked a dialogue.
Anyway, his question deals with a project he's currently working on. The system deals with exchange rates, and its data must be available to several other systems. The data arrives in file form once every X time, and is then inserted into a database which is accesible to all systems.
The system is a web-app, and the requirement was for high-performance read access to the exchange rates. Gizi started looking for a caching solution to decrease the number of database hits. His problem was the dependency of the items in the cache. He wanted to do some type of file dependency, but it wasn't really working out.
The first solution I suggested took advantage of the fact that both the DB and the APP itself would be on the same physical server. SQL server can touch a file quite easily, and doing so in a trigger on the table where the exchange rates are stored after an insert, update, or a delete would enable the DB to notify the APP of the change. There were two problems with this approach.
One - should the database be moved to a different server, this wouldn't work without changing the APP. The solution is quite simple, create a simple web service on the APP server that touches a file there. This file will be used as the dependency for the cache. Then, compile the proxy that calls the web service into an exe and place it on the DB server. In the trigger, call the exe, and all's well.
Two - and this is WAY more important than one - this solution doesn't provide the appropriate resolution - there's no way to know which exchange rates changed, so the APP would have to get ALL the data EVERY TIME a change occurs. This caching would cause worse performance than just hitting the DB on every read !
The solution that seemed to be best had no explicit caching in it. All reads would be done via a service - ExchangeRates.Get(currencyCode from, currencyCode to). Inside the service, all the rates would be stored in memory, all the time, and only once. No calls would ever be made to the DB. When a new file arrived containing the updated exchange rates, a separate windows service would "wake up" and do the following: call a webservice on the APP ( like ExchangeRates.Set(string from, string to, double value) ) which would update the data in memory in the APP, and only afterwards update the DB.
The solution of course needs a mechanism for starting from scratch - possibly calling the windows service to act again on the most recent file.
This solution uses no explicit caching - the data itself is the cache, and it's always kept up to date in memory. No polling is required. Furthermore, the system places no load on the database and fulfills the requirement for high-performance reads.
Sometimes, caching doesn't improve system-wide performance and what's really needed is a redesign.