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
210
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
860
Open Source as a Business (PyCon SG 2014)
zeeg
0
310
Angular.js Workshop (PyCon SG 2014)
zeeg
0
220
Architecting a Culture of Quality
zeeg
2
310
Release Faster
zeeg
12
1.3k
Open Source as a Business (EuroPython 2013)
zeeg
18
17k
Building to Scale (PyCon TW 2013)
zeeg
18
1.2k
Building to Scale
zeeg
28
24k
Lessons in Testing - DjangoCon 2012
zeeg
8
1.4k
Other Decks in Technology
See All in Technology
RAGの性能を評価しよう
kurahara
1
270
GitHub Actions/Docker/Terraform/Renovate で最小限の Monorepo CD パイプラインを作る / Minimalistic Monorepo CD Pipeline with GitHub Actions, Docker, Terraform and Renovate
yuyatakeyama
4
340
Pythonを活用したLLMによる構造的データ生成の手法と実践
brainpadpr
2
210
エンジニアは伝え方が9割/90% of what engineers need is communication skills
ykanoh
2
140
How CERN serves 1EB of data via FUSE
ennael
PRO
0
15k
REST API Design Pitfalls
victorrentea
1
500
【swonet.conf_】NOCメンバーが語るSTMの実態!! ~ShowNetから若者への贈り物~
shownet
PRO
0
220
OPENLOGI Company Profile for engineer
hr01
1
12k
XPを始める新人に伝えたい近道の鍵
nakasho
1
220
Valuable Software Engineering
avandeursen
0
250
MLOpsの「あるある」課題の解決と、そのためのライブラリgokart
mski_iksm
1
150
【shownet.conf_】コンピューティング資源を統合した分散コンテナ基盤の進化
shownet
PRO
0
290
Featured
See All Featured
We Have a Design System, Now What?
morganepeng
49
7.1k
GraphQLとの向き合い方2022年版
quramy
43
13k
Reflections from 52 weeks, 52 projects
jeffersonlam
346
20k
Agile that works and the tools we love
rasmusluckow
327
21k
Bash Introduction
62gerente
608
210k
[RailsConf 2023] Rails as a piece of cake
palkan
49
4.7k
Why You Should Never Use an ORM
jnunemaker
PRO
53
9k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
26
2k
YesSQL, Process and Tooling at Scale
rocio
167
14k
What the flash - Photography Introduction
edds
67
11k
A designer walks into a library…
pauljervisheath
201
24k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
7.5k
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)