redis is the answer, what's the question - tech nottingham
TRANSCRIPT
Garry Shutler | @gshutler
Garry Shutler | @gshutler
@gshutler
What is it?
@gshutler
@gshutler
What is it good for?
@gshutler
The Redis protocol
Simple to implement
Fast to parse
Human readable
@gshutler
@gshutler
The Redis protocol
COMMAND KEY ARGS...
@gshutler
@gshutler
The Redis protocol
redis.command(key, *args)
@gshutler
@gshutler
The Redis protocol
SET mykey 3
@gshutler
@gshutler
The Redis protocol
redis.set("mykey", 3)
@gshutler
@gshutler
The Redis protocol
SET mykey 3 EX 3600
@gshutler
@gshutler
The Redis protocol
redis.set("mykey", 3, { "ex": 3600 })
@gshutler
@gshutler
Cache
@gshutler
Cachefunction cached(key, fn) { var value = redis.get(key); if (!value) { value = fn(); redis.set(key, value); } return value;}
@gshutler
Cachefunction expensiveThing() { return cached("expensive", function () { // do something that's expensive return expensiveValue; });}
@gshutler
Cache
expensiveThing(); // missexpensiveThing(); // hitexpensiveThing(); // hit
@gshutler
Cachefunction expensiveThing(param) { var key = "expensive:" + param; return cached(key, function () { sleep(param); return param; });}
@gshutler
Cache
expensiveThing(1); // missexpensiveThing(1); // hitexpensiveThing(2); // missexpensiveThing(2); // hitexpensiveThing(1); // hit
@gshutler
Cachefunction cached(key, expiry, fn) { var value = redis.get(key); if (value) { redis.expire(key, expiry); } else { value = fn(); redis.set(key, value, { "ex": expiry }); } return value;}
@gshutler
Cachefunction expensiveThing(param) { var key = "expensive:" + param; return cached(key, 3600, function () { sleep(param); return param; });}
@gshutler
or vs
Relative In 5 minutes
Absolute At 9am
@gshutler
Expiration
@gshutler
Expiration
my_report:last_hour
@gshutler
@gshutler
Expiration
my_report:2015051118
@gshutler
@gshutler
Data types
@gshutler
@gshutler
String
@gshutler
@gshutler
List
@gshutler
@gshutler
Set
@gshutler
@gshutler
Conditional GET
@gshutler
@gshutler
Conditional GETvar etagKey = "etag:" + url;
if (storedEtag = redis.get(etagKey)) { headers["If-None-Match"] = storedEtag;}
var response = http.get(url, headers);var etag = response.headers["ETag"];
redis.set(etagKey, etag, { "ex": 300 });
@gshutler
@gshutler
Touch values
@gshutler
@gshutler
Touch values
SET {KEY} 1 EX {TIME}
EXISTS {KEY}
@gshutler
@gshutler
Ephemeral lookups
@gshutler
@gshutler
Ephemeral lookups
Forgotten password IDs
OAuth access tokens
Voucher codes
@gshutler
@gshutler
Time-series counter
@gshutler
@gshutler
Time-series counter
INCR clicks:201505111830
@gshutler
@gshutler
Time-series counter
INCR clicks:201505111830INCR clicks:2015051118INCR clicks:20150511
@gshutler
@gshutler
Time-series counter
INCR clicks:201505111830EXPIRE clicks:201505111830 86400
INCR clicks:2015051118EXPIRE clicks:2015051118 2419200
INCR clicks:20150511
@gshutler
@gshutler
Time-series counter> MGET clicks:201505111826 clicks:201505111827 clicks:201505111828 clicks:201505111829 clicks:2015051118301)"5"2)(nil)3)"2"4)"10"5)"1"
@gshutler
@gshutler
Unique visitors
@gshutler
@gshutler
Unique visitors
SADD {KEY} {VALUE}
@gshutler
@gshutler
Unique visitors
SADD visitors:2015051118 1SADD visitors:2015051118 2SADD visitors:2015051118 2
@gshutler
@gshutler
Unique visitors
SCARD {KEY}
@gshutler
@gshutler
Unique visitors
SCARD visitors:2015051118
@gshutler
@gshutler
Queuing
@gshutler
@gshutler
Queuing
RPUSH {KEY} {VALUE}
@gshutler
@gshutler
Queuing
RPUSH queue 1RPUSH queue 2
@gshutler
@gshutler
Queuing
["1", "2"]
@gshutler
@gshutler
Queuing
LPOP {KEY}
@gshutler
@gshutler
Queuing
LPOP queue
@gshutler
@gshutler
Queuing
"1"
@gshutler
@gshutler
Queuing
["2"]
@gshutler
@gshutler
Queuing
LPUSH queue 3
@gshutler
@gshutler
Queuing
["3", "2"]
@gshutler
@gshutler
Queuing
@gshutler
RPUSH queue 4 RPUSH queue 5
queue
LPOP queue LPOP queue LPOP queue
@gshutler
Queuing
BLPOP {KEY}... {TIMEOUT}
@gshutler
@gshutler
Queuing
Encoded values
Reply queues
@gshutler
@gshutler
Have a go
@gshutler
@gshutler
Have a go
Cached Fibonacci
Distributed processing
@gshutler
Garry Shutler | @gshutler