Riding Redis @ask.fm

81
RIDING REDIS @

Transcript of Riding Redis @ask.fm

Page 1: Riding Redis @ask.fm

RIDING REDIS @

Page 2: Riding Redis @ask.fm

60M REGISTERED USERS

200M MONTHLY UNIQUE USERS

450M PAGEVIEWS A DAY

Page 3: Riding Redis @ask.fm

600 QUESTIONS / SECOND

20K REQUESTS / SECOND

50K LIKES / MINUTE

250K REGISTRATIONS / DAY

Page 4: Riding Redis @ask.fm

~600 SERVERS

~300 RUBY NODES

~50 JAVA NODES

~35 REDIS NODES

~90 MySQL NODES

Page 5: Riding Redis @ask.fm

COMPARISON

13B PAGEVIEWS 200M UNIQUE USERS 32M QUESTIONS ANSWERED

13B PAGEVIEWS* 300M UNIQUE USERS** 76.9M POSTS CREATED*

130B PAGEVIEWS*** N/A UNIQUE USERS 340M TWEETS CREATED***

_________________________________________________* http://www.tumblr.com/press** http://yahoo.tumblr.com/post/50902111638/tumblr-yahoo***http://en.wikipedia.org/wiki/Twitter

Page 6: Riding Redis @ask.fm

REDIS

Page 7: Riding Redis @ask.fm

Open-sourceKey-value databaseIn-memoryData-structure server

REDIS

Page 8: Riding Redis @ask.fm

Salvatore Sanfilippo@antirez

REDIS AUTHOR

Page 9: Riding Redis @ask.fm

TWITTERINSTAGRAMSTACK-OVERFLOWBLIZZARD

WHO IS USING REDIS?

Page 10: Riding Redis @ask.fm

6 SCENARIOS6 REDIS DATA-STRUCTURES

Page 11: Riding Redis @ask.fm

COUNTERS STRING

MESSAGES QUEUE LIST

USER ACTIVITY MATRIX HASH

FUNCTIONAL SWITCHES BIT OPERATIONS

THE WALL SORTED SET

REAL-TIME MONITORING PUB / SUB

Page 12: Riding Redis @ask.fm

Scenario 1 : Counters

Page 13: Riding Redis @ask.fm

GLOBAL COUNTERS

ACTIVE USERSQUESTIONS ASKED TODAY

LIKES TOTALLYREGISTRATIONS THIS MONTH

Page 14: Riding Redis @ask.fm

SELECT count(*) FROM users WHERE state='active';

NAIVE SOLUTION

Page 15: Riding Redis @ask.fm

REDIS STRING

MOST BASIC REDIS TYPEBINARY SAFEUP TO 512 MbOPERATIONS

INCR, DECR

Page 16: Riding Redis @ask.fm

@redis.incr "users/active/total"[email protected] "users/active/total"

users / active / total 61 771 480

users / inactive / total 6 943 366

EXAMPLE

Page 17: Riding Redis @ask.fm

USERS COUNTERS

Page 18: Riding Redis @ask.fm

@redis.incr "user/#{@user.id}/answers"[email protected] "user/#{@user.id}/likes"[email protected] "user/#{@user.id}/gifts"

user / :user_id/ answers 57

user / :user_id / likes 13 905

user / :user_id / gifts 27

EXAMPLE #2: USERS COUNTERS

Page 19: Riding Redis @ask.fm

COUNTERS CONSISTENCY

Page 20: Riding Redis @ask.fm

CONSISTENCY = 1 / PERFORMANCE

Page 21: Riding Redis @ask.fm

@redis.expire "user/#{@user.id}/inbox_questions", 1.day

SOLVED MOST CASES FOR US

REDIS TTL

Page 22: Riding Redis @ask.fm

SCALABILITY

Page 23: Riding Redis @ask.fm

@redis_shard_map = { 0 => Redis.new(:host=>"redis_host_0"), 1 => Redis.new(:host=>"redis_host_1"), ..., 7 => Redis.new(:host=>"redis_host_7")}

@redis = @redis_shard_map[@user.id % 8]@redis.incr "user/#{@user.id}/answers"

SCALABILITY (2)

Page 24: Riding Redis @ask.fm

Scenario 2 : Messages Queue

Page 25: Riding Redis @ask.fm

THIRD PARTY INTERACTION

