SlideShare ist ein Scribd-Unternehmen logo
1 von 34
Downloaden Sie, um offline zu lesen
Advanced Redis
data structures
by Amir Salihefendic
About me
Founder
Millions of data items
Co-founder, former CTO
Billions of data items
Redis: Greatness
Everything is in memory, data is persistent
Amazing Performance
The Hacker’s database
Redis: Greatness
Great lead dev
Amazing progress (Sentinel, Cluster, …)
Redis Rich Datatypes
• Relational databases

Schemas, tables, columns, rows, indexes etc.

• Column databases (BigTable, hBase etc.)

Schemas, columns, column families, rows etc.

• Redis

key-value, sets, lists, hashes, bitmaps, etc.
Redis datatypes resemble datatypes
in programming languages.
They are natural to us!
redis_wrap
A wrapper for Redis datatypes, so
they mimic the datatypes found in
Python
https://github.com/Doist/redis_wrap
# Mimic of Python lists
bears = get_list('bears')
bears.append('grizzly')
assert len(bears) == 1
assert 'grizzly' in bears
# Mimic of hashes
villains = get_hash('villains')
assert 'riddler' not in villains
villains['riddler'] = 'Edward Nigma'
assert 'riddler' in villains
assert len(villains.keys()) == 1
del villains['riddler']
assert len(villains) == 0
# Mimic of Python sets
fishes = get_set('fishes')
assert 'nemo' not in fishes
fishes.add('nemo')
assert 'nemo' in fishes
for item in fishes:
assert item == 'nemo'
redis_wrap: usage
redis_graph
A simple graph database in Python
https://github.com/Doist/redis_graph
# Adding an edge between nodes
add_edge(from_node='frodo', to_node='gandalf')
assert has_edge(from_node='frodo',
to_node='gandalf') == True
# Getting neighbors of a node
assert list(neighbors('frodo')) == ['gandalf']
# Deleting edges
delete_edge(from_node='frodo', to_node='gandalf')
# Setting node values
set_node_value('frodo', '1')
assert get_node_value('frodo') == '1'
# Setting edge values
set_edge_value('frodo_baggins', '2')
assert get_edge_value('frodo_baggins') == '2'
redis_graph: Usage
redis_graph: Implementation
from redis_wrap import *
#--- Edges ----------------------------------------------
def add_edge(from_node, to_node, system='default'):
edges = get_set( from_node, system=system )
edges.add( to_node )
def delete_edge(from_node, to_node, system='default'):
edges = get_set( from_node, system=system )
key_node_y = to_node
if key_node_y in edges:
edges.remove( key_node_y )
def has_edge(from_node, to_node, system='default'):
edges = get_set( from_node, system=system )
return to_node in edges
def neighbors(node_x, system='default'):
return get_set( node_x, system=system )
#--- Node values ----------------------------
def get_node_value(node_x, system='default'):
node_key = 'nv:%s' % node_x
return get_redis(system).get( node_key )
def set_node_value(node_x, value, system='default'):
node_key = 'nv:%s' % node_x
return get_redis(system).set( node_key, value )
#--- Edge values -----------------------------
def get_edge_value(edge_x, system='default'):
edge_key = 'ev:%s' % edge_x
return get_redis(system).get( edge_key )
def set_edge_value(edge_x, value, system='default'):
edge_key = 'ev:%s' % edge_x
return get_redis(system).set( edge_key, value )
redis_simple_queue
A simple queue in Python using Redis
https://github.com/Doist/redis_simple_queue
redis_queue: usage
from redis_simple_queue import *
delete_jobs('tasks')
put_job('tasks', '42')
assert 'tasks' in get_all_queues()
assert queue_stats('tasks')['queue_size'] == 1
assert reserve_job('tasks') == '42'
assert queue_stats('tasks')['queue_size'] == 0
redis_queue: Implementation
from redis_wrap import *
def put(queue, job_data, system='default'):
get_list(queue, system=system).append(job_data)
def reserve(queue, system='default'):
return get_list(queue, system=system).pop()
def delete_jobs(queue, system='default'):
get_redis(system).delete(queue)
def get_all_queues(system='default'):
return get_redis(system).keys('*').split(' ')
def queue_stats(queue, system='default'):
return {
'queue_size': len(get_list(queue))
}
Cohort/Retention
Tracking
How bitmapist was born
bitmapist: The idea
MixPanel looks great!
bitmapist: Problem with MixPanel
MixPanel would cost
$2000/USD++/month
bitmapist + bitmapist.cohort
• Implements an advanced analytics library
on top of Redis bitmaps

