Ruby is also one of the most popular language used today by Web developers to build brilliant applications. The rise of the Rails framework was actually one of the main reasons this language received such popularity, however, Ruby is also a Swiss Army Knife language that is often used by system administrators for orchestration and automation.
There are of course, several clients to be memcached in Ruby but here we will be focusing on one of the most recent and stable clients that delivers high performance pure Ruby implementation of the memcached protocol, Dalli!
Dalli was written by the maintainer of memcache-client and is currently stable and being actively maintained.
The good thing about Dalli is that it can be integrated with Rails 3.x but, unfortunately, it does not integrate with the more popular Rails 2.x.
We need to install the Dalli gem using the following command:
gem install dalli
If you don't have the gem
tool, then most likely you don't have Ruby properly installed. In Ubuntu you can always use the following to get Ruby installed:
sudo apt-get install ruby
Let's start by doing a very basic
set
/get
operation on the memcached server from Ruby:require 'dalli' dc = Dalli::Client.new('localhost:11211', :threadsafe => true, :compress => true) dc.set('somekey', 123) puts("the value from cache is: #{dc.get('somekey')}")
This looks great; now let's store more complex structures in the memcached server:
require 'dalli' dc = Dalli::Client.new('localhost:11211', :threadsafe => true, :compress => true) user = {:name => "Ahmed", :job => "Engineer"} dc.set('user1', user, ttl=20) puts("user from cache: #{dc.get('user1')}")
Now, let's use a new feature which we did not use before (
replace
)require 'dalli' dc = Dalli::Client.new('localhost:11211', :threadsafe => true, :compress => true) user = {:name => "Ahmed", :job => "Engineer"} dc.set('user1', user, ttl=20) puts("user from cache: #{dc.get('user1')}") user[:age] = 31 dc.replace("user1", user, ttl=5) puts("user from cache: #{dc.get('user1')}")
First, we are importing Dalli into our namespace by using the require
statement. Then, we are creating a client that connects to the memcached server and we are also setting some options. The following are some of the interesting options:
:compress => true
: This will ask Dalli to compress values larger than 1024 bytes.:threadsafe => true
: This ensures that only a single thread is actively using the connection socket at a time; this is actually enabled by default, we added this to the snippet for clarity only.:namespace => "app"
: This adds a prefix to all keys set in this connection.:expires_in => 100
: This sets the default TTL(timeout) for all the keys where you are not specifying a TTL.
Then, we used the simple set
method to set a basic integer value, after we retrieved that value and printed to the console using puts.
In the second snippet, we created a standard Ruby Hash and we used the built-in serializer to store this hash as a value for the "user1"
key.
In the third snippet, we introduced a new feature of memcached, that is replace
. This was used to replace the entire hash stored for the "user1"
key with a modified version (we added age to it).
While we were replacing the value we also respecified the TTL value and changed the TTL of the value to be 5 seconds only. The replace
feature fails if the key is not already stored in the memcached server and that's the main difference between it and the method that you are already familiar with set
.
The constructor of the Client
class can also accept a list of servers to specify, in case you have a memcached cluster as you can see, it's a list of servers.
Dalli::Client.new(['localhost:11211:10', 'cache-2.example.com:11211:5', '192.168.0.1:22122:5'], :threadsafe => true, :failover => true, :expires_in => 300)
For every server, the format is server:port:weight
, where weight allows you to distribute cache unevenly. Both weight and port are optional. If you pass in nil, Dalli will use the MEMCACHE_SERVERS
environment variable or default to localhost:11211
if it is not present.