blog.waterlow.work

Ruby, Rails, js, etc...

【Ruby】【キャッシュ】dalli(memcachedのクライアントgem)を使ってみました

目的

memcachedrubymemcachedクライアントであるgemのdalliを使ってみたのでまとめ

memcached.org github.com

少し前に、キャッシュについていろいろやらないといけない機会があったのですが
キャッシュを実現するミドルウェアを触ったことがなかったため、手も足も出ないような状況になってしまいました。

これを期にキャッシュに使われるミドルウェアを触っていこうと思い
手始めにmemcachedと、rubyクライアントの中で割りと広く使われているdalliを触ってみました。 基本的な使い方と、覚えておけばどこかで役立ちそうな使い方についてまとめてみます。

基本的な使い方(インストールから)

インストールはgemのreadmeに親切に書いてあるのでその通りにやりましょう

$ brew install memcached
$ gem install dalli

使いかたもreadmeと一緒ですが、irbで以下のように叩くと試せます。

irb(main)> require 'dalli'
irb(main)> options = { namespace: 'app_v1', compress: true }
irb(main)> dc = Dalli::Client.new('localhost:11211', options)
irb(main)> dc.set('abc', 123)
irb(main)> dc.get('abc') # => 123

deleteしたり、有効期間を指定してsetするとかが出来ます

irb(main)> dc.set('abc', 123)
irb(main)> dc.delete('abc')
irb(main)> dc.get('abc') # => nil
irb(main)>
irb(main)> dc.set('abc', 123, 5)
irb(main)> dc.get('abc') # => 123
irb(main)> sleep 6
irb(main)> dc.get('abc') # => nil

覚えていて役立ちそうな使い方1(get_multi)

1つのキーに対するget、set、deleteはできるけど、複数キーはどうなの?という話。 memcachedのコマンドだと同じgetでできるみたいです。

github.com

dalliの場合はDalli::Client#get_multiを使います。

irb(main)> dc.set('abc', 123)
irb(main)> dc.set('def', 456)
dc.get_multi('abc', 'def') # => {"abc"=>123, "def"=>456}

DBと組み合わせて使うときに、N+1対策で使えそうです。

覚えていて役立ちそうな使い方2(cas)

Check And Set (or Compare And Swap)の略で、memcachedで楽観的ロックを実現するための機能です

irb(main)> dc.set('a', 'value1')
irb(main)> dc.cas('a') { 'value2' }
irb(main)> dc.get('a') # => value2
irb(main)> dc.cas('a') { |v| sleep 10 "#{v}+1" } # sleepの間に別コンソールでdc.set('a', 'value4')を実行する
=> false
irb(main)> dc.get('a') # => value4

casメソッドのブロックの中で行う処理に関しては、他者がそのキーの値を変更していない場合のみ書き込みでき
変更している場合にはfalseが返され書き込みに失敗します。
配列みたいなデータ構造があると、ロックと組み合わせてキューみたいな使い方ができるかなと思いました。

casメソッドにまかせている色々なことを、自力でやることもできます。詳細は述べませんが、以下のようにやるといろいろメソッドが追加されます。

irb(main)> require 'dalli/cas/client'

詳細は以下

dalli/client.rb at master · petergoldstein/dalli · GitHub