• https://github.com/Doist/bitmapist
• Hundreds of millions of events for Todoist
• O(1) execution
bitmapist: Features
•Has user 123 been online today? This week?
•Has user 123 performed action "X"?
•How many users have been active have this month?
•How many unique users have performed action "X"
this week?
•How many % of users that were active last week are
still active?
•How many % of users that were active last month
are still active this month?
•O(1)! Using very small amounts of memory.
bitmapist: Bitmaps?
• SETBIT, GETBIT, BITCOUNT, BITOP 

• SETBIT somekey 8 1
• GETBIT somekey 8
• BITOP AND destkey somekey1 somekey2
• http://en.wikipedia.org/wiki/Bit_array
bitmapist: Usage
# Mark user 123 as active and has played a song
mark_event('active', 123)
mark_event('song:played', 123)
# Answer if user 123 has been active this month
assert 123 in MonthEvents('active', now.year, now.month)
assert 123 in MonthEvents('song:played', now.year, now.month)
# How many users have been active this week?
print len(WeekEvents('active', now.year, now.isocalendar()[1]))
# Perform bit operations. How many users that
# have been active last month are still active this month?
active_2_months = BitOpAnd(
MonthEvents('active', last_month.year, last_month.month),
MonthEvents('active', now.year, now.month)
)
print len(active_2_months)
bitmapist.cohort: Visualization
Read more
http://amix.dk/blog/post/19718
fixedlist
How fixedlist was born
fixedlist: Problem
Timelines: Exponential data growth
fixedlist: The Easy Solution
Throw money at the problem
fixedlist: Cheating!
• Fixed timeline size
• O(1) insertion
• O(1) update
• O(1) get
• Cacheable
Solution that Facebook and Twitter use
fixedlist
2.5x faster than pure Redis solution
1.4x less memory than pure Redis solution
https://github.com/Doist/fixedlist
fixedlist: Usage
# Add a value to a list
fixedlist.add('hello', 'world')
# Add mutliple values to multiple keys at once
fixedlist.add(['hello1', 'hello2'], ['world1', 'world2'])
# Get valuesfrom a list
assert fixedlist.get('hello') == ['world', 'world1', 'world2']
# Remove a value
fixedlist.remove('hello', 'world1')
Saved Plurk tens of thousands of $
Redis+Lua+Python
When you want:
More complex data types
Better performance
Redis+Python: Incr implementation
def incr_python(key, delta=1, system='default'):
client, scripts = get_redis(system)
with client.pipeline() as p:
p.watch(key)
value = delta
old = p.get(key)
if old:
value = int(old) + delta
p.set(key, value)
p.unwatch()
return value
Redis+Lua: Incr implementation
scripts = {
'incr': client.register_script(_load_lua_script('incr.lua'))
}
...
def incr_lua(key, delta=1, system='default'):
client, scripts = get_redis(system)
return scripts['incr'](keys=['key', 'delta'], args=[key, delta])
local delta = tonumber(ARGV[2])
local value = delta
local old = tonumber(redis.call('get', ARGV[1]))
if old then
value = value + old
end
if not redis.call('set', ARGV[1], value) then
return nil
end
return value
Perfomance: Lua 3x faster
Python
time python test_incr_python.py 300000
python test_incr_python.py 300000 37.77s user 12.00s
system 73% cpu 1:07.73 total
Lua
time python test_incr_lua.py 300000
python test_incr_lua.py 300000 10.76s user 2.85s
system 66% cpu 20.513 total
https://github.com/amix/demo-redis-python-lua
fixedlist in Lua
Proof of concept
Tokyo Tyrant example
https://gist.github.com/amix/f15508ac6a8b534c3290
Q & A
More questions:
amix@doist.io
@amix3k

Weitere ähnliche Inhalte

Was ist angesagt?

Redis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational DatabasesRedis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational Databases
Karel Minarik
 
ETL With Cassandra Streaming Bulk Loading
ETL With Cassandra Streaming Bulk LoadingETL With Cassandra Streaming Bulk Loading
ETL With Cassandra Streaming Bulk Loading
alex_araujo
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
Alex Bilbie
 

