In my efforts to learn more about Web development and what it is like for startups adopting Web platforms I've decided to build an application on the Facebook platform. I haven't yet decided on an application but for the sake of argument let's say it is a Favorite Comic Books application which allows me to store my favorite comic books and shows me to most popular comic books among my friends.
The platform requirements for the application seems pretty straightforward. I'll need a database and some RESTful Web services which provide access to the database from the widget which can be written in my language of choice. I'll also need to write the widget in FBML which will likely mean I'll have to host images and CSS files as well. So far nothing seems particularly esoteric.
Since I didn't want my little experiment eventually costing me a lot of money, I thought this was an excellent time to try out Amazon's Simple Storage Service (S3) and Elastic Compute Cloud (EC2) services since I'll only pay for as much resources as I use instead of paying a flat hosting fee..
However it seems supporting this fairly straightforward application is beyond the
current capabilities of EC2 +
S3. S3 is
primarily geared towards file storage so although it makes a good choice for cheaply
hosting images and CSS stylesheets, it's a not a good choice for storing relational
or structured data. If it was just searching within a single user's data (
e.g. just searching within my favorite comics) I could store it all in single XML file
then use XPath to find what I was looking for. However my application will need to
perform aggregated queries across multiple user's data (i.e. looking at the favorite
comics of all of my friends then fetching the most popular ones) so a file based solution
isn't a good fit. I really want a relational database.
EC2 seemed really promising because I could create
a virtual server running in Amazon's cloud and load it up with my choice of operating
system, database and Web development tools. Unfortunately, there was a fly in the
ointment. There is no persistent storage in
EC2 so if your virtual server goes down for any
reason such as taking it down to install security patches or a system crash, all
your data is lost.
This is a well known problem within the
EC2 community which has resulted in a bunch of
clever hacks being proposed by a number of parties. In his post entitled
Amazon EC2, MySQL, Amazon S3 Jeff Barr of
Amazon writes
I was on a conference call yesterday and the topic of ways to store persistent data when using Amazon EC2 came up a couple of times. It would be really cool to have a persistent instance of a relational database like MySQL
but there's nothing like that around at the moment. An instance can
have a copy of MySQL installed and can store as much data as it would
like (subject to the 160GB size limit for the virtual disk drive) but
there's no way to ensure that the data is backed up in case the
instance terminates without warning.
Or is there?
It is fairly easy to configure multiple instances of MySQL in a
number of master-slave, master-master, and other topologies. The master
instances produce a transaction log each time a change is made to a
database record. The slaves or co-masters keep an open connection to
the master, reading the changes as they are logged and mimicing the
change on the local copy. There can be some replication delay for
various reasons, but the slaves have all of the information needed to
maintain exact copies of the database tables on the master.
Besides the added complexity this places on the application, it still isn't fool proof as is pointed out in the various comments in response to Jeff's post.
Demitrious Kelly who also realizes the problems with relying on replication to solve the persistence problem proposed an alternate solution in his post MySQL on Amazon EC2 (my thoughts) where he writes
Step #2: I’m half the instance I used to be! With each AMI you get
160GB of (mutable) disk space, and almost 2GB of ram, and the
equivalent of a Xeon 1.75Ghz processor. Now divide that, roughly, in
half. You’ve done that little math exercise because your one AMI is
going to act as 2 AMI's. Thats right. I’m recommending running two
separate instances of MySQL on the single server.
Before you start shouting at the heretic, hear me out!
+-----------+ +-----------+
| Server A | | Server B |
+-----------+ +-----------+
| My | My | | My | My |
| sQ | sQ | | sQ | sQ |
| l | l | | l | l |
| | | | | |
| #2<=== #1 <===> #1 ===>#2 |
| | | | | |
+ - - - - - + + - - - - - +
On each of our servers, MySQL #1 and #2 both occupy a max of 70Gb of
space. The MySQL #1 instances of all the servers are setup in a
master-master topography. And the #2 instance is setup as a slave only
of the #1 instance on the same server. so on server A MySQL #2 is a
copy (one way) of #1 on server A.
With the above setup *if* server B were to get restarted for some
reason you could: A) shut down the MySQL instance #2 on server A. Copy
that MySQL #2 over to Both slots on server B. Bring up #1 on server B
(there should be no need to reconfigure its replication relationship
because #2 pointed at #1 on server A already). Bring up #2 on server B,
and reconfigure replication to pull from #1 on ServerB. This whole time
#1 on Server A never went down. Your services were never disrupted.
Also with the setup above it is possible (and advised) to regularly
shut down #2 and copy it into S3. This gives you one more layer of
fault tollerance (and, I might add, the ability to backup without going
down.)
Both solutions are fairly complicated, error prone and still don't give you as much reliability as you would get if you simply had a hard disk that didn't lose all its data when you rebooted the server goes down. At this point it is clear that a traditional hosted service solution is the route to go. Any good suggestions for server-side LAMP or WISC hosting that won't cost an arm and a leg? Is Joyent any good?
PS: It is clear this is a significant problem for Amazon's grid computing play and one that has to be fixed if the company is serious about getting into the grid computing game and providing a viable alternative to startups looking for a platform to build the next "Web 2.0" hit. Building a large scale, distributed, relational database then making it available to developers as a platform is unprecedented so they have their work cut out for them. I'd incorrectly assumed that BigTable was the precedent for this but I've since learned that BigTable is more like a large scale, distributed, spreadsheet table as opposed to a relational database. This explains a lot of the characteristics of the query API of Google Base.