Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Dynamic Data Cache

Dynamic Data Cache

Note: This desk has been revised. https://speakerdeck.com/bobmajdakjr/dynamic-data-cache-v2

Given at Lone Star PHP 2014 in Dallas Texas, talking about some quick ways to bolt dynamic data caching onto an application.

Bob Majdak Jr

April 26, 2014
Tweet

More Decks by Bob Majdak Jr

Other Decks in Programming

Transcript

  1. WHY CACHING STATIC OUTPUT SUCKS Potentially hundreds of static HTML

    files on the web server.  But, static serving is fast!  Yes… yes it is… sometimes… Have to wrap every single app output with cache collecting and storage. May even have to refactor the app depending on how output is sent out. (lots of echos everywhere vs a template, etc, whatever)  But WordPress has a plugin for that!  Good for you.
  2. CACHE RAW DATA if cache exists return cached data else

    query database fetch data result cache data return data
  3. CACHE RAW DATA PRO Typically smaller memory footprint. Abstracts the

    cache at a very high level that is easy to intercept. Interception being key. You could integrity test it against the database, if you wanted. CON Still requires PHP to parse data and create your objects for each requested object.
  4. CACHE DATA OBJECTS if cache exists return cached object else

    query database fetch result build object from data cache object return object
  5. CACHE DATA OBJECTS PRO Objects are brought back just as

    you left them. Objects don‘t need to construct again. Just inflate. CON Requires deeper integration with the code platform depending on application structure. May require architecture changes – this style works much nicer with Factory style building. If an object is changed, such as a property renamed, all the cached versions will be broke. A forced flush!
  6. APPCACHE Local to the application instance/hit/request. Great for storing objects

    which tend to be small and reused multiple times an application, such as users objects. Installation: None. It’s an application design feature. Overly Simple Example: Cache::$Data = array( ‘user-1’ => User Object { ‘ID’=>1, ‘Name’=‘Bob’ }, ‘user-117’ => User Object { ‘ID’=>117, ‘Name’=‘John’ } );
  7. MEMCACHE Local to the application cluster/network. We use it the

    same as the Appcache, only it magically persists across page hits or requests. Memcache is a server for key=>value storage. It allows you to build a pool of servers working together to create one giant cache. Servers can be added and dropped as needed. http://memcached.org/ It can be accessed with PHP via the Memcache extension. http://www.php.net/memcache (note, PHP has memcache and memcacheD… without the D is the preferred, updated, and up to date version. However, the preferred server daemon does have the D.)
  8. CACHE INTERFACE: APP AND MEM Here we have the constructor

    for this Cache interface class. Because of how we want it to work, ideally our application would only create one instance of this class to be globally accessed by anything in the app. Also known as a singleton. That is what the static property and Create method is for. At application start we call Cache::Create(); and will be able to access it via Cache::$Main. If you have a global instance manager (Nether\Stash) you would not need the statics.
  9. CACHE INTERFACE: STORE INTO CACHE In Appcache we can store

    data as is, because Objects are Passed-By- Reference by default, and other values are only Copy-On-Write, this is a very efficient storage for data that probably won’t change by the end of the application hit. To store into Memcache however we must flatten or serialize the data before sending it to the Memcache server. This will allow Memcache to store flat data it does not care what it is at all. Cache::$Main->Set(‘test’,’bob’);
  10. CACHE INTERFACE: FETCH FROM CACHE To fetch from Appcache we

    can grab the data right back as stored. To fetch from Memcache we have to reinflate or unseralize the data we originally stored there. $data = Cache::$Main->Get(‘test’);
  11. CACHE INTERFACE: INVALIDATE CACHE When a data object changes, all

    the caches related to that object need to be flushed so that they can be recached with the updated version. This will tell the caches to forget the data stored, next time we fetch the data we will notice the cache is missing and repopulate it with fresh data. Cache::$Main->Drop(‘test’);
  12. CACHE PROCESS: FIRST HIT, FIRST QUERY <application> get_user(1); <get_user($id)> checking

    cache… <appcache> i no has. <memcache> i no has. <get_user($id)> checking database… <database> lol, fools. i has it. <appcache> ok now I has it. <memcache> ok now i has it. <get_user($id)> here is user with id 1
  13. CACHE PROCESS: FIRST HIT, SECOND QUERY <application> get_user(1); <get_user($id)> checking

    cache… <appcache> i has i has! here it is. <get_user($id)> here is user with id 1
  14. CACHE PROCESS: SECOND HIT, FIRST QUERY <application> get_user(1); <get_user($id)> checking

    cache… <appcache> i no has. <memcache> oh oh i has! here it is. <appcache> now i has it. <get_user($id)> here is user with id 1
  15. CACHE PROCESS: SECOND HIT, SECOND QUERY <application> get_user(1); <get_user($id)> checking

    cache… <appcache> i has i has! here it is. <get_user($id)> here is user with id 1
  16. DISKCACHE Local to the filesystem. Great for caching huge data

    sets that may take time for the server to turn out, like a list of all the users who wrote posts that had over 100 likes this month, data we would use to generate a “most popular submitter” type page. Scan post table, Join user table, Count post likes Where likes >= 100 Sort by likes A simple query, but after 1,000,000 posts could “be slow” and also could return a huge data set. Huge datasets like this could be too much bloat to have in App and Memcache. Installation: None. It’s an application design feature.
  17. CACHE INTERFACE: DISKCACHE Diskcache is better suited for large data

    sets that do not change or are not accessed as often as other objects. You must also take into consideration file system security when implementing it.
  18. THE NEW FLOW Read the most recent posts. Iterate over

    each post, fetch the user associated. Render the page. If the most recent posts were not already cached, they are cached the first time they are fetched. If the user was not already cached, they are cached first time they are fetched as well. Next time this page is loaded: 100% of the request is served from cache without a single hit to the database.
  19. SOME THIRD PARTY STUFF… ONES YOU CAN BOLT ONTO ANYTHING.

    Doctrine Cache (App, APC, Disk, Memcache, MongoDB, Redis, …)  https://github.com/doctrine/cache Symfony 2 Cache (App, APC, Disk, Memcache, Redis, …)  https://github.com/illuminate/cache Nether Cache (App, Memcache, Disk)  https://github.com/netherphp/cache
  20. EXAMPLE USING THIRD PARTY: NETHER This example uses the Nether

    Cache module to handle checking, populating, and invalidating of cache. All the third parties more or less work the same, just with different function names and whatnot. Pick the one that fits best in your framework, (e.g. already using Symfony2, use illuminate/cache)
  21. OVERLY ENTHUSIASTIC CONSTRUCTION __construct($id); A Constructor. Constructors construct things. To

    build something, you must provide materials. Why would a constructor fetch and cache? It’s not __fetchachtor($id); Searching by Email or Username? Constructor expects an ID here. Why does an object need to know how to fetch an object?
  22. FACTORY + OBJECT CACHE Constructor only contains logic to validate

    and construct the object given the building materials it was given. The finished Object is cached. GetByID knows that the cache contains complete objects. Static functions means objects don’t have public methods they don’t need. A user doesn’t need to know how to find itself by its Email when you already have found it.
  23. FACTORY + DATA CACHE Constructor only contains logic to validate

    and construct the object given the building materials it was given. The original source data is cached. GetByID knows that the cache is really just a database row. Static functions means objects don’t have public methods they don’t need. A user doesn’t need to know how to find itself by its Email when you already have found it.
  24. SECURING YOUR CACHE Shared hosting and Diskcache?  Encrypt cache

    before store.  Only store to a private directory that only the required applications have access to read.  Don’t cache in the public web directory. Memcached, MongoDB, Redis, or any other network accessed cache?  Cache servers should only be accessible by the private network only.  Firewalling, etc.  Encrypt if you want, technically not necessary if protected isolated network.
  25. CACHE. HIT IT HARD. HIT IT OFTEN. Bob Majdak Jr

    • @bobmajdakjr • [email protected] • This Talk: • https://joind.in/10824 • These Slides: • http://goo.gl/ReC4uy