Was ist angesagt? (20)

Redis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational DatabasesRedis — The AK-47 of Post-relational Databases
Redis — The AK-47 of Post-relational Databases
 
An Introduction to REDIS NoSQL database
An Introduction to REDIS NoSQL databaseAn Introduction to REDIS NoSQL database
An Introduction to REDIS NoSQL database
 
Redis SoCraTes 2014
Redis SoCraTes 2014Redis SoCraTes 2014
Redis SoCraTes 2014
 
Redis Functions, Data Structures for Web Scale Apps
Redis Functions, Data Structures for Web Scale AppsRedis Functions, Data Structures for Web Scale Apps
Redis Functions, Data Structures for Web Scale Apps
 
Redis/Lessons learned
Redis/Lessons learnedRedis/Lessons learned
Redis/Lessons learned
 
ETL With Cassandra Streaming Bulk Loading
ETL With Cassandra Streaming Bulk LoadingETL With Cassandra Streaming Bulk Loading
ETL With Cassandra Streaming Bulk Loading
 
Getting Started with MongoDB
Getting Started with MongoDBGetting Started with MongoDB
Getting Started with MongoDB
 
Indexing
IndexingIndexing
Indexing
 
memcached Distributed Cache
memcached Distributed Cachememcached Distributed Cache
memcached Distributed Cache
 
Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015Cassandra 3.0 - JSON at scale - StampedeCon 2015
Cassandra 3.0 - JSON at scale - StampedeCon 2015
 
Bulk Loading Data into Cassandra
Bulk Loading Data into CassandraBulk Loading Data into Cassandra
Bulk Loading Data into Cassandra
 
MongoDB-SESSION03
MongoDB-SESSION03MongoDB-SESSION03
MongoDB-SESSION03
 
Cassandra Summit 2014: Reading Cassandra SSTables Directly for Offline Data A...
Cassandra Summit 2014: Reading Cassandra SSTables Directly for Offline Data A...Cassandra Summit 2014: Reading Cassandra SSTables Directly for Offline Data A...
Cassandra Summit 2014: Reading Cassandra SSTables Directly for Offline Data A...
 
Everything you always wanted to know about Redis but were afraid to ask
Everything you always wanted to know about Redis but were afraid to askEverything you always wanted to know about Redis but were afraid to ask
Everything you always wanted to know about Redis but were afraid to ask
 
Choosing a Shard key
Choosing a Shard keyChoosing a Shard key
Choosing a Shard key
 
Redis introduction
Redis introductionRedis introduction
Redis introduction
 
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
Webinaire 2 de la série « Retour aux fondamentaux » : Votre première applicat...
 
Cassandra Community Webinar | Become a Super Modeler
Cassandra Community Webinar | Become a Super ModelerCassandra Community Webinar | Become a Super Modeler
Cassandra Community Webinar | Become a Super Modeler
 
Introduction to Redis
Introduction to RedisIntroduction to Redis
Introduction to Redis
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 

Andere mochten auch

MongoDB Tick Data Presentation
MongoDB Tick Data PresentationMongoDB Tick Data Presentation
MongoDB Tick Data Presentation
MongoDB
 
Linux 4.x Tracing Tools: Using BPF Superpowers
Linux 4.x Tracing Tools: Using BPF SuperpowersLinux 4.x Tracing Tools: Using BPF Superpowers
Linux 4.x Tracing Tools: Using BPF Superpowers
Brendan Gregg
 
Découverte de Redis
Découverte de RedisDécouverte de Redis
Découverte de Redis
JEMLI Fathi
 
Les modèles NoSQL
Les modèles NoSQLLes modèles NoSQL
Les modèles NoSQL
ebiznext
 

Andere mochten auch (15)

Austin Bingham. Transducers in Python. PyCon Belarus
Austin Bingham. Transducers in Python. PyCon BelarusAustin Bingham. Transducers in Python. PyCon Belarus
Austin Bingham. Transducers in Python. PyCon Belarus
 
المكتبة الزيتونية سمير باني
المكتبة الزيتونية سمير بانيالمكتبة الزيتونية سمير باني
المكتبة الزيتونية سمير باني
 
Using MongoDB As a Tick Database
Using MongoDB As a Tick DatabaseUsing MongoDB As a Tick Database
Using MongoDB As a Tick Database
 