Page 26: Riding Redis @ask.fm

RUBY BLOCKING MODEL

Page 27: Riding Redis @ask.fm

Resque to the rescue

https://github.com/resque/resque

Page 28: Riding Redis @ask.fm

REDIS-BACKED LIBRARY FOR● CREATING BACKGROUND JOBS

● PLACING THOSE JOBS ON MULTIPLE QUEUES● AND PROCESSING THEM LATER

RESQUE

Page 29: Riding Redis @ask.fm

REDIS LIST

SIMPLY LISTS OF STRINGSMAX LENGTH 232 - 1CONSTANT TIME INSERTIONOPERATIONS:

LPUSH, LPOP, RPUSH, RPOPLREM, LRANGE

Page 30: Riding Redis @ask.fm

WORKFLOW

Page 31: Riding Redis @ask.fm

Why Resque?

Page 32: Riding Redis @ask.fm

Resque.enqueue(PostToFacebookJob, "Hello world")

ADDING A NEW JOB

Page 33: Riding Redis @ask.fm

@redis.lpush 'queue:facebook', '{ "class":"PostToFacebookJob", "args":["Hello world"] }'

O(1)

COMPLEXITY

Page 34: Riding Redis @ask.fm

@redis.rpop "queue:facebook"O(1)

GETTING A JOB FROM QUEUE

Page 35: Riding Redis @ask.fm

Scenario 3 :User activity matrix

Page 36: Riding Redis @ask.fm

ROBOTSCRAWLERS

SPAM

TIME-BASED RESTRICTIONS

Page 37: Riding Redis @ask.fm

POSTASK A QUESTION

LOGINLIKE

GETPROFILE VIEW

USER ACTIONS

Page 38: Riding Redis @ask.fm

LIMIT ACTIVITYPER MINUTEPER HOURPER DAY

REQUIREMENTS

Page 39: Riding Redis @ask.fm
Page 40: Riding Redis @ask.fm

REDIS HASH

MAPS BETWEEN

STRING FIELDS AND VALUES

MAX PAIRS 232 - 1

OPERATIONS:HGET, HGETALLHSET, HDEL

Page 41: Riding Redis @ask.fm

LIKES QUESTIONS REQUESTS

user/:uid/date/:today/minute/:minute 12 3 27

user/:uid/date/:today/hour/:hour 34 15 113

user/:uid/date/:today/day/:day 158 22 529

STRUCTURE

Page 42: Riding Redis @ask.fm

def register_users_like!(user_id)minute = @redis.hincrby minute_key, 'like', 1hour = @redis.hincrby hour_key, 'like', 1day = @redis.hincrby day_key, 'like', 1

end

EXAMPLE: REGISTER ACTIVITY

Page 43: Riding Redis @ask.fm

def allowed_to_like_questions?(user_id)minute = @redis.hget minute_key, "likes"hour = @redis.hget hour_key, "likes"day = @redis.hget day_key, "likes"

return per_minute < LIKES_PER_MINUTE_THRESHOLD && per_hour < LIKES_PER_HOUR_THRESHOLD && per_day < LIKES_PER_DATE_THRESHOLD

end

EXAMPLE: ALLOWED?

Page 44: Riding Redis @ask.fm

@redis.expire per_minute_key, [email protected] per_hour_key, [email protected] per_day_key, 1.day

CLEANUP

Page 45: Riding Redis @ask.fm

SCALABILITY

SCALE BY USER_ID

DATEPHASE OF THE MOON

Page 46: Riding Redis @ask.fm

CONSISTENT HASHING

Page 47: Riding Redis @ask.fm

Scenario 4 :Functional switches

Page 48: Riding Redis @ask.fm

TURN ON/OFF ANY FEATURE ON SITE

REQUIREMENTS

Page 49: Riding Redis @ask.fm

PHOTO ANSWERSVIDEO ANSWERS

WALLSTREAM

DATABASE SHARDSSET POSTS PER PAGE

FUNCTIONALITY

Page 50: Riding Redis @ask.fm

BIT OPERATIONS

BIT OPERATIONSSETBIT, GETBITBITCOUNT

Page 51: Riding Redis @ask.fm

@redis.setbit common_settings_key, WALL_ENABLED, true

EXAMPLE

Page 52: Riding Redis @ask.fm

