SlideShare una empresa de Scribd logo
1 de 66
Descargar para leer sin conexión
REDIS: Need for speed
@elena_kolevska
Elena Kolevska 1
About Our Company
REDISFORYOURBOSS
Elena Kolevska
Who am I?
A nomad earthling | Self employed developer
BLOG.ELENAKOLEVSKA.COM
@ELENA_KOLEVSKA
(Really) SHORT
INTRO
No, seriously!
REDISISANOPENSOURCE(BSD licensed),
IN-MEMORYDATASTRUCTURESTORE,USED
ASDATABASE,CACHEANDMESSAGE
BROKER
The 'Definition' on redis.io
• Different data structures
• Keys with a limited time-to-live
• Lua scripting
• Transactions
• Pipelining
• Pub/Sub
• Built-in replication
• Different levels of on-disk persistence
BASIC FEATURES:
SPEED
AVAILABLE CLIENTS IN:
ActionScript
Common
Erlang
Haxe
Matlab
Pascal
Racket
Smalltalk
bash
Crystal
Fancy
Io
mruby
Perl
Rebol
Swift
C
D
gawk
Java
Nim
PHP
Ruby
Tcl
C#
Dart
GNUProlog
Javascript
Nodejs
PureData
Rust
VB
C++
Elixir
Go
Julia
ObjectiveC
Python
Scala
VCL
Clojure
Emacs lisp
Haskell
Lua
OCaml
R
Scheme
AVAILABLE DATA STRUCTURES:
•STRINGS (Binary safe, can be anything from "hello world" to a jpeg file)
•LISTS(Collections of string elements sorted according to the order of insertion)
•SETS (Collections of unique, unsorted string elements)
•SORTEDSETS (It's like Sets with a score)
•HASHES (Objects. Maps of fields associated to values. Think non-nested json objects)
•BITMAPS (Manipulate Strings on a bit level)
•HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
STRINGS
•Binary safe, can be from "hello world" to a jpeg filekeyname
value •Maximum size = 512MB
•Keynames can be emojis 🐘🦄😀
LISTS
keyname
value1
value2
value3
value2
value5
•Collection of strings
•Sorted by order of insertion
•Great for queues and timelines
•LPOP, BLPOP, LPUSHX, BRPOPLPUSH are O(1) operations
•Max length: > 4 billion elements
SETS
keyname
value1
value2
value3
value4
value5
•Collections of unique, unsorted string elements
•Great for tracking unique appearances
•Unions, intersections, differences
•Max length: > 4 billion elements
HASHES
keyname •Maps between string fields and string values
•Great for tracking representing objects
field1
field2
field3
field4
value1
value2
value3
value4
•Max length: > 4 billion elements
SORTED SETS
keyname •Sets with a floating number score
•Very fast access to elements in the middle
•Perfect for leaderboards
field1
field2
field3
field4
0.6379
6.379
63.79
637.9
•Get ranks of elements
•Get ranges of sorted elements
•Sort by value and by field, indirectly (lex)
BITMAPS
•Manipulate Strings on a bit levelkeyname
value •Set / clear individual bits
•Find the first set or unset bit
•Get count of all set/unset bits
HYPERLOGLOGS
•Probabilistic data structure used for estimating cardinalitykeyname
*
•Uses at most 12KB
•Conceptually similar to sets
•1% margin of error
•Used in IOT
Imagine ...
I loved the service at #statscompany,
30 minutes from ticket creation to
resoltuion. Well done guys, I'm
impressed.
I hate the service at #statscompany, I've
been on hold for the past 20minutes.
OUR SCENARIO: TWITTER ANALYZER DASHBOARD
751
TOTAL TWEETS
751Main stream
120sub-stream foo
107sub-stream bar
 




...
Substream:keyword 1 Substream:keyword 2
Love
Hate
Great
0 30 60 90 120
86
107
120
Total tweets
Scores
Main Stream
[1]CONNECTING
TOREDIS
[1]CONNECTINGTOREDIS
Install the PRedis package using Composer
> composer require predis/predis
Initialise the client
$parameters = [
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379
];
$client = new PredisClient($parameters, ['prefix' => 'stats:']);
[2] SET TRACKED
DATA
AVAILABLE DATA STRUCTURES:
•STRINGS (Binary safe, can be anything from "hello world" to a jpeg file)
•LISTS(Collections of string elements sorted according to the order of insertion)
•SETS (Collections of unique, unsorted string elements)
•SORTEDSETS (It's like Sets with a score)
•HASHES (Objects. Maps of fields associated to values. Think non-nested json objects)
•BITMAPS (Manipulate Strings on a bit level)
•HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
[2]SETTRACKEDDATA
Use sets to store all the hashtags we'll be looking at and all the keywords as well
$client->sadd('hashtags', 'thestatscompany','statscompany',
'statscampaign');
// hashtags | 'thestatscompany'
// | 'statscompany'
// | 'statscampaign'
$client->sadd('keywords', 'loved', 'amazed', 'frustrated',
'problem', 'terrible', 'amazing', 'great', 'hate');
[3] GET THE
DATA
[3]GETTHEDATA
Use Twitter Stream API to receive notifications for tweets containing any of the hashtags we're following
$hashtags = $client->smembers('hashtags');
// array (size=3)
// 0 => string 'thestatscompany' (length=15)
// 1 => string 'statscompany' (length=12)
// 2 => string 'statscampaign' (length=13)
Save every new tweet from the stream as a separate string:
$keyname = 'tweet_id:' . $tweet_id;
$tweet_contents = "Amazed by the customer service of #statscompany";
$client->set($keyname, $tweet_contents);
$keyname = 'tweet_id:' . $tweet_id;
$tweet_contents = "Amazed by the customer service of #statscompany";
$client->set($keyname, $tweet_contents);
AVAILABLE DATA STRUCTURES:
•STRINGS (Binary safe, can be anything from "hello world" to a jpeg file)
•LISTS(Collections of string elements sorted according to the order of insertion)
•SETS (Collections of unique, unsorted string elements)
•SORTEDSETS (It's like Sets with a score)
•HASHES (Objects. Maps of fields associated to values. Think non-nested json objects)
•BITMAPS (Manipulate Strings on a bit level)
•HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
And then push to a queue to be processed asynchronously
$client->lpush('message_queue', $keyname);
// 'message_queue' | 'tweet_id:45645656'
// | 'tweet_id:44645234'
// | 'tweet_id:43645232'
$client->lpush('message_queue', $keyname);
// 'message_queue' | 'tweet_id:45645656'
// | 'tweet_id:44645234'
// | 'tweet_id:43645232'
AVAILABLE DATA STRUCTURES:
•STRINGS (Binary safe, can be anything from "hello world" to a jpeg file)
•LISTS(Collections of string elements sorted according to the order of insertion)
•SETS (Collections of unique, unsorted string elements)
•SORTEDSETS (It's like Sets with a score)
•HASHES (Objects. Maps of fields associated to values. Think non-nested json objects)
•BITMAPS (Manipulate Strings on a bit level)
•HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
[4] WORKER TO
PROCESS THE
QUEUED JOBS
[4]WORKERTOPROCESSTHEQUEUEDJOBS
A separate worker will be grabbing jobs off the top of the queue and processing them:
$message_queue = $client->rpop('message_queue');$message_queue = $client->rpop('message_queue');
Reliable queue: RPOPLPUSH, BRPOPLPUSH
Blocking queue: BLPOP, BRPOP
[5] PROCESS THE
TWEET CONTENT
[5]PROCESSTHETWEETCONTENT
$tweet_contents = $client->get($keyname);
$keywords = $client->smembers('keywords');
foreach ($keywords as $keyword) {
$tweet_contents = strtolower($tweet_contents);
$keyword = strtolower($keyword);
if (strpos($tweet_contents,$keyword) !== false){
$client->zincrby('mention_counter', 1, $keyword);
$keyword_feed_keyname = 'keyword_feeds:'. $keyword;
$client->lpush($keyword_feed_keyname, $tweet_contents);
$client->ltrim($keyword_feed_keyname, 0, 50);
}
}
$client->incr('total_count'); // Increase the general tweet count
$client->lpush('main_feed', $tweet_contents);
$client->ltrim('main_feed', 0, 100);
$tweet_contents = $client->get($keyname);
$keywords = $client->smembers('keywords');
foreach ($keywords as $keyword) {
$tweet_contents = strtolower($tweet_contents);
$keyword = strtolower($keyword);
if (strpos($tweet_contents,$keyword) !== false){
$client->zincrby('mention_counter', 1, $keyword);
$keyword_feed_keyname = 'keyword_feeds:'. $keyword;
$client->lpush($keyword_feed_keyname, $tweet_contents);
$client->ltrim($keyword_feed_keyname, 0, 50);
}
}
$client->incr('total_count'); // Increase the general tweet count
$client->lpush('main_feed', $tweet_contents);
$client->ltrim('main_feed', 0, 100);
SORTED SETS
keyname •Sets with a floating number score
•Very fast access to elements in the middle
•Perfect for leaderboards
field1
field2
field3
field4
0.6379
6.379
63.79
637.9
•Get ranks of elements
•Get ranges of sorted elements
•Sort by value and by field, indirectly (lex)
[5]PROCESSTHETWEETCONTENT
$tweet_contents = $client->get($keyname);
$keywords = $client->smembers('keywords');
foreach ($keywords as $keyword) {
$tweet_contents = strtolower($tweet_contents);
$keyword = strtolower($keyword);
if (strpos($tweet_contents,$keyword) !== false){
$client->zincrby('mention_counter', 1, $keyword);
$keyword_feed_keyname = 'keyword_feeds:'. $keyword;
$client->lpush($keyword_feed_keyname, $tweet_contents);
$client->ltrim($keyword_feed_keyname, 0, 50);
}
}
$client->incr('total_count'); // Increase the general tweet count
$client->lpush('main_feed', $tweet_contents);
$client->ltrim('main_feed', 0, 100);
[6] SHOW
THE STATS
[6]SHOWTHESTATS
$total_count = $client->get('total_count');
// 'total_count' | 259
$scores = $client->zrevrangebyscore('mention_counter', '+inf', '-inf', ['withscores'=>1]);
// mention_counter | 'amazed' => 9.00
// | 'frustrated' => 5.00
// | 'love' => 4.00
// Feed by keyword
foreach ($scores as $keyname => $score) {
$keyword_feeds[$keyname] = $client->lrange('keyword_feeds:' . $keyname, 0, -1);
}
// Feed of all tweets containing one of the specified hashtags
$main_feed = $client->lrange('main_feed', 0, -1);
OUR SCENARIO: TWITTER ANALYZER DASHBOARD
751
TOTAL TWEETS
751Main stream
120sub-stream foo
107sub-stream bar
 




...
Substream:keyword 1 Substream:keyword 2
Love
Hate
Great
0 30 60 90 120
86
107
120
Total tweets
Scores
Main Stream
[7] CAN WE
MAKE IT FASTER?
Redis is TCP server using client/server model. A request to the server is
accomplished in two steps:
•The client sends a query to the server, and reads from the socket, usually in a blocking way,
for the server response
•The server processes the command and sends the response back to the client
Client Server
Networking link
Request from client to server
Response from server to client
Redis is a TCP server using the client/server model. A request to the server
is accomplished in two steps:
•The client sends a query to the server, and reads from the socket, usually in a blocking way,
for the server response
•The server processes the command and sends the response back to the client
Client Server
Request from client to server
Response from server to client
RTT: Round Trip Time
Number of
requests to
server
•Save the tweet
•Add tweet to main feed
•Increase counter for total tweets
•Get all monitored keywords
•Check tweet for any keywords
•Increase counter for found keywords
•Add tweet to sub-feed
•Update score
9THESTEPS:
Number of
requests to
server
•Save the tweet
•Add tweet to main feed
•Increase counter for total tweets
•Get all monitored keywords
•Check tweet for any keywords
•Increase counter for found keywords
•Add tweet to sub-feed
•Update score
13?
} + 4 requests for every found keyword
THESTEPS:
[WARP 8]
PIPELINING
1
Number of
requests to
server</php
$keywords = $client->smembers("keywords");
$responses = $client->pipeline(function ($pipe) use ($keywords) {
$pipe->set(...); // Save the tweet
$pipe->lpush(...); // Save the tweet to main feed
$pipe->ltrim(...); // Trim the main feed to X tweets so it doesn't grow forever
foreach ($keywords as $keyword) {
$pipe->incr(...); // Increase the counter for the keyword
$pipe->lpush(...); // Add to the subbed
$pipe->ltrim(...); // Trim the stream to X tweets
$pipe->zincrby(...); // Update score
}
});
USINGTHEPREDISLIBRARYFORPHP
2
Number of
requests to
server</php
$keywords = $client->smembers("keywords");
$responses = $client->pipeline(function ($pipe) use ($keywords) {
$pipe->set(...); // Save the tweet
$pipe->lpush(...); // Save the tweet to main feed
$pipe->ltrim(...); // Trim the main feed to X tweets so it doesn't grow forever
foreach ($keywords as $keyword) {
$pipe->incr(...); // Increase the counter for the keyword
$pipe->lpush(...); // Add to the subfeed
$pipe->ltrim(...); // Trim the stream to X tweets
$pipe->zincrby(...); // Update score
}
});
USINGTHEPREDISLIBRARYFORPHP
[WARP 9] LUA
SCRIPTING
Create a hello.lua file:
return "Hello"
> redis-cli --eval /path/to/script/hello.lua
"Hello"
hello.lua:
local tweet = ARGV[1]
local key_tweet = KEYS[1]
local key_keywords = KEYS[2]
local key_total_tweets_count = KEYS[3]
local key_scores = KEYS[4]
local key_main_feed = KEYS[5]
redis.call("SET", key_tweet, tweet) -- Save the tweet
redis.call("INCR", key_total_tweets_count) -- Increase the total tweet count
redis.call("LPUSH", key_main_feed, tweet) -- Push the tweet to the main feed
redis.call("LTRIM", key_main_feed, 0, 100) -- Trim the main feed
local keywords = redis.call("SMEMBERS", key_keywords) -- Get the keywords
for i, name in ipairs(keywords) do
if string.find(tweet, name) then
local substream_name = "sub_feed:" .. name
redis.call("LPUSH", substream_name, tweet) -- Push the tweet to the sub feed
redis.call("LTRIM", substream_name, 0, 100) -- Trim the sub feed
redis.call("ZINCRBY", key_scores, 1, name) -- Increment the score in the leaderboard
end
end
return "OK"
> redis-cli --eval hello.lua tweet_123 keywords ... , "A tweet about the words foo and bar"
"OK"
1!
Number of
requests to
server
SCRIPT
•Evaluates a script cached on the server side by its SHA1 digest. The command is otherwise
identical to EVAL.
> redis-cli SCRIPT LOAD "$(cat hello.lua)"
"6d52847f03028ab1d4620b60dd6ef4a14c8727d7"
> redis-cli evalsha 6d52847f03028ab1d4620b60dd6ef4a14c8727d7 5 
> tweet_123 keywords ... "A tweet about the words foo and bar"
"OK"
EVALSHA
•Load a script into the scripts cache, without executing it. Returns a SHA-1 digest of the script.
[WARP 10]
MODULES
•Dynamically loaded libraries
•Written in C
•Almost as fast as the Redis core
•Let you extend Redis commands, create new data structures, access data almost
as fast as native Redis commands
•Add-ons to Redis
•Coming in version 4.0, currently in Beta (RC)
WHATAREREDISMODULES?
•Low-level: Close to native access to core data structures
•High-level: Client-like access to core and modules' commands
LAYERSOFTHEMODULESAPI
RedisModule_Call(ctx,"INCR","sc",argv[1],"10");
Command
Format specifier
Arguments
The context object
c -- Null terminated C string pointer.
b -- C buffer, two arguments needed: C string pointer and size_t length.
s -- RedisModuleString as received in argv or by other Redis module APIs returning a RedisModuleString object.
l -- Long long integer.
v -- Array of RedisModuleString objects.
! -- This modifier just tells the function to replicate the command to slaves and AOF. It is ignored from the point of view of
arguments parsing.
HIGHLEVELAPI
Anatomy of a module
#include "redismodule.h"
#include <stdlib.h>
int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// ...
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// Register the module or error out
if (RedisModule_Init(ctx, "tweet_processor", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR;
// Register the command or error out
if (RedisModule_CreateCommand(ctx, "tweet.process", ProcessTweet_RedisCommand,
"readonly", 1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR;
return REDISMODULE_OK;
}
Definitions of the API
Called whenever the module is loaded
Must be present in each Redis module
Register the module or error out
Register the command or error out
Command Function name
Anatomy of a module
#include "redismodule.h"
#include <stdlib.h>
int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// ...
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// Register the module or error out
if (RedisModule_Init(ctx, "process_tweet", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR;
// Register the command or error out
if (RedisModule_CreateCommand(ctx, "process_tweet.rand", ProcessTweet_RedisCommand,
"readonly", 1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR;
return REDISMODULE_OK;
}
The logic of the module
How much faster does it get?
Anatomy of a module
#include "redismodule.h"
#include <stdlib.h>
int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// ...
}
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// Register the module or error out
if (RedisModule_Init(ctx, "process_tweet", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR;
// Register the command or error out
if (RedisModule_CreateCommand(ctx, "process_tweet.rand", ProcessTweet_RedisCommand,
"readonly", 1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR;
return REDISMODULE_OK;
}
int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
// We need EXACTLY 5 arguments
if (argc != 5) return RedisModule_WrongArity(ctx);
RedisModule_AutoMemory(ctx);
RedisModuleCallReply *reply;
reply = RedisModule_Call(ctx, "INCR", "s", argv[3]);
RedisModule_ReplyWithCallReply(ctx, reply);
return REDISMODULE_OK;
}
Enable automatic memory management
Call Redis commands
Reply with a call object
RedisModule_AutoMemory(ctx);
RedisModuleKey *key;
key = RedisModule_OpenKey(ctx,argv[1],REDISMODULE_READ|REDISMODULE_WRITE);
if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) {
RedisModule_StringSet(key,argv[2]);
}
RedisModule_CloseKey(key);
Open a key. Return a key pointer
Checks the type of the key
Set a string value for a key
Close the key
LOWLEVELAPI
Compiling
$ gcc -fPIC -std=gnu99 -c -o process_tweet process_tweet.c
$ ld -o process_tweet.so process_tweet.o -shared -Bsymbolic -lc
On Linux:
$ gcc -dynamic -fno-common -std=gnu99 -c -o process_tweet.o process_tweet.c
$ ld -o process_tweet.so process_tweet.o -bundle -undefined dynamic_lookup -lc
On OSX:
Loading
./redis-unstable/src/redis-server --loadmodule ./process_tweet.so
Calling the command
127.0.01:6379> tweet.process tweet_id:42 "This is my tweet about the words foo and bar" ...
Our command
Questions ?
Thank you !
@elena_kolevska

Más contenido relacionado

La actualidad más candente

PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overviewjsmith92
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Kacper Gunia
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojobpmedley
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworksdiego_k
 
Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101hendrikvb
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony TechniquesKris Wallsmith
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowKacper Gunia
 
Symfony without the framework
Symfony without the frameworkSymfony without the framework
Symfony without the frameworkGOG.com dev team
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128PrinceGuru MS
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8PrinceGuru MS
 

La actualidad más candente (20)

PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!Forget about index.php and build you applications around HTTP!
Forget about index.php and build you applications around HTTP!
 
Webrtc mojo
Webrtc mojoWebrtc mojo
Webrtc mojo
 
Perl web frameworks
Perl web frameworksPerl web frameworks
Perl web frameworks
 
New in php 7
New in php 7New in php 7
New in php 7
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Fatc
FatcFatc
Fatc
 
Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101Web Apps in Perl - HTTP 101
Web Apps in Perl - HTTP 101
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
CodeIgniter 3.0
CodeIgniter 3.0CodeIgniter 3.0
CodeIgniter 3.0
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
 
Mojo as a_client
Mojo as a_clientMojo as a_client
Mojo as a_client
 
Symfony without the framework
Symfony without the frameworkSymfony without the framework
Symfony without the framework
 
Developing apps using Perl
Developing apps using PerlDeveloping apps using Perl
Developing apps using Perl
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
Php tips-and-tricks4128
Php tips-and-tricks4128Php tips-and-tricks4128
Php tips-and-tricks4128
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8
 

Similar a Redis for your boss 2.0

Scaling php applications with redis
Scaling php applications with redisScaling php applications with redis
Scaling php applications with redisjimbojsb
 
Charla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo WebCharla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo WebMikel Torres Ugarte
 
Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013Simon McCartney
 
Service discovery and configuration provisioning
Service discovery and configuration provisioningService discovery and configuration provisioning
Service discovery and configuration provisioningSource Ministry
 
Mojo – Simple REST Server
Mojo – Simple REST ServerMojo – Simple REST Server
Mojo – Simple REST Serverhendrikvb
 
Internationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsInternationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsPierre MARTIN
 
Advanced Technology for Web Application Design
Advanced Technology for Web Application DesignAdvanced Technology for Web Application Design
Advanced Technology for Web Application DesignBryce Kerley
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)Robert Swisher
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeWim Godden
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress DeveloperJoey Kudish
 
Cassandra Tutorial
Cassandra TutorialCassandra Tutorial
Cassandra Tutorialmubarakss
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Shinya Ohyanagi
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018Adam Tomat
 
テスト用のプレゼンテーション
テスト用のプレゼンテーションテスト用のプレゼンテーション
テスト用のプレゼンテーションgooseboi
 
DBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たちDBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たちRyo Miyake
 
All Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for NewbiesAll Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for NewbiesDave Stokes
 

Similar a Redis for your boss 2.0 (20)

Redis
RedisRedis
Redis
 
Scaling php applications with redis
Scaling php applications with redisScaling php applications with redis
Scaling php applications with redis
 
Charla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo WebCharla EHU Noviembre 2014 - Desarrollo Web
Charla EHU Noviembre 2014 - Desarrollo Web
 
Php summary
Php summaryPhp summary
Php summary
 
Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013Stack kicker devopsdays-london-2013
Stack kicker devopsdays-london-2013
 
Service discovery and configuration provisioning
Service discovery and configuration provisioningService discovery and configuration provisioning
Service discovery and configuration provisioning
 
Mojo – Simple REST Server
Mojo – Simple REST ServerMojo – Simple REST Server
Mojo – Simple REST Server
 
Internationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsInternationalizing CakePHP Applications
Internationalizing CakePHP Applications
 
Advanced Technology for Web Application Design
Advanced Technology for Web Application DesignAdvanced Technology for Web Application Design
Advanced Technology for Web Application Design
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Beyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the codeBeyond PHP - It's not (just) about the code
Beyond PHP - It's not (just) about the code
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress Developer
 
Blog Hacks 2011
Blog Hacks 2011Blog Hacks 2011
Blog Hacks 2011
 
Pecl Picks
Pecl PicksPecl Picks
Pecl Picks
 
Cassandra Tutorial
Cassandra TutorialCassandra Tutorial
Cassandra Tutorial
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
 
テスト用のプレゼンテーション
テスト用のプレゼンテーションテスト用のプレゼンテーション
テスト用のプレゼンテーション
 
DBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たちDBIx::Skinnyと仲間たち
DBIx::Skinnyと仲間たち
 
All Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for NewbiesAll Things Open 2016 -- Database Programming for Newbies
All Things Open 2016 -- Database Programming for Newbies
 

Último

Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Hr365.us smith
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesPhilip Schwarz
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfLivetecs LLC
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaHanief Utama
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odishasmiwainfosol
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfIdiosysTechnologies1
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentationvaddepallysandeep122
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 

Último (20)

Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)Recruitment Management Software Benefits (Infographic)
Recruitment Management Software Benefits (Infographic)
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Folding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a seriesFolding Cheat Sheet #4 - fourth in a series
Folding Cheat Sheet #4 - fourth in a series
 
How to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdfHow to Track Employee Performance A Comprehensive Guide.pdf
How to Track Employee Performance A Comprehensive Guide.pdf
 
React Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief UtamaReact Server Component in Next.js by Hanief Utama
React Server Component in Next.js by Hanief Utama
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort ServiceHot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
Hot Sexy call girls in Patel Nagar🔝 9953056974 🔝 escort Service
 
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company OdishaBalasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
Balasore Best It Company|| Top 10 IT Company || Balasore Software company Odisha
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Best Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdfBest Web Development Agency- Idiosys USA.pdf
Best Web Development Agency- Idiosys USA.pdf
 
PREDICTING RIVER WATER QUALITY ppt presentation
PREDICTING  RIVER  WATER QUALITY  ppt presentationPREDICTING  RIVER  WATER QUALITY  ppt presentation
PREDICTING RIVER WATER QUALITY ppt presentation
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 

Redis for your boss 2.0

  • 1. REDIS: Need for speed @elena_kolevska Elena Kolevska 1 About Our Company REDISFORYOURBOSS Elena Kolevska
  • 2. Who am I? A nomad earthling | Self employed developer BLOG.ELENAKOLEVSKA.COM @ELENA_KOLEVSKA
  • 5. • Different data structures • Keys with a limited time-to-live • Lua scripting • Transactions • Pipelining • Pub/Sub • Built-in replication • Different levels of on-disk persistence BASIC FEATURES:
  • 8. AVAILABLE DATA STRUCTURES: •STRINGS (Binary safe, can be anything from "hello world" to a jpeg file) •LISTS(Collections of string elements sorted according to the order of insertion) •SETS (Collections of unique, unsorted string elements) •SORTEDSETS (It's like Sets with a score) •HASHES (Objects. Maps of fields associated to values. Think non-nested json objects) •BITMAPS (Manipulate Strings on a bit level) •HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
  • 9. STRINGS •Binary safe, can be from "hello world" to a jpeg filekeyname value •Maximum size = 512MB •Keynames can be emojis 🐘🦄😀
  • 10. LISTS keyname value1 value2 value3 value2 value5 •Collection of strings •Sorted by order of insertion •Great for queues and timelines •LPOP, BLPOP, LPUSHX, BRPOPLPUSH are O(1) operations •Max length: > 4 billion elements
  • 11. SETS keyname value1 value2 value3 value4 value5 •Collections of unique, unsorted string elements •Great for tracking unique appearances •Unions, intersections, differences •Max length: > 4 billion elements
  • 12. HASHES keyname •Maps between string fields and string values •Great for tracking representing objects field1 field2 field3 field4 value1 value2 value3 value4 •Max length: > 4 billion elements
  • 13. SORTED SETS keyname •Sets with a floating number score •Very fast access to elements in the middle •Perfect for leaderboards field1 field2 field3 field4 0.6379 6.379 63.79 637.9 •Get ranks of elements •Get ranges of sorted elements •Sort by value and by field, indirectly (lex)
  • 14. BITMAPS •Manipulate Strings on a bit levelkeyname value •Set / clear individual bits •Find the first set or unset bit •Get count of all set/unset bits
  • 15. HYPERLOGLOGS •Probabilistic data structure used for estimating cardinalitykeyname * •Uses at most 12KB •Conceptually similar to sets •1% margin of error •Used in IOT
  • 17. I loved the service at #statscompany, 30 minutes from ticket creation to resoltuion. Well done guys, I'm impressed. I hate the service at #statscompany, I've been on hold for the past 20minutes.
  • 18. OUR SCENARIO: TWITTER ANALYZER DASHBOARD 751 TOTAL TWEETS 751Main stream 120sub-stream foo 107sub-stream bar       ... Substream:keyword 1 Substream:keyword 2 Love Hate Great 0 30 60 90 120 86 107 120 Total tweets Scores Main Stream
  • 20. [1]CONNECTINGTOREDIS Install the PRedis package using Composer > composer require predis/predis Initialise the client $parameters = [ 'scheme' => 'tcp', 'host' => '127.0.0.1', 'port' => 6379 ]; $client = new PredisClient($parameters, ['prefix' => 'stats:']);
  • 22. AVAILABLE DATA STRUCTURES: •STRINGS (Binary safe, can be anything from "hello world" to a jpeg file) •LISTS(Collections of string elements sorted according to the order of insertion) •SETS (Collections of unique, unsorted string elements) •SORTEDSETS (It's like Sets with a score) •HASHES (Objects. Maps of fields associated to values. Think non-nested json objects) •BITMAPS (Manipulate Strings on a bit level) •HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
  • 23. [2]SETTRACKEDDATA Use sets to store all the hashtags we'll be looking at and all the keywords as well $client->sadd('hashtags', 'thestatscompany','statscompany', 'statscampaign'); // hashtags | 'thestatscompany' // | 'statscompany' // | 'statscampaign' $client->sadd('keywords', 'loved', 'amazed', 'frustrated', 'problem', 'terrible', 'amazing', 'great', 'hate');
  • 25. [3]GETTHEDATA Use Twitter Stream API to receive notifications for tweets containing any of the hashtags we're following $hashtags = $client->smembers('hashtags'); // array (size=3) // 0 => string 'thestatscompany' (length=15) // 1 => string 'statscompany' (length=12) // 2 => string 'statscampaign' (length=13)
  • 26. Save every new tweet from the stream as a separate string: $keyname = 'tweet_id:' . $tweet_id; $tweet_contents = "Amazed by the customer service of #statscompany"; $client->set($keyname, $tweet_contents); $keyname = 'tweet_id:' . $tweet_id; $tweet_contents = "Amazed by the customer service of #statscompany"; $client->set($keyname, $tweet_contents);
  • 27. AVAILABLE DATA STRUCTURES: •STRINGS (Binary safe, can be anything from "hello world" to a jpeg file) •LISTS(Collections of string elements sorted according to the order of insertion) •SETS (Collections of unique, unsorted string elements) •SORTEDSETS (It's like Sets with a score) •HASHES (Objects. Maps of fields associated to values. Think non-nested json objects) •BITMAPS (Manipulate Strings on a bit level) •HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
  • 28. And then push to a queue to be processed asynchronously $client->lpush('message_queue', $keyname); // 'message_queue' | 'tweet_id:45645656' // | 'tweet_id:44645234' // | 'tweet_id:43645232' $client->lpush('message_queue', $keyname); // 'message_queue' | 'tweet_id:45645656' // | 'tweet_id:44645234' // | 'tweet_id:43645232'
  • 29. AVAILABLE DATA STRUCTURES: •STRINGS (Binary safe, can be anything from "hello world" to a jpeg file) •LISTS(Collections of string elements sorted according to the order of insertion) •SETS (Collections of unique, unsorted string elements) •SORTEDSETS (It's like Sets with a score) •HASHES (Objects. Maps of fields associated to values. Think non-nested json objects) •BITMAPS (Manipulate Strings on a bit level) •HYPERLOGLOGS (Probabilistic data structure used to estimate the cardinality of a set)
  • 30. [4] WORKER TO PROCESS THE QUEUED JOBS
  • 31. [4]WORKERTOPROCESSTHEQUEUEDJOBS A separate worker will be grabbing jobs off the top of the queue and processing them: $message_queue = $client->rpop('message_queue');$message_queue = $client->rpop('message_queue'); Reliable queue: RPOPLPUSH, BRPOPLPUSH Blocking queue: BLPOP, BRPOP
  • 33. [5]PROCESSTHETWEETCONTENT $tweet_contents = $client->get($keyname); $keywords = $client->smembers('keywords'); foreach ($keywords as $keyword) { $tweet_contents = strtolower($tweet_contents); $keyword = strtolower($keyword); if (strpos($tweet_contents,$keyword) !== false){ $client->zincrby('mention_counter', 1, $keyword); $keyword_feed_keyname = 'keyword_feeds:'. $keyword; $client->lpush($keyword_feed_keyname, $tweet_contents); $client->ltrim($keyword_feed_keyname, 0, 50); } } $client->incr('total_count'); // Increase the general tweet count $client->lpush('main_feed', $tweet_contents); $client->ltrim('main_feed', 0, 100); $tweet_contents = $client->get($keyname); $keywords = $client->smembers('keywords'); foreach ($keywords as $keyword) { $tweet_contents = strtolower($tweet_contents); $keyword = strtolower($keyword); if (strpos($tweet_contents,$keyword) !== false){ $client->zincrby('mention_counter', 1, $keyword); $keyword_feed_keyname = 'keyword_feeds:'. $keyword; $client->lpush($keyword_feed_keyname, $tweet_contents); $client->ltrim($keyword_feed_keyname, 0, 50); } } $client->incr('total_count'); // Increase the general tweet count $client->lpush('main_feed', $tweet_contents); $client->ltrim('main_feed', 0, 100);
  • 34. SORTED SETS keyname •Sets with a floating number score •Very fast access to elements in the middle •Perfect for leaderboards field1 field2 field3 field4 0.6379 6.379 63.79 637.9 •Get ranks of elements •Get ranges of sorted elements •Sort by value and by field, indirectly (lex)
  • 35. [5]PROCESSTHETWEETCONTENT $tweet_contents = $client->get($keyname); $keywords = $client->smembers('keywords'); foreach ($keywords as $keyword) { $tweet_contents = strtolower($tweet_contents); $keyword = strtolower($keyword); if (strpos($tweet_contents,$keyword) !== false){ $client->zincrby('mention_counter', 1, $keyword); $keyword_feed_keyname = 'keyword_feeds:'. $keyword; $client->lpush($keyword_feed_keyname, $tweet_contents); $client->ltrim($keyword_feed_keyname, 0, 50); } } $client->incr('total_count'); // Increase the general tweet count $client->lpush('main_feed', $tweet_contents); $client->ltrim('main_feed', 0, 100);
  • 37. [6]SHOWTHESTATS $total_count = $client->get('total_count'); // 'total_count' | 259 $scores = $client->zrevrangebyscore('mention_counter', '+inf', '-inf', ['withscores'=>1]); // mention_counter | 'amazed' => 9.00 // | 'frustrated' => 5.00 // | 'love' => 4.00 // Feed by keyword foreach ($scores as $keyname => $score) { $keyword_feeds[$keyname] = $client->lrange('keyword_feeds:' . $keyname, 0, -1); } // Feed of all tweets containing one of the specified hashtags $main_feed = $client->lrange('main_feed', 0, -1);
  • 38. OUR SCENARIO: TWITTER ANALYZER DASHBOARD 751 TOTAL TWEETS 751Main stream 120sub-stream foo 107sub-stream bar       ... Substream:keyword 1 Substream:keyword 2 Love Hate Great 0 30 60 90 120 86 107 120 Total tweets Scores Main Stream
  • 39. [7] CAN WE MAKE IT FASTER?
  • 40. Redis is TCP server using client/server model. A request to the server is accomplished in two steps: •The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response •The server processes the command and sends the response back to the client Client Server Networking link Request from client to server Response from server to client
  • 41. Redis is a TCP server using the client/server model. A request to the server is accomplished in two steps: •The client sends a query to the server, and reads from the socket, usually in a blocking way, for the server response •The server processes the command and sends the response back to the client Client Server Request from client to server Response from server to client RTT: Round Trip Time
  • 42. Number of requests to server •Save the tweet •Add tweet to main feed •Increase counter for total tweets •Get all monitored keywords •Check tweet for any keywords •Increase counter for found keywords •Add tweet to sub-feed •Update score 9THESTEPS:
  • 43. Number of requests to server •Save the tweet •Add tweet to main feed •Increase counter for total tweets •Get all monitored keywords •Check tweet for any keywords •Increase counter for found keywords •Add tweet to sub-feed •Update score 13? } + 4 requests for every found keyword THESTEPS:
  • 45. 1 Number of requests to server</php $keywords = $client->smembers("keywords"); $responses = $client->pipeline(function ($pipe) use ($keywords) { $pipe->set(...); // Save the tweet $pipe->lpush(...); // Save the tweet to main feed $pipe->ltrim(...); // Trim the main feed to X tweets so it doesn't grow forever foreach ($keywords as $keyword) { $pipe->incr(...); // Increase the counter for the keyword $pipe->lpush(...); // Add to the subbed $pipe->ltrim(...); // Trim the stream to X tweets $pipe->zincrby(...); // Update score } }); USINGTHEPREDISLIBRARYFORPHP
  • 46. 2 Number of requests to server</php $keywords = $client->smembers("keywords"); $responses = $client->pipeline(function ($pipe) use ($keywords) { $pipe->set(...); // Save the tweet $pipe->lpush(...); // Save the tweet to main feed $pipe->ltrim(...); // Trim the main feed to X tweets so it doesn't grow forever foreach ($keywords as $keyword) { $pipe->incr(...); // Increase the counter for the keyword $pipe->lpush(...); // Add to the subfeed $pipe->ltrim(...); // Trim the stream to X tweets $pipe->zincrby(...); // Update score } }); USINGTHEPREDISLIBRARYFORPHP
  • 48. Create a hello.lua file: return "Hello" > redis-cli --eval /path/to/script/hello.lua "Hello"
  • 49. hello.lua: local tweet = ARGV[1] local key_tweet = KEYS[1] local key_keywords = KEYS[2] local key_total_tweets_count = KEYS[3] local key_scores = KEYS[4] local key_main_feed = KEYS[5] redis.call("SET", key_tweet, tweet) -- Save the tweet redis.call("INCR", key_total_tweets_count) -- Increase the total tweet count redis.call("LPUSH", key_main_feed, tweet) -- Push the tweet to the main feed redis.call("LTRIM", key_main_feed, 0, 100) -- Trim the main feed local keywords = redis.call("SMEMBERS", key_keywords) -- Get the keywords for i, name in ipairs(keywords) do if string.find(tweet, name) then local substream_name = "sub_feed:" .. name redis.call("LPUSH", substream_name, tweet) -- Push the tweet to the sub feed redis.call("LTRIM", substream_name, 0, 100) -- Trim the sub feed redis.call("ZINCRBY", key_scores, 1, name) -- Increment the score in the leaderboard end end return "OK"
  • 50. > redis-cli --eval hello.lua tweet_123 keywords ... , "A tweet about the words foo and bar" "OK" 1! Number of requests to server
  • 51. SCRIPT •Evaluates a script cached on the server side by its SHA1 digest. The command is otherwise identical to EVAL. > redis-cli SCRIPT LOAD "$(cat hello.lua)" "6d52847f03028ab1d4620b60dd6ef4a14c8727d7" > redis-cli evalsha 6d52847f03028ab1d4620b60dd6ef4a14c8727d7 5 > tweet_123 keywords ... "A tweet about the words foo and bar" "OK" EVALSHA •Load a script into the scripts cache, without executing it. Returns a SHA-1 digest of the script.
  • 53. •Dynamically loaded libraries •Written in C •Almost as fast as the Redis core •Let you extend Redis commands, create new data structures, access data almost as fast as native Redis commands •Add-ons to Redis •Coming in version 4.0, currently in Beta (RC) WHATAREREDISMODULES?
  • 54. •Low-level: Close to native access to core data structures •High-level: Client-like access to core and modules' commands LAYERSOFTHEMODULESAPI
  • 55.
  • 56.
  • 57.
  • 58. RedisModule_Call(ctx,"INCR","sc",argv[1],"10"); Command Format specifier Arguments The context object c -- Null terminated C string pointer. b -- C buffer, two arguments needed: C string pointer and size_t length. s -- RedisModuleString as received in argv or by other Redis module APIs returning a RedisModuleString object. l -- Long long integer. v -- Array of RedisModuleString objects. ! -- This modifier just tells the function to replicate the command to slaves and AOF. It is ignored from the point of view of arguments parsing. HIGHLEVELAPI
  • 59. Anatomy of a module #include "redismodule.h" #include <stdlib.h> int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // ... } int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // Register the module or error out if (RedisModule_Init(ctx, "tweet_processor", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR; // Register the command or error out if (RedisModule_CreateCommand(ctx, "tweet.process", ProcessTweet_RedisCommand, "readonly", 1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; return REDISMODULE_OK; } Definitions of the API Called whenever the module is loaded Must be present in each Redis module Register the module or error out Register the command or error out Command Function name
  • 60. Anatomy of a module #include "redismodule.h" #include <stdlib.h> int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // ... } int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // Register the module or error out if (RedisModule_Init(ctx, "process_tweet", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR; // Register the command or error out if (RedisModule_CreateCommand(ctx, "process_tweet.rand", ProcessTweet_RedisCommand, "readonly", 1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; return REDISMODULE_OK; } The logic of the module
  • 61. How much faster does it get? Anatomy of a module #include "redismodule.h" #include <stdlib.h> int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // ... } int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // Register the module or error out if (RedisModule_Init(ctx, "process_tweet", 1, REDISMODULE_APIVER_1) == REDISMODULE_ERR) return REDISMODULE_ERR; // Register the command or error out if (RedisModule_CreateCommand(ctx, "process_tweet.rand", ProcessTweet_RedisCommand, "readonly", 1,1,1) == REDISMODULE_ERR) return REDISMODULE_ERR; return REDISMODULE_OK; } int ProcessTweet_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { // We need EXACTLY 5 arguments if (argc != 5) return RedisModule_WrongArity(ctx); RedisModule_AutoMemory(ctx); RedisModuleCallReply *reply; reply = RedisModule_Call(ctx, "INCR", "s", argv[3]); RedisModule_ReplyWithCallReply(ctx, reply); return REDISMODULE_OK; } Enable automatic memory management Call Redis commands Reply with a call object
  • 62. RedisModule_AutoMemory(ctx); RedisModuleKey *key; key = RedisModule_OpenKey(ctx,argv[1],REDISMODULE_READ|REDISMODULE_WRITE); if (RedisModule_KeyType(key) == REDISMODULE_KEYTYPE_EMPTY) { RedisModule_StringSet(key,argv[2]); } RedisModule_CloseKey(key); Open a key. Return a key pointer Checks the type of the key Set a string value for a key Close the key LOWLEVELAPI
  • 63. Compiling $ gcc -fPIC -std=gnu99 -c -o process_tweet process_tweet.c $ ld -o process_tweet.so process_tweet.o -shared -Bsymbolic -lc On Linux: $ gcc -dynamic -fno-common -std=gnu99 -c -o process_tweet.o process_tweet.c $ ld -o process_tweet.so process_tweet.o -bundle -undefined dynamic_lookup -lc On OSX: Loading ./redis-unstable/src/redis-server --loadmodule ./process_tweet.so
  • 64. Calling the command 127.0.01:6379> tweet.process tweet_id:42 "This is my tweet about the words foo and bar" ... Our command