MongoDB Tick Data Presentation
MongoDB Tick Data PresentationMongoDB Tick Data Presentation
MongoDB Tick Data Presentation
 
Introduction aux bases de données NoSQL
Introduction aux bases de données NoSQLIntroduction aux bases de données NoSQL
Introduction aux bases de données NoSQL
 
HTML5, Spring, NoSQL et mobilité
HTML5, Spring, NoSQL et mobilitéHTML5, Spring, NoSQL et mobilité
HTML5, Spring, NoSQL et mobilité
 
Linux 4.x Tracing Tools: Using BPF Superpowers
Linux 4.x Tracing Tools: Using BPF SuperpowersLinux 4.x Tracing Tools: Using BPF Superpowers
Linux 4.x Tracing Tools: Using BPF Superpowers
 
BigData_Chp4: NOSQL
BigData_Chp4: NOSQLBigData_Chp4: NOSQL
BigData_Chp4: NOSQL
 
Les BD NoSQL
Les BD NoSQLLes BD NoSQL
Les BD NoSQL
 
Découverte de Redis
Découverte de RedisDécouverte de Redis
Découverte de Redis
 
Les modèles NoSQL
Les modèles NoSQLLes modèles NoSQL
Les modèles NoSQL
 
introduction à MongoDB
introduction à MongoDBintroduction à MongoDB
introduction à MongoDB
 
REX Storm Redis
REX Storm RedisREX Storm Redis
REX Storm Redis
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework spring
 
Technologies pour le Big Data
Technologies pour le Big DataTechnologies pour le Big Data
Technologies pour le Big Data
 

Ähnlich wie Advanced Redis data structures

Migrating from matlab to python
Migrating from matlab to pythonMigrating from matlab to python
Migrating from matlab to python
ActiveState
 
Mongo and Harmony
Mongo and HarmonyMongo and Harmony
Mongo and Harmony
Steve Smith
 
Redis深入浅出
Redis深入浅出Redis深入浅出
Redis深入浅出
锐 张
 

Ähnlich wie Advanced Redis data structures (20)

Amir Salihefendic: Redis - the hacker's database
Amir Salihefendic: Redis - the hacker's databaseAmir Salihefendic: Redis - the hacker's database
Amir Salihefendic: Redis - the hacker's database
 
Redispresentation apac2012
Redispresentation apac2012Redispresentation apac2012
Redispresentation apac2012
 
Performing Data Science with HBase
Performing Data Science with HBasePerforming Data Science with HBase
Performing Data Science with HBase
 
Dynamo DB & RDS Deep Dive - AWS India Summit 2012
Dynamo DB & RDS Deep Dive - AWS India Summit 2012Dynamo DB & RDS Deep Dive - AWS India Summit 2012
Dynamo DB & RDS Deep Dive - AWS India Summit 2012
 
An Introduction to gensim: "Topic Modelling for Humans"
An Introduction to gensim: "Topic Modelling for Humans"An Introduction to gensim: "Topic Modelling for Humans"
An Introduction to gensim: "Topic Modelling for Humans"
 
6° Sessione - Ambiti applicativi nella ricerca di tecnologie statistiche avan...
6° Sessione - Ambiti applicativi nella ricerca di tecnologie statistiche avan...6° Sessione - Ambiti applicativi nella ricerca di tecnologie statistiche avan...
6° Sessione - Ambiti applicativi nella ricerca di tecnologie statistiche avan...
 
Hands on Mahout!
Hands on Mahout!Hands on Mahout!
Hands on Mahout!
 
Migrating from matlab to python
Migrating from matlab to pythonMigrating from matlab to python
Migrating from matlab to python
 
Indexing thousands of writes per second with redis
Indexing thousands of writes per second with redisIndexing thousands of writes per second with redis
Indexing thousands of writes per second with redis
 
R programming & Machine Learning
R programming & Machine LearningR programming & Machine Learning
R programming & Machine Learning
 
Mongo and Harmony
Mongo and HarmonyMongo and Harmony
Mongo and Harmony
 
Redis
RedisRedis
Redis
 
Introduction Mysql
Introduction Mysql Introduction Mysql
Introduction Mysql
 
Mysql introduction
Mysql introduction Mysql introduction
Mysql introduction
 
Redis深入浅出
Redis深入浅出Redis深入浅出
Redis深入浅出
 
