Redis速習会@Wantedly
川崎禎紀 / Yoshinori Kawasaki
シゴトでココロオドル
• Redisの基本的な使い方
• Ruby on RailsからのRedisの使い方
今日速習する内容
シゴトでココロオドル
REmote DIctionary Server
シゴトでココロオドル
In-memory
http://www.eecs.berkeley.edu/~rcs/research/interactive_latency.html
シゴトでココロオドル
• 高速なKVS
– メモリに全てのデータを保存
• 様々なデータ型
– 後述
• ディスクに非同期で永続化
– 後述
• 用途
– データベース
– キャシュ
– message broker
Redis
シゴトでココロオドル
• シングルスレッド
• 普通はCPU律速にならず、メモリまたはネッ
トワーク律速になる
• 最新バージョンは 3.0.5
– https://raw.githubusercontent.com/antirez/redi
s/3.0/00-RELEASENOTES
• ドキュメントがしっかりしている
Redis (contd)
シゴトでココロオドル
$ brew install redis
$ redis-server /usr/local/etc/redis.conf
$ redis-cli
127.0.0.1:6379> PING
PONG
課題 PING
シゴトでココロオドル
127.0.0.1:6379> GET foo
(nil)
127.0.0.1:6379> SET foo bar
OK
127.0.0.1:6379> GET foo
"bar"
127.0.0.1:6379> GETSET foo baz
"bar"
127.0.0.1:6379> GET foo
"baz"
課題 GET, SET
シゴトでココロオドル
• String
– 数値もString
• List
– 双方向リンクリスト
– LPOP, LPUSH, RPOP, RPUSH, RPOPLPUSH…
– ブロッキング版BLPOP, BRPOP, BRPOPLPUSH
• Set
– 集合
• Sorted set
– スコアつき集合
– range queryが使える
– スコアボードとかにつかう
Data Types
シゴトでココロオドル
• Hash
– Key-Value set
• Bitmap (bit array)
– bit列
• HyperLogLog
– 集合のcardinarity
• Geospatial item
– 緯度経度。まだ安定版にはない。
• http://redis.io/topics/data-types
• http://redis.io/topics/data-types-intro
Data Types (contd)
シゴトでココロオドル
127.0.0.1:6379> GET baz
(nil)
127.0.0.1:6379> INCR baz
(integer) 1
127.0.0.1:6379> GET baz
"1"
127.0.0.1:6379> INCRBY baz 1000
(integer) 1001
127.0.0.1:6379> GET baz
"1001"
課題 INCR, DECR
シゴトでココロオドル
127.0.0.1:6379> SET foo hello
OK
127.0.0.1:6379> EXPIRE foo 10
(integer) 1
127.0.0.1:6379> GET foo
"hello"
127.0.0.1:6379> TTL foo
(integer) 1
127.0.0.1:6379> GET foo
(nil)
127.0.0.1:6379> TTL foo
(integer) -2
課題 EXPIRE
シゴトでココロオドル
• http://redis.io/commands
コマンド一覧
シゴトでココロオドル
• RDB
– デフォルト
– 非同期スナップショット
• forkして書き込むので親processでdisk I/O発生しない
– 履歴バックアップしやすい
– リスタート時の読み込みがはやい
– 数分のデータロスの可能性
• AOF
– 追記型
• disk seekが発生しない
– RDBのログ相当(PostgreSQLのWAL)
• 再生可能
– スナップショットよりサイズが大きい
– 単独で使わない方がいい
• 作者は将来統合したいと思っている
– “we'll likely end up unifying AOF and RDB into a single persistence model
in the future (long term plan).”
ディスク永続化
http://redis.io/topics/persistence
シゴトでココロオドル
• Hash, List, Set(整数のみ), Sorted Setはデー
タ数とデータ長が設定値より少ない場合、エン
コードされて保存される
• CPUとメモリのトレードオフ
メモリ最適化されたデータ型
http://redis.io/topics/memory-optimization
シゴトでココロオドル
• noeviction
– don't expire at all, just return an error on write operations
– デフォルト。キャッシュとして使わない場合
• volatile-lru
– remove the key with an expire set using an LRU algorithm
– キャッシュとデータ永続化を両方使いたい場合
• allkeys-lru
– remove any key according to the LRU algorithm
– 冪乗則のアクセスパターンの場合
– まよったらこれ
• volatile-random
– remove a random key with an expire set
– キャッシュとデータ永続化を両方使いたい場合
• allkeys-random
– remove a random key, any key
– 均等にアクセスがある場合
• volatile-ttl
– remove the key with the nearest expire time (minor TTL)
– キャッシュ生成時によいTTLを設定できるならこれ
• EXPIRE使うとメモリを余計にとる
• キャッシュとデータ永続化は別々のRedisインスタンスにするのがオススメ
maxmemoryに達した場合の挙動
http://redis.io/topics/lru-cache
シゴトでココロオドル
$ redis-cli FLUSHALL
$ redis-benchmark -t SET -r 100000 -n 1000000
$ redis-cli INFO | grep used_memory
used_memory:11745408
used_memory_human:11.20M
used_memory_rss:20680704
used_memory_peak:20696752
used_memory_peak_human:19.74M
課題 メモリ使用量
シゴトでココロオドル
• コメントが充実している
• 一度ざっと目を通すのがオススメ
• 場所
– Homebrewでインストールした人
• /usr/local/etc/redis.conf
– GitHub 3.0 branch
• https://github.com/antirez/redis/blob/3.0/redis.conf
課題 設定ファイル
シゴトでココロオドル
$ redis-cli -h 130.211.253.154
130.211.253.154:6379> SUBSCRIBE channels:1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channels:1"
3) (integer) 1
1) "message"
2) "channels:1"
3) "wantedly!"
$ redis-cli -h 130.211.253.154
127.0.0.1:6379> PUBLISH channels:1 wantedly!
(integer) 1
課題 Pub/Sub
シゴトでココロオドル
• Pipelining
– 複数コマンドを同時リクエスト
– RTTを削減
• Transaction
– MULTI / EXECコマンド
– Rollbackはしない
• Luaスクリプト
– EVALコマンド
– RDBのstored procedureのようなことも出来る
• Master-Slave replication
• Redis Sentinel
• Redis Cluster
その他の機能
シゴトでココロオドル
ここからRubyの話になります
シゴトでココロオドル
• redis
• redis-rails
• redis-rack
• redis-activesupport
• redis-actionpack
• redis-namespace
• redis-objects
• hiredis
• sidekiq, resque
Gem
シゴトでココロオドル
Railsと使う場合
# For Rails.cache
# config/application.rb
config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', { expires_in:
90.minutes }
# For session store
# config/initializers/session_store.rb
MyApplication::Application.config.session_store :redis_store, servers:
‘redis://localhost:6379/0/cache’
実体は別のgem
require 'redis-store'
require 'redis-activesupport'
require 'redis-actionpack'
redis-rails gem
シゴトでココロオドル
redis-rails で使えないコマンドが使える
コマンドがそのままメソッド名になっている
# Remove the last element in a list, append it to another list and return it.
#
# @param [String] source source key
# @param [String] destination destination key
# @return [nil, String] the element, or nil when the source key does not exist
def rpoplpush(source, destination)
synchronize do |client|
client.call([:rpoplpush, source, destination])
end
end
redis gem
シゴトでココロオドル
• redis gemはpure ruby
• hiredis gemはCで書かれたconnectionと
reply parserのhiredisを使えるようにする
• benchmark
– https://github.com/redis/hiredis-
rb#benchmarks
hiredis gem
シゴトでココロオドル
Redisのdata typeをRuby的なdata typeにマップしてくれる
class Team < ActiveRecord::Base
include Redis::Objects
lock :trade_players, :expiration => 15 # sec
value :at_bat
counter :hits
counter :runs
counter :outs
counter :inning, :start => 1
list :on_base
list :coaches, :marshal => true
set :outfielders
hash_key :pitchers_faced # "hash" is taken by Ruby
sorted_set :rank, :global => true
end
redis-objects gem
シゴトでココロオドル
@team = Team.first
@team.on_base << 'player1'
@team.on_base << 'player2'
@team.on_base << 'player3'
@team.on_base # ['player1', 'player2', 'player3']
@team.on_base.pop
@team.on_base.shift
@team.on_base.length # 1
@team.on_base.delete('player2')
redis-objects gem (contd)
シゴトでココロオドル
keyにデフォルトのnamespaceをつける
redis = Redis.new
namespaced_redis = Redis::Namespace.new(:foo, redis: redis)
namespaced_redis.set(‘bar’, ‘baz’)
# equivalent to redis.set('ns:foo', 'bar'))
redis.get('foo:bar') # => 'baz'
redis-namespace gem
シゴトでココロオドル
• ソースコード
– git@github.com:wantedly/instant-learn-redis.git
• SNS的なやつ
– User: id, name, email, avatar_url
– Relation: user_id, friend_id
• プロフィールページ
– 共通の友人一覧が遅い
– http://localhost:3000/users/2
課題 mutual friends
シゴトでココロオドル
$ git clone git@github.com:antirez/redis.git
オプショナル課題
シゴトでココロオドル
• 速習したこと
– Redisの基本的な使い方
– Ruby on RailsからのRedisの使い方
• 速習しなかったこと
– Luaスクリプト
– Master-Slave replication
– Cluster
– Sentinel
– 実運用にむけた注意点
• ドキュメント読もう!
• ソースも読もう!!
まとめ

Redis速習会@Wantedly