SlideShare a Scribd company logo
1 of 44
Scaling PHP Applications with Redis
Josh Butts
Zendcon 2011

http://joind.in/3783
About Me

• Director of Development at Vertive, LLC


• Zend Certified in PHP 5 and ZF


• Organizer of AustinPHP


• Find me online:


  • Twitter: @jimbojsb


  • Github: jimbojsb
Agenda

• Redis Overview


• Types of keys


• PHP Strategies
What is Redis?

• Redis is an “Advanced” key-value store database


• Backed by VMWare


• Redis works like memcached, but better:


  • Atomic commands & transactions


  • Server-side data structures


  • In-memory + disk persistence
Redis in an in-memory database

• You need as much RAM as you have data


• There are no plans to improve support for “virtual” memory


• Disk persistence is exactly that


• Customize disk writes interval to suit your pain threshold


• Something interesting happens when you run out of memory
How to get Redis

• http://redis.io


• Doesn’t run (well) on Windows


   • There are a few ports out there


• Has virtually no compile dependencies


• Most distros have a package


• Make sure you’re running at least 2.2


   • 2.4.1 became stable 10/17/11
How to explore

• There aren’t any good GUI tools out there


• redis-cli is your friend
A bit about organization

• Redis can have multiple databases


  • Analogous to a MySQL database within a server instance


  • Theoretically, over 1000 databases per server


  • One data file on disk per instance


• Within a database, namespace your keys


  • Ex: myapp:mykey


  • Keep them concise but useful. Keys take memory too!
Types of Keys
String Keys             http://redis.io/commands#string

• Simple key-value


• Memcache equivalent


• Common Commands


  • SET


  • GET


  • INCR


  • STRLEN
Hash Keys                     http://redis.io/commands#hash

• Key + multiple fields / values                  • Common commands

• Like an associative array in PHP                  • HSET

• mykey => [field1 => value1, field2 => value2]     • HGET

• No nesting (unlike PHP)                           • HGETALL


                                                    • HDEL


                                                    • HVALS


                                                    • HKEYS
Hash Keys
Set Keys                            http://redis.io/commands#set

• key + unordered list of strings


• myset => [item2, item5, item1,]


• Common Commands


   • SADD


   • SMEMBERS


   • SISMEMBER


   • SREM
Set Keys
List Keys                        http://redis.io/commands#list

• Like sets, except insertion order matters


• Build queues or stacks


• Optional blocking


• Common commands


  • [B]LPUSH


  • [B]LPOP


  • LLEN
List Keys
Sorted Set Keys

• Like sets, but sorted by a user-provided score value


• Extremely fast access by score or range of scores, because it’s sorted in
  storage


• Common commands


  • ZADD


  • ZRANGE


  • ZREVRANGE
Sorted Set Keys
Other commands that work on all keys

• DEL - delete a key, regardless of type


• KEYS - search for keys (usually with a wildcard)


• EXPIRE / PERSIST - change expiration values for keys
Connecting from PHP
Connecting from PHP

