21
"Little Server of Awesome" 2011 Dvir Volk Software Architect, DoAT [email protected] http://doat.com

Introduction to redis - version 2

Embed Size (px)

DESCRIPTION

This is a revised and shorter version of my old "introduction to redis" lecture

Citation preview

Page 1: Introduction to redis - version 2

"Little Server of Awesome"

2011 Dvir Volk

Software Architect, DoAT [email protected] http://doat.com

Page 2: Introduction to redis - version 2

Redis: Key => DataStructure Server

● Memcache-ish in-memory key/value store● But values are complex data types:

○ blobs○ lists○ sets○ sorted sets○ hash tables

● And it has persistence.● Open source; very helpful and friendly community.● Used in the real world: github, craigslist, bit.ly, engineyard...● Used heavily in doAT as a front-end database, search, geo

resolving

Page 3: Introduction to redis - version 2

Key Features and Cool Stuff● All data is in memory (almost)

● All data is eventually persistent

● Handles huge workloads easily

● Mostly O(1) behavior, Ideal for write-heavy workloads

● Support for atomic operations, transactions

● Has pub/sub functionality

● Single threaded, uses aync. IO● Internal scripting with LUA in alpha

Page 4: Introduction to redis - version 2

A little benchmark

This is on my laptop (core i7 @2.2Ghz)

● SET: 187265.92 requests per second● GET: 185185.17 requests per second● INCR: 190114.06 requests per second

● LPUSH: 190114.06 requests per second● LPOP: 187090.73 requests per second● ● SADD: 186567.16 requests per second● SPOP: 185873.61 requests per second

Page 5: Introduction to redis - version 2

Scaling it up

● Master-slave replication out of the box

● Slaves can be made masters on the fly

● Redis-cluster in alpha state.

● Sharding supported by some clients

● Single threaded - run num_cores/2 instances on the same machine

Page 6: Introduction to redis - version 2

Persistence● All data is synchronized to disk - eventually or immediately

● Pick your risk level Vs. performance

● Data is either dumped in a forked process, or written as a append-only change-log (AOF)

● Append-only mode supports transactional disk writes so you can lose no data (cost: 99% speed loss :) )

● You can save the state explicitly, background or blocking

● If the data is too big to fit in memory - redis can handle its own swap.

Page 7: Introduction to redis - version 2

Show me the features!

Page 8: Introduction to redis - version 2

The basics...Get/Sets - nothing fancy. Keys are strings, anything goes - just quote spaces.redis> SET foo "bar"OKredis> GET foo"bar"

You can atomically increment numbersredis> SET bar 337OKredis> INCRBY bar 1000(integer) 1337

Getting multiple values at onceredis> MGET foo bar1. "bar"2. "1337"

Keys are lazily expiredredis> EXPIRE foo 1(integer) 1redis> GET foo(nil)Be careful with EXPIRE - re-setting a value without re-expiring it will remove the expiration!

Page 9: Introduction to redis - version 2

Atomic OperationsGETSET puts a different value inside a key, retriving the old oneredis> SET foo barOKredis> GETSET foo baz"bar"redis> GET foo"baz"

SETNX sets a value only if it does not existredis> SETNX foo bar*OK*redis> SETNX foo baz*FAILS*

Page 10: Introduction to redis - version 2

List operations● Lists are your ordinary linked lists. ● You can push and pop at both sides, extract range, resize..● Random access and ranges at O(N)● BLPOP: Blocking POP - wait until a list has elements and pop

them. Useful for realtime stuff.

Page 11: Introduction to redis - version 2

Set operations● Sets are... well, sets of unique values w/ push, pop, etc.● Sets can be intersected/diffed /union'ed server side.● Can be useful as keys when building complex schemata.

Page 12: Introduction to redis - version 2

Sorted Sets● Same as sets, but with score per element● Ranked ranges, aggregation of scores on INTERSECT● Can be used as ordered keys in complex schemata● Think timestamps, inverted index, geohashing, ip ranges

Page 13: Introduction to redis - version 2

Hashes● Hash tables as values● Think of an object store with atomic access to object

