Summary
Observing that many Web applications handle more data reads than writes, Michael Nygard outlines two popular techniques to improve application performance using commodity, off-the-shelf hardware and software.
Advertisement
Observing that:
The reflexive answer to scaling is, "Scale out at the web and app tiers, scale up in the data tier."
Nygard first discusses the most common approach to scaling the data tier: cache pools. Both open-source and commercial products serve this need well:
Your application almost certainly does more reads than writes, probably to an overwhelming degree... For a travel site, the ratio will be about 10:1. For a commerce site, it will be from 50:1 to 200:1. There are a lot of variables here, especially when you start doing more effective caching, but even then, the ratios are highly skewed...
Pretty much every web app is already caching a bunch of things at a bunch of layers... The net result of all this caching is a lot of redundancy... By moving the cache out of the app server process, you can access the same cache from multiple instances, reducing duplication. Getting those objects out of the heap, You can make the app server heap smaller, which will also reduce garbage collection pauses. If you make the cache distributed, as well as external, then you can reduce duplication even further...
Nygard then introduces another approach to scaling out the data tier, using the built-replication capabilities of many database products:
When your database starts to get that middle-age paunch and it just isn't as zippy as it used to be, think about offloading those reads...
How do you create a read pool? Good news! It uses nothing more than built-in replication features of the database itself. Basically, you just configure the write master to ship its archive logs (or whatever your DB calls them) to the read pool databases. They spin up the logs to bring their state into synch with the write master...
As with external data caching, read pools will also cause some members of the pool to be slightly out-of-date, which Nygard observes may be acceptable for many applications:
The read machines will always reflect an earlier point in time... Does that matter? To a certain extent, I can't answer that. It might matter, depending on your domain and application. But in general, I think it matters less often than it seems.
What do you think of read pools? How do you scale up your data tiers?
One of the things to remember is that transactional consistency is generally only necessary for the transactions themselves (and not the web pages), because the transaction demarcation is conducted by the servers within the scope of a single request, and not by the client (e.g. browser) across a scope of multiple requests. That means that no matter how up to date your data is when you put together a web page, it will be stale by the time the app server writes it to a stream, which means it will be more stale by the time the browser receives it, which means it will be significantly more stale by the time the browser renders it, which means it will be very stale by the time the end user reads it, and so stale as to be almost putrid by the time that the end user manages to click on some action related to it, let alone by the time that request makes it back to the server.