14. Example: Transactions
$ redis-cli
...
redis> SET "player:1:coins" 30
redis> SET "player:2:coins" 63
# ... Players decide to trade some coin
redis> MULTI
redis> INCRBY "player:1:coins" 15
redis> DECRBY "player:2:coins" 15
redis> EXEC
# 1. (integer) 45
# 2. (integer) 48
15. In-memory storage
• Simple single process event
driven design
• No locks
• 100K+ operations per second
16. Asynchronous persistence
• Snapshotting - save 60 1000
# dump every 60 seconds if at least 1000
keys changed
• Append-only file - durable with log
rewrite support
17. Master-slave replication
slaveof '192.168.1.1' 6379
• Multiple slaves
• Slaves of slaves
• Scalability
• Defer save to
slaves
29. require 'rubygems' $ redis-cli
require "redis" ...
redis> PUBLISH rubyfuza:chat "Smoke me a
redis = Redis.connect kipper..."
redis> PUBLISH rubyfuza:chat "I'll be back
trap(:INT) { puts; exit } for breakfast."
redis> PUBLISH rubyfuza:chat "exit"
redis.subscribe('rubyfuza:chat') do |on|
on.subscribe do |channel, subscriptions|
puts "Subscribed to ##{channel}"
end
on.message do |channel, message|
puts "##{channel}: #{message}"
redis.unsubscribe if message == "exit"
end
on.unsubscribe do |channel, subscriptions|
puts "Unsubscribed from ##{channel}"
end
end
30. Resque
• Backed by redis
• Asynchronous job server
• Multiple queues
• Sinatra based web-ui
31. class PostalWorker
@queue :post_box
def self.perform( user_id )
User.where( :id => user_id )
msg = UserMail.welcome_message( user )
msg.deliver
end
end
...
Resque.enqueue( PostalWorker, user.id )