CuRious about R in Power BI? End to end R in Power BI for beginners
CuRious about R in Power BI? End to end R in Power BI for beginners CuRious about R in Power BI? End to end R in Power BI for beginners
CuRious about R in Power BI? End to end R in Power BI for beginners
 
What the C?
What the C?What the C?
What the C?
 
DjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling DisqusDjangoCon 2010 Scaling Disqus
DjangoCon 2010 Scaling Disqus
 
Protect Your Payloads: Modern Keying Techniques
Protect Your Payloads: Modern Keying TechniquesProtect Your Payloads: Modern Keying Techniques
Protect Your Payloads: Modern Keying Techniques
 
17641.ppt
17641.ppt17641.ppt
17641.ppt
 

Kürzlich hochgeladen

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Kürzlich hochgeladen (20)

Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 

Advanced Redis data structures

  • 2. About me Founder Millions of data items Co-founder, former CTO Billions of data items
  • 3. Redis: Greatness Everything is in memory, data is persistent Amazing Performance The Hacker’s database
  • 4. Redis: Greatness Great lead dev Amazing progress (Sentinel, Cluster, …)
  • 5. Redis Rich Datatypes • Relational databases
 Schemas, tables, columns, rows, indexes etc.
 • Column databases (BigTable, hBase etc.)
 Schemas, columns, column families, rows etc.
 • Redis
 key-value, sets, lists, hashes, bitmaps, etc.
  • 6. Redis datatypes resemble datatypes in programming languages. They are natural to us!
  • 7. redis_wrap A wrapper for Redis datatypes, so they mimic the datatypes found in Python https://github.com/Doist/redis_wrap
  • 8. # Mimic of Python lists bears = get_list('bears') bears.append('grizzly') assert len(bears) == 1 assert 'grizzly' in bears # Mimic of hashes villains = get_hash('villains') assert 'riddler' not in villains villains['riddler'] = 'Edward Nigma' assert 'riddler' in villains assert len(villains.keys()) == 1 del villains['riddler'] assert len(villains) == 0 # Mimic of Python sets fishes = get_set('fishes') assert 'nemo' not in fishes fishes.add('nemo') assert 'nemo' in fishes for item in fishes: assert item == 'nemo' redis_wrap: usage
  • 9. redis_graph A simple graph database in Python https://github.com/Doist/redis_graph
  • 10. # Adding an edge between nodes add_edge(from_node='frodo', to_node='gandalf') assert has_edge(from_node='frodo', to_node='gandalf') == True # Getting neighbors of a node assert list(neighbors('frodo')) == ['gandalf'] # Deleting edges delete_edge(from_node='frodo', to_node='gandalf') # Setting node values set_node_value('frodo', '1') assert get_node_value('frodo') == '1' # Setting edge values set_edge_value('frodo_baggins', '2') assert get_edge_value('frodo_baggins') == '2' redis_graph: Usage
  • 11. redis_graph: Implementation from redis_wrap import * #--- Edges ---------------------------------------------- def add_edge(from_node, to_node, system='default'): edges = get_set( from_node, system=system ) edges.add( to_node ) def delete_edge(from_node, to_node, system='default'): edges = get_set( from_node, system=system ) key_node_y = to_node if key_node_y in edges: edges.remove( key_node_y ) def has_edge(from_node, to_node, system='default'): edges = get_set( from_node, system=system ) return to_node in edges def neighbors(node_x, system='default'): return get_set( node_x, system=system ) #--- Node values ---------------------------- def get_node_value(node_x, system='default'): node_key = 'nv:%s' % node_x return get_redis(system).get( node_key ) def set_node_value(node_x, value, system='default'): node_key = 'nv:%s' % node_x return get_redis(system).set( node_key, value ) #--- Edge values ----------------------------- def get_edge_value(edge_x, system='default'): edge_key = 'ev:%s' % edge_x return get_redis(system).get( edge_key ) def set_edge_value(edge_x, value, system='default'): edge_key = 'ev:%s' % edge_x return get_redis(system).set( edge_key, value )
  • 12. redis_simple_queue A simple queue in Python using Redis https://github.com/Doist/redis_simple_queue
  • 13. redis_queue: usage from redis_simple_queue import * delete_jobs('tasks') put_job('tasks', '42') assert 'tasks' in get_all_queues() assert queue_stats('tasks')['queue_size'] == 1 assert reserve_job('tasks') == '42' assert queue_stats('tasks')['queue_size'] == 0
  • 14. redis_queue: Implementation from redis_wrap import * def put(queue, job_data, system='default'): get_list(queue, system=system).append(job_data) def reserve(queue, system='default'): return get_list(queue, system=system).pop() def delete_jobs(queue, system='default'): get_redis(system).delete(queue) def get_all_queues(system='default'): return get_redis(system).keys('*').split(' ') def queue_stats(queue, system='default'): return { 'queue_size': len(get_list(queue)) }
  • 17. bitmapist: Problem with MixPanel MixPanel would cost $2000/USD++/month
  • 18. bitmapist + bitmapist.cohort • Implements an advanced analytics library on top of Redis bitmaps
 • https://github.com/Doist/bitmapist • Hundreds of millions of events for Todoist • O(1) execution
  • 19. bitmapist: Features •Has user 123 been online today? This week? •Has user 123 performed action "X"? •How many users have been active have this month? •How many unique users have performed action "X" this week? •How many % of users that were active last week are still active? •How many % of users that were active last month are still active this month? •O(1)! Using very small amounts of memory.
  • 20. bitmapist: Bitmaps? • SETBIT, GETBIT, BITCOUNT, BITOP 
 • SETBIT somekey 8 1 • GETBIT somekey 8 • BITOP AND destkey somekey1 somekey2 • http://en.wikipedia.org/wiki/Bit_array
  • 21. bitmapist: Usage # Mark user 123 as active and has played a song mark_event('active', 123) mark_event('song:played', 123) # Answer if user 123 has been active this month assert 123 in MonthEvents('active', now.year, now.month) assert 123 in MonthEvents('song:played', now.year, now.month) # How many users have been active this week? print len(WeekEvents('active', now.year, now.isocalendar()[1])) # Perform bit operations. How many users that # have been active last month are still active this month? active_2_months = BitOpAnd( MonthEvents('active', last_month.year, last_month.month), MonthEvents('active', now.year, now.month) ) print len(active_2_months)
  • 25. fixedlist: The Easy Solution Throw money at the problem
  • 26. fixedlist: Cheating! • Fixed timeline size • O(1) insertion • O(1) update • O(1) get • Cacheable Solution that Facebook and Twitter use
  • 27. fixedlist 2.5x faster than pure Redis solution 1.4x less memory than pure Redis solution https://github.com/Doist/fixedlist
  • 28. fixedlist: Usage # Add a value to a list fixedlist.add('hello', 'world') # Add mutliple values to multiple keys at once fixedlist.add(['hello1', 'hello2'], ['world1', 'world2']) # Get valuesfrom a list assert fixedlist.get('hello') == ['world', 'world1', 'world2'] # Remove a value fixedlist.remove('hello', 'world1') Saved Plurk tens of thousands of $
  • 29. Redis+Lua+Python When you want: More complex data types Better performance
  • 30. Redis+Python: Incr implementation def incr_python(key, delta=1, system='default'): client, scripts = get_redis(system) with client.pipeline() as p: p.watch(key) value = delta old = p.get(key) if old: value = int(old) + delta p.set(key, value) p.unwatch() return value
  • 31. Redis+Lua: Incr implementation scripts = { 'incr': client.register_script(_load_lua_script('incr.lua')) } ... def incr_lua(key, delta=1, system='default'): client, scripts = get_redis(system) return scripts['incr'](keys=['key', 'delta'], args=[key, delta]) local delta = tonumber(ARGV[2]) local value = delta local old = tonumber(redis.call('get', ARGV[1])) if old then value = value + old end if not redis.call('set', ARGV[1], value) then return nil end return value
  • 32. Perfomance: Lua 3x faster Python time python test_incr_python.py 300000 python test_incr_python.py 300000 37.77s user 12.00s system 73% cpu 1:07.73 total Lua time python test_incr_lua.py 300000 python test_incr_lua.py 300000 10.76s user 2.85s system 66% cpu 20.513 total https://github.com/amix/demo-redis-python-lua
  • 33. fixedlist in Lua Proof of concept Tokyo Tyrant example https://gist.github.com/amix/f15508ac6a8b534c3290
  • 34. Q & A More questions: amix@doist.io @amix3k