members

redis> HSET foo bar 1(integer) 1redis> HSET foo baz 2(integer) 1redis> HSET foo foo foo(integer) 1

redis> HGETALL foo{ "bar": "1", "baz": "2", "foo": "foo"}

redis> HINCRBY foo bar 1(integer) 2

redis> HGET foo bar"2"

redis> HKEYS foo1. "bar"2. "baz"3. "foo"

Page 14: Introduction to redis - version 2

PubSub - Publish/Subscribe● Clients can subscribe to channels or patterns and receive

notifications when messages are sent to channels.● Subscribing is O(1), posting messages is O(n)● Think chats, Comet applications: real-time analytics, twitter

Page 15: Introduction to redis - version 2

Transactions● MULTI, ...., EXEC: Easy because of the single thread.● All commands are executed after EXEC, block and return

values for the commands as a list.● Example:

redis> MULTIOKredis> SET "foo" "bar"QUEUEDredis> INCRBY "num" 1QUEUEDredis> EXEC1) OK2) (integer) 1

● Transactions can be discarded with DISCARD.

● WATCH allows you to lock keys while you are queuing your transaction, and avoid race conditions.

Page 16: Introduction to redis - version 2

Gotchas, Lessons Learned● 64 bit instances consume much much more RAM.

● Master/Slave sync far from perfect.

● DO NOT USE THE KEYS COMMAND!!!

● vm.overcommit_memory = 1

● Use MONITOR to see what's going on

Page 17: Introduction to redis - version 2

Recipe 1: Social Feed● Each User's followers are list: user:$ID:followers => { 1, 2, 4 }

● Each User's feed is a sorted set with the time-stamp being the score: user:$ID:feed => { msg1234: 124950132, ... }

● Each message is either a blob or a HASH object with fields: msg1234 => {title, text, ... }

● When a message is added, we:○ add the message○ read the posting user's follower list○ add the message id to each follower's feed

● When a user reads their feeds, we use ZREVRANGE to get the latest item ids, and HGETALL to fetch the message texts.

● For bonus points, connected users can receive push notifications with PubSub

Page 18: Introduction to redis - version 2

Recipe 2: Real-Time Analytics● We want to measure page views, per page, one minute resolution,

in real time.● Each page is represented by a sorted set, where the value is the

minute, and the score is the number of hits.

● On each page hit, we do ZINCRBY <page> <current_minute> 1

● Page views for the last N minutes: ZREVRANGE <page> 0 N

● Group several pages together: ZUNIONSTORE ... AGGREGATE SUM

● Trimming for a specific window: ZREMRANGEBYRANK

● Again, PubSub can be used to push updates to clients

Page 19: Introduction to redis - version 2

Recipe 3: Processing Queue● Each task can be a blob describing it with json, using

SET/GET/DEL.

● We keep a list of pending tasks, or multiple lists per task type/priority ("tasks:urgent")

● Worker procs can work from any machine over the network.

● Workers poll task queues using BRPOP tasks:urgent● atomicity guaranteed!

● When a task is pulled it can be marked on a different list/set of "tasks:inprogress". When a task is done it is moved to a "done" or "failed" task list.

● A manager can monitor failed tasks and move them around.

Page 20: Introduction to redis - version 2

Other use case ideas● Geo Resolving with geohashing● Implemented and opened by yours truly https://github.com/doat/geodis

● API Key and rate management● Very fast key lookup, rate control counters using INCR

● Real time game data● ZSETs for high scores, HASHES for online users, etc

● Database Shard Index● map key => database id. Count size with SETS

● Comet - no polling ajax● use BLPOP or pub/sub

● Machine learning data with automatic persistence.● sorted sets are your vectors!

Page 21: Introduction to redis - version 2

More resources

Redis' website:http://redis.io

Excellent and more detailed presentation by Simon Willison (a bit old):http://simonwillison.net/static/2010/redis-tutorial/

Much more complex twitter clone:http://code.google.com/p/redis/wiki/TwitterAlikeExample

Full command reference:http://redis.io/commands