Beruflich Dokumente
Kultur Dokumente
(scaling twitter)
Rails Scales.
(but not out of the box)
First, Some Facts
• 600 requests per second. Growing fast.
• 180 Rails Instances (Mongrel). Growing fast.
• 1 Database Server (MySQL) + 1 Slave.
• 30-odd Processes for Misc. Jobs
• 8 Sun X4100s
• Many users, many updates.
Joy Pain
MAKIN EM GO FAST
It’s Easy, Really.
1. Realize Your Site is Slow
2. Optimize the Database
3. Cache the Hell out of Everything
4. Scale Messaging
5. Deal With Abuse
It’s Easy, Really.
1. Realize Your Site is Slow
2. Optimize the Database
3. Cache the Hell out of Everything
4. Scale Messaging
5. Deal With Abuse
6. Profit
the
more
you
know
• Munin
• Nagios
• AWStats & Google Analytics
• Exception Notifier / Exception Logger
• Immediately add reporting to track problems.
Test Everything
• No Need To Be Fancy
• Agile Becomes
Important When Your
Site Is Down
<!-- served to you through a copper wire by sampaati at 22 Apr
15:02 in 343 ms (d 102 / r 217). thank you, come again. -->
<!-- served to you through a copper wire by kolea.twitter.com at
22 Apr 15:02 in 235 ms (d 87 / r 130). thank you, come again. -->
<!-- served to you through a copper wire by raven.twitter.com at
22 Apr 15:01 in 450 ms (d 96 / r 337). thank you, come again. -->
Benchmarks?
let your users do it.
<!-- served to you through a copper wire by kolea.twitter.com at
22 Apr 15:00 in 409 ms (d 88 / r 307). thank you, come again. -->
<!-- served to you through a copper wire by firebird at 22 Apr
15:03 in 2094 ms (d 643 / r 1445). thank you, come again. -->
<!-- served to you through a copper wire by quetzal at 22 Apr
15:01 in 384 ms (d 70 / r 297). thank you, come again. -->
The Database
{ Part the Second }
“The Next Application I Build is Going
to Be Easily Partitionable” - S. Butterfield
“The Next Application I Build is Going
to Be Easily Partitionable” - S. Butterfield
“The Next Application I Build is Going
to Be Easily Partitionable” - S. Butterfield
Too Late.
Index Everything
class AddIndex < ActiveRecord::Migration
def self.up
add_index :users, :email
end
def self.down
remove_index :users, :email
end
end
def self.down
remove_column "users", "friends_ids"
end
end
class Friendship < ActiveRecord::Base
belongs_to :user
belongs_to :friend
after_create :add_to_denormalized_friends
after_destroy :remove_from_denormalized_friends
def add_to_denormalized_friends
user.friends_ids << friend.id
user.friends_ids.uniq!
user.save_without_validation
end
def remove_from_denormalized_friends
user.friends_ids.delete(friend.id)
user.save_without_validation
end
end
Don’t be Stupid
bob.friends.map(&:email)
Status.count()
“email like ‘%#{search}%’”
That’s where we are.
Seriously.
If your Rails application is doing anything more
complex than that, you’re doing something wrong*.
ve
i d
c t
A cor
R e
90% API Requests
Cache Them!
“There are only two hard things in CS:
cache invalidation and naming things.”
Jabber Client
(drb)
Incoming Outgoing
Presence
Messages Messages
MySQL
Server
DRb.start_service ‘druby://localhost:10000’, myobject
Client
myobject = DRbObject.new_with_uri(‘druby://localhost:10000’)
Rinda
• ActiveMQ (Java)
• RabbitMQ (erlang)
• MySQL + Lightweight Locking
• Something Else?
erlang?