• Several libraries out there


   • Rediska (http://rediska.geometria-lab.net/)


      • PHP 5.2 / ZF 1.x friendly


   • Predis (https://github.com/nrk/predis)


      • The best in my experience


      • Requires PHP 5.3
Predis

• All the examples here assume you’re using Predis


• Connect to a localhost redis: $p = new PredisClient();


• Redis commands implemented as magic methods on Client();


• $p->set($key, $val);


• $val = $p->get($key);
Attribute Display Logic

                                             items_attributes
                         items
                                                id INT(11)

                       id INT(11)             item_id INT(11)

                                          attr_name VARCHAR(32)
                   name VARCHAR(32)
                                          attr_value VARCHAR(32)



                   10k rows               100k rows
• An item, a Dell Latitude Laptop, has:


  • Free Shipping, Financing Available, Expires Soon, etc
Attribute Display Logic

   • Display “Free Shipping” graphic on the item if it has a free
     shipping attribute row




                        50 items per page
Attribute Display - Traditional

  class Item
  {
     public function hasAttribute($name)
     {
       $sql = "SELECT 1
             FROM items_attributes
             WHERE item_id = $this->id
             AND attr_name='$name'
             LIMIT 1";
       $result = $this->pdo->execute($sql);
       return $result != false;
     }
  }
Denormalize data from MySQL to Redis

• Smart caching


• Define a consistent way to represent a relational object in Redis


  • I prefer [object class]:[object id]:[attribute]


  • ex: product:13445:num_comments


  • This prevents data collisions, and makes it easy to work with data on
    the command line
Attribute Display - Redis


class Item
{
   public function hasAttribute($name)
   {
     return $this->redis->sismember(“item:$this->id:attributes”, $name);
   }

    public function addAttribute($name, $value)
    {
      //traditional mysql stuff here still
      $this->redis->sadd('item:45:attributes', $name);
    }
}
Advantages

• The more items you have, the less MySQL will scale this solution for you on
  it’s own


• Frequently updating your items kills the MySQL query cache


• Checking existence of a set member is O(1) time


• On a laptop, I can check roughly 10,000 attributes per second
Session Clustering



      WEB - 1             WEB - 2         WEB - 3

      PHP Sessions       PHP Sessions     PHP Sessions




                     Inconsistent state
Session Clustering



       WEB - 1        WEB - 2        WEB - 3




                       DB - 1

                     PHP Sessions


Slow with many users (never cached), replication lag
Session Clustering



      WEB - 1              WEB - 2        WEB - 3




           REDIS - 1                 DB - 1

            PHP Sessions



   Constant time lookups, in-memory sessions
Job Queues

• Redis lists make great job queues


• Offload your intensive workloads to some other process


• Blocking I/O allows you to easily build long-running daemons
Job Queues

class Queue
{
   protected $name;
   protected $predis;

    public function push(Array $job)
    {
      $this->predis->lpush($this->name, json_encode($job));
    }

    public function pop($block = false)
    {
      $job = null;
      if ($block) {
          $data = $this->predis->brpop($this->name, 0);
          $job = $data[1];
      } else {
          $job = $this->predis->rpop($this->name);
      }
      if ($job) {
          return json_decode($job);
      }
    }
}
Queuing Jobs

$q = new Queue('test_queue');
$form = new My_Zend_Form();
if ($form->isValid($_POST)) {

    $q->push($form->getValues());
    $message = “Thanks for your submission”;

} else {

    $message = “Error - something went wrong”;

}

echo “<h1>$message</h1>”;
Processing Jobs - Crontab style

 function processJob(Array $job)
 {
    //...something really cool here
    // throw an exception on error
 }

 // process all pending jobs
 $q = new Queue(‘test_queue’);
 while ($job = $q->pop()) {
    try {
            processJob($job);
        } catch (Exception $e) {
           Echo “error processing job”;
           $q = new Queue(‘errors’);
           $q->push($job);
        }
 }
Processing Jobs - Worker style

function processJob(Array $job)
{
   //...something really cool here
   // throw an exception on error
}

// keep processing jobs as they become available
$q = new Queue(‘test_queue’);
while ($job = $q->pop(true)) {
   try {
           processJob($job);
       } catch (Exception $e) {
          Echo “error processing job”;
          $q = new Queue(‘errors’);
          $q->push($job);
       }
}
MVC Routing

• Example:


  • Offers.com has about 3900 stores


  • Store pages live at /[store]/
Old Store Routing


 class Store_Route
 {
    public function route($url)
    {
      $sql = “SELECT id, type
                        FROM stores
                        WHERE url=’$url’”;
      $store = $this->pdo->execute($sql);
      //... do logic to determine what action to use based on type ...//
            return array(“module”     => “core”,
                             “controller” => “store”,
                             “action”    => $action);
    }
 }




• And then there’s offers.com/[holiday]/....
New Routing


class Redis_Route
{
   public function route($url)
   {
     $p = $this->predis;
     if ($p->exists($url)) {

          list($module, $controller, $action) = $this->redis->hVals($url);
          return array(“module”    => $module,
                   “controller” => $controller,
                   “action”    => $action);
        }
        return false;
    }
}
Filling in the Redis keys




 class Store
 {
    public function create(Array $data)
    {
           // ... traditional SQL stuff to put store in the database ... //
         $route = array(“module” => “core”,
                           “controller” => “store”,
                           “action” => $data[“type”]);
           $this->predis->hmset($data[“url”], $route);
    }
 }
Advantages

• I can now create offers.com/[anything]/ and route it to the right place, in
  O(1) time


• I’m only adding a few lines of code to my existing models
Questions?
http://joind.in/3783
Vertive is Hiring

• We help people save money


• We’re looking for engineers in Austin, TX to work on:

More Related Content

What's hot

Kicking ass with redis
Kicking ass with redisKicking ass with redis
Kicking ass with redis
Dvir Volk
 

What's hot (20)

Redis and it's data types
Redis and it's data typesRedis and it's data types
Redis and it's data types
 
Speed up your Symfony2 application and build awesome features with Redis
Speed up your Symfony2 application and build awesome features with RedisSpeed up your Symfony2 application and build awesome features with Redis
Speed up your Symfony2 application and build awesome features with Redis
 
Introduction to redis - version 2
Introduction to redis - version 2Introduction to redis - version 2
Introduction to redis - version 2
 
Redis Use Patterns (DevconTLV June 2014)
Redis Use Patterns (DevconTLV June 2014)Redis Use Patterns (DevconTLV June 2014)
Redis Use Patterns (DevconTLV June 2014)
 
Redis memcached pdf
Redis memcached pdfRedis memcached pdf
Redis memcached pdf
 
Redis introduction
Redis introductionRedis introduction
Redis introduction
 
Redis in Practice
Redis in PracticeRedis in Practice
Redis in Practice
 
An Introduction to REDIS NoSQL database
An Introduction to REDIS NoSQL databaseAn Introduction to REDIS NoSQL database
An Introduction to REDIS NoSQL database
 
Redis/Lessons learned
Redis/Lessons learnedRedis/Lessons learned
Redis/Lessons learned
 
Boosting Machine Learning with Redis Modules and Spark
Boosting Machine Learning with Redis Modules and SparkBoosting Machine Learning with Redis Modules and Spark
Boosting Machine Learning with Redis Modules and Spark
 
Extend Redis with Modules
Extend Redis with ModulesExtend Redis with Modules
Extend Redis with Modules
 
Introduction to Redis
Introduction to RedisIntroduction to Redis
Introduction to Redis
 
Redis basics
Redis basicsRedis basics
Redis basics
 
Kicking ass with redis
Kicking ass with redisKicking ass with redis
Kicking ass with redis
 
Nodejs - A quick tour (v5)
Nodejs - A quick tour (v5)Nodejs - A quick tour (v5)
Nodejs - A quick tour (v5)
 
Redis and its many use cases
Redis and its many use casesRedis and its many use cases
Redis and its many use cases
 
Nodejs - A quick tour (v4)
Nodejs - A quick tour (v4)Nodejs - A quick tour (v4)
Nodejs - A quick tour (v4)
 
Introduction to Redis
Introduction to RedisIntroduction to Redis
Introduction to Redis
 
Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?Nodejs - Should Ruby Developers Care?
Nodejs - Should Ruby Developers Care?
 
Nodejs - A-quick-tour-v3
Nodejs - A-quick-tour-v3Nodejs - A-quick-tour-v3
Nodejs - A-quick-tour-v3
 

Viewers also liked

Redis Everywhere - Sunshine PHP
Redis Everywhere - Sunshine PHPRedis Everywhere - Sunshine PHP
Redis Everywhere - Sunshine PHP
Ricard Clau
 
Beyond relational database - Building high performance websites using Redis a...
Beyond relational database - Building high performance websites using Redis a...Beyond relational database - Building high performance websites using Redis a...
Beyond relational database - Building high performance websites using Redis a...
Dinh Pham
 
MOSC2012 - Building High-Performance Web-Application with PHP & MongoDB
MOSC2012 - Building High-Performance Web-Application with PHP & MongoDBMOSC2012 - Building High-Performance Web-Application with PHP & MongoDB
MOSC2012 - Building High-Performance Web-Application with PHP & MongoDB
r1dotmy
 
Redis everywhere - PHP London
Redis everywhere - PHP LondonRedis everywhere - PHP London
Redis everywhere - PHP London
Ricard Clau
 
Authentication: Cookies vs JWTs and why you’re doing it wrong
Authentication: Cookies vs JWTs and why you’re doing it wrongAuthentication: Cookies vs JWTs and why you’re doing it wrong
Authentication: Cookies vs JWTs and why you’re doing it wrong
Derek Perkins
 

Viewers also liked (20)

How to scale PHP applications
How to scale PHP applicationsHow to scale PHP applications
How to scale PHP applications
 
PHP High Availability High Performance
PHP High Availability High PerformancePHP High Availability High Performance
PHP High Availability High Performance
 
(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance
 
Architechture of a social network for 30M users
Architechture of a social network for 30M usersArchitechture of a social network for 30M users
Architechture of a social network for 30M users
 
Slide Seminar PHP Indonesia - NoSQL Redis
Slide Seminar PHP Indonesia - NoSQL RedisSlide Seminar PHP Indonesia - NoSQL Redis
Slide Seminar PHP Indonesia - NoSQL Redis
 
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
Creating a Smooth Development Workflow for High-Quality Modular Open-Source P...
 
Redis Everywhere - Sunshine PHP
Redis Everywhere - Sunshine PHPRedis Everywhere - Sunshine PHP
Redis Everywhere - Sunshine PHP
 
NoSQL in MySQL
NoSQL in MySQLNoSQL in MySQL
NoSQL in MySQL
 
Beyond relational database - Building high performance websites using Redis a...
Beyond relational database - Building high performance websites using Redis a...Beyond relational database - Building high performance websites using Redis a...
Beyond relational database - Building high performance websites using Redis a...
 
MOSC2012 - Building High-Performance Web-Application with PHP & MongoDB
MOSC2012 - Building High-Performance Web-Application with PHP & MongoDBMOSC2012 - Building High-Performance Web-Application with PHP & MongoDB
MOSC2012 - Building High-Performance Web-Application with PHP & MongoDB
 
Scaling symfony apps
Scaling symfony appsScaling symfony apps
Scaling symfony apps
 
Docker deploy
Docker deployDocker deploy
Docker deploy
 
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
Building Multi-Tenant and SaaS products in PHP - CloudConf 2015
 
Frontera: open source, large scale web crawling framework
Frontera: open source, large scale web crawling frameworkFrontera: open source, large scale web crawling framework
Frontera: open source, large scale web crawling framework
 
Scaling PHP to 40 Million Uniques
Scaling PHP to 40 Million UniquesScaling PHP to 40 Million Uniques
Scaling PHP to 40 Million Uniques
 
RestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message QueueRestMQ - HTTP/Redis based Message Queue
RestMQ - HTTP/Redis based Message Queue
 
PHP with Service BUS (RabbitMQ/Redis/MongoDB) - IMasters PHP Experience 2016
PHP with Service BUS (RabbitMQ/Redis/MongoDB) - IMasters PHP Experience 2016PHP with Service BUS (RabbitMQ/Redis/MongoDB) - IMasters PHP Experience 2016
PHP with Service BUS (RabbitMQ/Redis/MongoDB) - IMasters PHP Experience 2016
 
Redis everywhere - PHP London
Redis everywhere - PHP LondonRedis everywhere - PHP London
Redis everywhere - PHP London
 
Magento scalability from the trenches (Meet Magento Sweden 2016)
Magento scalability from the trenches (Meet Magento Sweden 2016)Magento scalability from the trenches (Meet Magento Sweden 2016)
Magento scalability from the trenches (Meet Magento Sweden 2016)
 
Authentication: Cookies vs JWTs and why you’re doing it wrong
Authentication: Cookies vs JWTs and why you’re doing it wrongAuthentication: Cookies vs JWTs and why you’re doing it wrong
Authentication: Cookies vs JWTs and why you’re doing it wrong
 

Similar to Scaling php applications with redis

Introducing PHP Data Objects
Introducing PHP Data ObjectsIntroducing PHP Data Objects
Introducing PHP Data Objects
webhostingguy
 
MIND sweeping introduction to PHP
MIND sweeping introduction to PHPMIND sweeping introduction to PHP
MIND sweeping introduction to PHP
BUDNET
 

Similar to Scaling php applications with redis (20)

PHP Basics and Demo HackU
PHP Basics and Demo HackUPHP Basics and Demo HackU
PHP Basics and Demo HackU
 
Fatc
FatcFatc
Fatc
 
Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010Advanced Php - Macq Electronique 2010
Advanced Php - Macq Electronique 2010
 
Php summary
Php summaryPhp summary
Php summary
 
Redis the better NoSQL
Redis the better NoSQLRedis the better NoSQL
Redis the better NoSQL
 
Php
PhpPhp
Php
 
Supercharging WordPress Development in 2018
Supercharging WordPress Development in 2018Supercharging WordPress Development in 2018
Supercharging WordPress Development in 2018
 
Performance tuning with zend framework
Performance tuning with zend frameworkPerformance tuning with zend framework
Performance tuning with zend framework
 
Working with databases in Perl
Working with databases in PerlWorking with databases in Perl
Working with databases in Perl
 
Top ten-list
Top ten-listTop ten-list
Top ten-list
 
Spl Not A Bridge Too Far phpNW09
Spl Not A Bridge Too Far phpNW09Spl Not A Bridge Too Far phpNW09
Spl Not A Bridge Too Far phpNW09
 
Introducing PHP Data Objects
Introducing PHP Data ObjectsIntroducing PHP Data Objects
Introducing PHP Data Objects
 
Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Modern php
Modern phpModern php
Modern php
 
Drupal II: The SQL
Drupal II: The SQLDrupal II: The SQL
Drupal II: The SQL
 
Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2Zend Framework 1 + Doctrine 2
Zend Framework 1 + Doctrine 2
 
Php course-in-navimumbai
Php course-in-navimumbaiPhp course-in-navimumbai
Php course-in-navimumbai
 
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, HerokuPostgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
Postgres & Redis Sitting in a Tree- Rimas Silkaitis, Heroku
 
PHP from soup to nuts Course Deck
PHP from soup to nuts Course DeckPHP from soup to nuts Course Deck
PHP from soup to nuts Course Deck
 
MIND sweeping introduction to PHP
MIND sweeping introduction to PHPMIND sweeping introduction to PHP
MIND sweeping introduction to PHP
 

More from jimbojsb

Fall 2011 PHP Class - Session 2
Fall 2011 PHP Class - Session 2Fall 2011 PHP Class - Session 2
Fall 2011 PHP Class - Session 2
jimbojsb
 
Fall 2011 PHP Class - Session 1
Fall 2011 PHP Class - Session 1Fall 2011 PHP Class - Session 1
Fall 2011 PHP Class - Session 1
jimbojsb
 
Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06
jimbojsb
 
GeekAustin PHP Class - Session 7
GeekAustin PHP Class - Session 7GeekAustin PHP Class - Session 7
GeekAustin PHP Class - Session 7
jimbojsb
 
GeekAustin PHP Class - Session 6
GeekAustin PHP Class - Session 6GeekAustin PHP Class - Session 6
GeekAustin PHP Class - Session 6
jimbojsb
 
Geek Austin PHP Class - Session 4
Geek Austin PHP Class - Session 4Geek Austin PHP Class - Session 4
Geek Austin PHP Class - Session 4
jimbojsb
 
Geek Austin PHP Class - Session 3
Geek Austin PHP Class - Session 3Geek Austin PHP Class - Session 3
Geek Austin PHP Class - Session 3
jimbojsb
 
Geek Austin PHP Class - Session 2
Geek Austin PHP Class - Session 2Geek Austin PHP Class - Session 2
Geek Austin PHP Class - Session 2
jimbojsb
 
Geek Austin PHP Class - Session 1
Geek Austin PHP Class - Session 1Geek Austin PHP Class - Session 1
Geek Austin PHP Class - Session 1
jimbojsb
 

More from jimbojsb (9)

Fall 2011 PHP Class - Session 2
Fall 2011 PHP Class - Session 2Fall 2011 PHP Class - Session 2
Fall 2011 PHP Class - Session 2
 
Fall 2011 PHP Class - Session 1
Fall 2011 PHP Class - Session 1Fall 2011 PHP Class - Session 1
Fall 2011 PHP Class - Session 1
 
Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06
 
GeekAustin PHP Class - Session 7
GeekAustin PHP Class - Session 7GeekAustin PHP Class - Session 7
GeekAustin PHP Class - Session 7
 
GeekAustin PHP Class - Session 6
GeekAustin PHP Class - Session 6GeekAustin PHP Class - Session 6
GeekAustin PHP Class - Session 6
 
Geek Austin PHP Class - Session 4
Geek Austin PHP Class - Session 4Geek Austin PHP Class - Session 4
Geek Austin PHP Class - Session 4
 
Geek Austin PHP Class - Session 3
Geek Austin PHP Class - Session 3Geek Austin PHP Class - Session 3
Geek Austin PHP Class - Session 3
 
Geek Austin PHP Class - Session 2
Geek Austin PHP Class - Session 2Geek Austin PHP Class - Session 2
Geek Austin PHP Class - Session 2
 
Geek Austin PHP Class - Session 1
Geek Austin PHP Class - Session 1Geek Austin PHP Class - Session 1
Geek Austin PHP Class - Session 1
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
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
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
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
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
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
 
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
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
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
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
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...
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
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
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
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
 
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
 

Scaling php applications with redis

  • 1. Scaling PHP Applications with Redis Josh Butts Zendcon 2011 http://joind.in/3783
  • 2. About Me • Director of Development at Vertive, LLC • Zend Certified in PHP 5 and ZF • Organizer of AustinPHP • Find me online: • Twitter: @jimbojsb • Github: jimbojsb
  • 3. Agenda • Redis Overview • Types of keys • PHP Strategies
  • 4. What is Redis? • Redis is an “Advanced” key-value store database • Backed by VMWare • Redis works like memcached, but better: • Atomic commands & transactions • Server-side data structures • In-memory + disk persistence
  • 5. Redis in an in-memory database • You need as much RAM as you have data • There are no plans to improve support for “virtual” memory • Disk persistence is exactly that • Customize disk writes interval to suit your pain threshold • Something interesting happens when you run out of memory
  • 6. How to get Redis • http://redis.io • Doesn’t run (well) on Windows • There are a few ports out there • Has virtually no compile dependencies • Most distros have a package • Make sure you’re running at least 2.2 • 2.4.1 became stable 10/17/11
  • 7. How to explore • There aren’t any good GUI tools out there • redis-cli is your friend
  • 8. A bit about organization • Redis can have multiple databases • Analogous to a MySQL database within a server instance • Theoretically, over 1000 databases per server • One data file on disk per instance • Within a database, namespace your keys • Ex: myapp:mykey • Keep them concise but useful. Keys take memory too!
  • 10. String Keys http://redis.io/commands#string • Simple key-value • Memcache equivalent • Common Commands • SET • GET • INCR • STRLEN
  • 11. Hash Keys http://redis.io/commands#hash • Key + multiple fields / values • Common commands • Like an associative array in PHP • HSET • mykey => [field1 => value1, field2 => value2] • HGET • No nesting (unlike PHP) • HGETALL • HDEL • HVALS • HKEYS
  • 13. Set Keys http://redis.io/commands#set • key + unordered list of strings • myset => [item2, item5, item1,] • Common Commands • SADD • SMEMBERS • SISMEMBER • SREM
  • 15. List Keys http://redis.io/commands#list • Like sets, except insertion order matters • Build queues or stacks • Optional blocking • Common commands • [B]LPUSH • [B]LPOP • LLEN
  • 17. Sorted Set Keys • Like sets, but sorted by a user-provided score value • Extremely fast access by score or range of scores, because it’s sorted in storage • Common commands • ZADD • ZRANGE • ZREVRANGE
  • 19. Other commands that work on all keys • DEL - delete a key, regardless of type • KEYS - search for keys (usually with a wildcard) • EXPIRE / PERSIST - change expiration values for keys
  • 21. Connecting from PHP • Several libraries out there • Rediska (http://rediska.geometria-lab.net/) • PHP 5.2 / ZF 1.x friendly • Predis (https://github.com/nrk/predis) • The best in my experience • Requires PHP 5.3
  • 22. Predis • All the examples here assume you’re using Predis • Connect to a localhost redis: $p = new PredisClient(); • Redis commands implemented as magic methods on Client(); • $p->set($key, $val); • $val = $p->get($key);
  • 23. Attribute Display Logic items_attributes items id INT(11) id INT(11) item_id INT(11) attr_name VARCHAR(32) name VARCHAR(32) attr_value VARCHAR(32) 10k rows 100k rows • An item, a Dell Latitude Laptop, has: • Free Shipping, Financing Available, Expires Soon, etc
  • 24. Attribute Display Logic • Display “Free Shipping” graphic on the item if it has a free shipping attribute row 50 items per page
  • 25. Attribute Display - Traditional class Item { public function hasAttribute($name) { $sql = "SELECT 1 FROM items_attributes WHERE item_id = $this->id AND attr_name='$name' LIMIT 1"; $result = $this->pdo->execute($sql); return $result != false; } }
  • 26. Denormalize data from MySQL to Redis • Smart caching • Define a consistent way to represent a relational object in Redis • I prefer [object class]:[object id]:[attribute] • ex: product:13445:num_comments • This prevents data collisions, and makes it easy to work with data on the command line
  • 27. Attribute Display - Redis class Item { public function hasAttribute($name) { return $this->redis->sismember(“item:$this->id:attributes”, $name); } public function addAttribute($name, $value) { //traditional mysql stuff here still $this->redis->sadd('item:45:attributes', $name); } }
  • 28. Advantages • The more items you have, the less MySQL will scale this solution for you on it’s own • Frequently updating your items kills the MySQL query cache • Checking existence of a set member is O(1) time • On a laptop, I can check roughly 10,000 attributes per second
  • 29. Session Clustering WEB - 1 WEB - 2 WEB - 3 PHP Sessions PHP Sessions PHP Sessions Inconsistent state
  • 30. Session Clustering WEB - 1 WEB - 2 WEB - 3 DB - 1 PHP Sessions Slow with many users (never cached), replication lag
  • 31. Session Clustering WEB - 1 WEB - 2 WEB - 3 REDIS - 1 DB - 1 PHP Sessions Constant time lookups, in-memory sessions
  • 32. Job Queues • Redis lists make great job queues • Offload your intensive workloads to some other process • Blocking I/O allows you to easily build long-running daemons
  • 33. Job Queues class Queue { protected $name; protected $predis; public function push(Array $job) { $this->predis->lpush($this->name, json_encode($job)); } public function pop($block = false) { $job = null; if ($block) { $data = $this->predis->brpop($this->name, 0); $job = $data[1]; } else { $job = $this->predis->rpop($this->name); } if ($job) { return json_decode($job); } } }
  • 34. Queuing Jobs $q = new Queue('test_queue'); $form = new My_Zend_Form(); if ($form->isValid($_POST)) { $q->push($form->getValues()); $message = “Thanks for your submission”; } else { $message = “Error - something went wrong”; } echo “<h1>$message</h1>”;
  • 35. Processing Jobs - Crontab style function processJob(Array $job) { //...something really cool here // throw an exception on error } // process all pending jobs $q = new Queue(‘test_queue’); while ($job = $q->pop()) { try { processJob($job); } catch (Exception $e) { Echo “error processing job”; $q = new Queue(‘errors’); $q->push($job); } }
  • 36. Processing Jobs - Worker style function processJob(Array $job) { //...something really cool here // throw an exception on error } // keep processing jobs as they become available $q = new Queue(‘test_queue’); while ($job = $q->pop(true)) { try { processJob($job); } catch (Exception $e) { Echo “error processing job”; $q = new Queue(‘errors’); $q->push($job); } }
  • 37. MVC Routing • Example: • Offers.com has about 3900 stores • Store pages live at /[store]/
  • 38. Old Store Routing class Store_Route { public function route($url) { $sql = “SELECT id, type FROM stores WHERE url=’$url’”; $store = $this->pdo->execute($sql); //... do logic to determine what action to use based on type ...// return array(“module” => “core”, “controller” => “store”, “action” => $action); } } • And then there’s offers.com/[holiday]/....
  • 39. New Routing class Redis_Route { public function route($url) { $p = $this->predis; if ($p->exists($url)) { list($module, $controller, $action) = $this->redis->hVals($url); return array(“module” => $module, “controller” => $controller, “action” => $action); } return false; } }
  • 40. Filling in the Redis keys class Store { public function create(Array $data) { // ... traditional SQL stuff to put store in the database ... // $route = array(“module” => “core”, “controller” => “store”, “action” => $data[“type”]); $this->predis->hmset($data[“url”], $route); } }
  • 41. Advantages • I can now create offers.com/[anything]/ and route it to the right place, in O(1) time • I’m only adding a few lines of code to my existing models
  • 44. Vertive is Hiring • We help people save money • We’re looking for engineers in Austin, TX to work on:

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. Can do increment, etc on individual fields\n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n