MASTER / SLAVE REPLICATION

SCALABILITY

Page 53: Riding Redis @ask.fm

Scenario 5 : The Wall

Page 54: Riding Redis @ask.fm

THE WALL

Page 55: Riding Redis @ask.fm

THE WALL

Page 56: Riding Redis @ask.fm

SHOW FRIENDS POSTS

INITIAL REQUIREMENT

Page 57: Riding Redis @ask.fm

SELECT * FROM questions q LEFT JOIN followships f ON (q.user_id = f.friend_id) WHERE f.user_id = :my_user_id ORDER BY q.answered_at LIMIT 0,25

SOLUTION

Page 58: Riding Redis @ask.fm

LATER REQUIREMENTS

LIKES INTRODUCEDSHOW RETWEETS

UNIQUENESS OF ANSWERSORDERED BY FIRST OCCURRENCE

PAGINATION NEEDEDDO NOT SHOW OWN POSTS

SHOW RETWEETS SINCE STARTED FOLLOWING A FRIENDS

Page 59: Riding Redis @ask.fm

MORE REQUIREMENTS

DO NOT SHOW RETWEETS IF ANSWERER OR RETWEETER IS DISABLED

SHOW LATEST FRIENDS WHO LIKED A QUESTION

Page 60: Riding Redis @ask.fm

OUR SOLUTION

Page 61: Riding Redis @ask.fm

IDEA

STORE SEPARATE SET OF QUESTIONS FOR EVERY USER

Page 62: Riding Redis @ask.fm

NON REPEATING COLLECTIONS OF STRINGS

EACH MEMBER ASSOCIATED WITH SCORE

QUICKLY ACCESSELEMENTS IN ORDERFAST EXISTENCE TESTFAST ACCESS TO ELEMENTS IN THE

MIDDLE

REDIS SORTED SET

Page 63: Riding Redis @ask.fm

user/:user_id/wallscore_1 score_2 ... score_N

question_id_1 question_id_2 ... question_id_N

score - timestamp, when the question_id first occurred in a set

STRUCTURE

Page 64: Riding Redis @ask.fm

● GET USERS WALL○ ZREVRANGEBYSCORE - O(log(N)+M)

● USER ANSWERED A QUESTION○ ZADD - O(log(N))

● LIKE○ ZRANK - O(log(N)) ○ ZADD - O(log(N))

● REMOVE ANSWER○ ZREM - O(M*log(N)

OPERATIONS

Page 65: Riding Redis @ask.fm

GUARANTEED 1000-1500 POSTS ON WALLPERIODICALLY CALL

ZCARDZREMRANGEBYRANK

CLEANUP

Page 66: Riding Redis @ask.fm

USER_ID

SHARDING

Page 67: Riding Redis @ask.fm

Scenario 6 :Real time monitoring

Page 68: Riding Redis @ask.fm

PATTERN DETECTION

REQUIREMENT

Page 69: Riding Redis @ask.fm

HUMAN vs MACHINE

Page 70: Riding Redis @ask.fm

MySQL TABLE PULL

INITIAL SOLUTION

Page 71: Riding Redis @ask.fm

PUBLISH / SUBSCRIBE MESSAGING PARADIGM

ALLOW PATTERN-MATCHING SUBSCRIPTIONS

OPERATIONS:SUBSCRIBE, UNSUBSCRIBEPUBLISH

REDIS PUB/SUB

Page 72: Riding Redis @ask.fm

SCHEMA

Page 73: Riding Redis @ask.fm

MODERATORS PANEL

Page 74: Riding Redis @ask.fm

Time complexity: O(N+M) where N is the number of clients subscribed to the receiving channel and M is the total number of subscribed patterns (by any client).

SCALING

Page 75: Riding Redis @ask.fm

So, why Redis?

Page 76: Riding Redis @ask.fm

SIMPLEFAST

FLEXIBLEROBUST

FREE

WHY REDIS?

Page 77: Riding Redis @ask.fm

CLUSTERING

WHAT'S MISSING

Page 78: Riding Redis @ask.fm

Not covered?

Page 79: Riding Redis @ask.fm

SETSLUA SCRIPTINGTRANSACTIONS

PIPELINED

NOT COVERED

Page 80: Riding Redis @ask.fm

JAVA

Page 81: Riding Redis @ask.fm

Questions