Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Redis Hacks
Search
David Cramer
May 03, 2014
Technology
3
220
Redis Hacks
Python Nordeste 2014 - Lightning Talk
David Cramer
May 03, 2014
Tweet
Share
More Decks by David Cramer
See All by David Cramer
Mastering Duct Tape (PyCon Balkan 2018)
zeeg
2
870
Open Source as a Business (PyCon SG 2014)
zeeg
0
350
Angular.js Workshop (PyCon SG 2014)
zeeg
0
230
Architecting a Culture of Quality
zeeg
2
320
Release Faster
zeeg
12
1.4k
Open Source as a Business (EuroPython 2013)
zeeg
18
17k
Building to Scale (PyCon TW 2013)
zeeg
18
1.3k
Building to Scale
zeeg
28
24k
Lessons in Testing - DjangoCon 2012
zeeg
8
1.4k
Other Decks in Technology
See All in Technology
Beyond {shiny}: The Future of Mobile Apps with R
colinfay
1
350
AIエージェントの地上戦 〜開発計画と運用実践 / 2025/04/08 Findy W&Bミートアップ #19
smiyawaki0820
25
8.4k
改めて学ぶ Trait の使い方 / phpcon odawara 2025
meihei3
1
560
Lightdashの利活用状況 ー導入から2年経った現在地_20250409
hirokiigeta
2
270
Devinで模索する AIファースト開発〜ゼロベースから始めるDevOpsの進化〜
potix2
PRO
6
2.6k
アジャイル脅威モデリング#1(脅威モデリングナイト#8)
masakane55
3
150
DuckDB MCPサーバーを使ってAWSコストを分析させてみた / AWS cost analysis with DuckDB MCP server
masahirokawahara
0
460
“パスワードレス認証への道" ユーザー認証の変遷とパスキーの関係
ritou
1
350
【2025年度新卒技術研修】100分で学ぶ サイバーエージェントのデータベース 活用事例とMySQLパフォーマンス調査
cyberagentdevelopers
PRO
4
6.2k
近年の PyCon 情勢から見た PyCon APAC のまとめ
terapyon
0
280
30 代子育て SRE が考える SRE ナレッジマネジメントの現在と将来
kworkdev
PRO
0
200
10分でわかるfreeeのQA
freee
1
12k
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
37
1.7k
Documentation Writing (for coders)
carmenintech
69
4.7k
Why Our Code Smells
bkeepers
PRO
336
57k
Fireside Chat
paigeccino
37
3.4k
YesSQL, Process and Tooling at Scale
rocio
172
14k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
32
5.1k
Being A Developer After 40
akosma
91
590k
How to Ace a Technical Interview
jacobian
276
23k
How GitHub (no longer) Works
holman
314
140k
GraphQLとの向き合い方2022年版
quramy
46
14k
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Designing Experiences People Love
moore
141
24k
Transcript
David Cramer twitter.com/zeeg Redis Hacks (or “How Sentry Scales”)
Buffering Writes
r = Redis() ! def incr(type, id): key = 'pending:{}'.format(type)
! r.zincrby(key, id, 1)
r = Redis() ! def flush(type): key = 'pending:{}'.format(type) result
= r.zrange(key, 0, -1, withscores=True) ! for id, count in result: prms = {'type': type, 'count': count, 'id': id} ! sql(""" update %(type)s set count = count + % (count)d where id = %(id)s """, prms)
Rate Limiting
r = Redis() ! def process_hit(project_id): epoch = time() /
60 key = ‘{}:{}’.format(project_id, epoch) ! pipe = r.pipeline() pipe.incr(key) pipe.expire(key, 60) result = pipe.execute() ! # return current value return int(result[0])
def request(project_id): result = process_hit(project_id) if result > 20: return
Response(status=429) return Response(status=200)
Time Series Data
def count_hits_today(project_id): start = time() end = now + DAY_SECONDS
! pipe = r.pipeline() for epoch in xrange(now, end, 10): key = ‘{}:{}’.format( project_id, epoch) pipe.get(key) results = pipe.execute() ! # remove non-zero results results = filter(bool, results) # coerce remainder to ints results = map(int, results) # return sum of buckets return sum(results)
Good-enough Locks
from contextlib import contextmanager ! r = Redis() ! @contextmanager
def lock(key, nowait=True): while not r.setnx(key, '1'): if nowait: raise Locked('try again soon!') sleep(0.01) ! # limit lock time to 10 seconds r.expire(key, 10) ! # do something crazy yield ! # explicitly unlock r.delete(key)
def do_something_crazy(): with lock('crazy'): print 'Hello World!'
Basic Sharding via Nydus
from nydus.db import create_cluster ! redis = create_cluster({ 'backend': 'nydus.db.backends.redis.Redis',
'hosts': { 0: {'db': 0}, 1: {'db': 1}, }, 'router': 'nydus.db.routers.keyvalue.PartitionRouter', })
def count_hits_today(project_id): start = time() end = now + DAY_SECONDS
! keys = [] for epoch in xrange(now, end, 10): key = '{}:{}'.format(project_id, epoch) keys.append(key) ! with redis.map() as conn: results = map(conn.get, keys) ! # remove non-zero results results = filter(bool, results) # coerce remainder to ints results = map(int, results) # return sum of buckets return sum(results)