t.me/aperitech
bit.ly/devcalendar
bit.ly/CodemotionTC
#AperiTech
Un’iniziativa di powered	by
IN-MEMORY CACHING
OBJECTS TECHNIQUES
Mauro Cassani,
PUG ROMA
30th May, 2017
ABOUT ME
Mauro Cassani
github.com/mauretto78
WHAT IS CACHE?
In computing, a cache, is a hardware or software
component that stores data so future requests for
that data can be served faster; the data stored in
a cache might be the result of an earlier computation,
or the duplicate of data stored elsewhere.[1]
“ “
[1] https://en.wikipedia.org/wiki/Cache_(computing)
CACHING TECHNIQUES
There are different caching methods that we can use with
PHP:
➤ Caching content

We can cache content in PHP by saving the final output of a specific
script into the filesystem then simply serving it like a static file for a
specific period of time instead of executing the original script.
CACHING TECHNIQUES
There are different caching methods that we can use with
PHP:
➤ Caching content

We can cache content in PHP by saving the final output of a specific
script into the filesystem then simply serving it like a static file for a
specific period of time instead of executing the original script.
➤ Database Cache

Caching the caching is done by the database server itself. This works
by caching the results of the query so the query is only parsed the first
time it runs and in the succeeding requests it won’t be parsed since the
results from the specific query is already cached by the database
server.
CACHING TECHNIQUES
There are different caching methods that we can use with
PHP:
➤ Caching content

We can cache content in PHP by saving the final output of a specific
script into the filesystem then simply serving it like a static file for a
specific period of time instead of executing the original script.
➤ Database Cache

Caching the caching is done by the database server itself. This works
by caching the results of the query so the query is only parsed the first
time it runs and in the succeeding requests it won’t be parsed since the
results from the specific query is already cached by the database
server.
➤ Memory Cache

Memory caching techniques are widely used; they use the volatile
memory data and are a lot more faster than caching in the file system.
MEMORY CACHING
Memory caching techniques are widely used; they use the volatile memory
data and are a lot more faster than caching in the file system.
➤ APCU [2]

Alternative PHP Cache User Cache (APCU) provides a full backwards
compatible API to the shared memory userland cache provided by APC.
[2] http://php.net/manual/en/intro.apcu.php
MEMORY CACHING
Memory caching techniques are widely used; they use the volatile memory
data and are a lot more faster than caching in the file system.
➤ APCU [2]

Alternative PHP Cache User Cache (APCU) provides a full backwards
compatible API to the shared memory userland cache provided by APC.
➤ MEMCACHED [3]

Memcached is an in-memory key-value store for small chunks of
arbitrary data (strings, objects) from results of database calls, API calls,
or page rendering.
[2] http://php.net/manual/en/intro.apcu.php

[3] https://memcached.org/
MEMORY CACHING
Memory caching techniques are widely used; they use the volatile memory
data and are a lot more faster than caching in the file system.
➤ APCU [2]

Alternative PHP Cache User Cache (APCU) provides a full backwards
compatible API to the shared memory userland cache provided by APC.
➤ MEMCACHED [3]

Memcached is an in-memory key-value store for small chunks of
arbitrary data (strings, objects) from results of database calls, API calls,
or page rendering.
➤ REDIS [4]

Redis is an open source (BSD licensed), in-memory data structure
store, used as a database, cache and message broker.
[2] http://php.net/manual/en/intro.apcu.php

[3] https://memcached.org/

[4] https://redis.io/
APCU
APCu (APC User Cache) is APC stripped of opcode caching.
The first APCu codebase was versioned 4.0.0, it was forked from the head
of the APC master branch at the time.
PHP 7 support is available as of APCu 5.0.0.
APCu can provide a compatibility mode, such that it can provide a drop in
replacement for the applicable parts of APC.
APCU IN PHP
<?php
// Set a value
apcu_store('foo', 'bar', 7200);
apcu_store('integer', 12345678, 7200);
apcu_store('boolean', true, 7200);
apcu_store('array', ['apple', 'banana', 'pear'], 7200);
apcu_store('object', serialize(new MyAwesomeClass()), 7200);
// Get a value
apcu_fetch(‘foo’);
// Delete a value
apcu_delete(‘foo’);
// Flush the cache
apcu_clear_cache();
APCU IN PHP(2)
<?php
// ..
$myCacheKey = 'my_cache_key';
$row = apcu_fetch($myCacheKey);
if (!$row) {
// Issue painful query to mysql
$sql = "SELECT * FROM table WHERE id = :id";
$dbo->prepare($sql);
$stmt->bindValue(':id', $someId, PDO::PARAM_INT);
$row = $stmt->fetch(PDO::FETCH_OBJ);
apcu_store($myCacheKey, serialize($row));
}
// Now I have access to $row, where I can do what I need to
// And for subsequent calls, the data will be pulled from cache and skip
// the query altogether
var_dump(unserialize($row));
MEMCACHED
Memcached is a distributed caching system in RAM for objects, and is
widely used in dynamic web applications to relieve the load on the
database, making it possible to serve some of the data to which access is
most frequent, directly from RAM memory .
MEMCACHED
Memcached is a distributed caching system in RAM for objects, and is
widely used in dynamic web applications to relieve the load on the
database, making it possible to serve some of the data to which access is
most frequent, directly from RAM memory .
Memcached was created in 2003 by the company operating LiveJournal,
Danga Interactive, which had to handle more than 20 million exponential
dynamic daily requests. The adoption of this innovative caching system
has made it possible to drastically reduce the load on database servers
and significantly improve site performance.
MEMCACHED
Memcached is a distributed caching system in RAM for objects, and is
widely used in dynamic web applications to relieve the load on the
database, making it possible to serve some of the data to which access is
most frequent, directly from RAM memory .
Memcached was created in 2003 by the company operating LiveJournal,
Danga Interactive, which had to handle more than 20 million exponential
dynamic daily requests. The adoption of this innovative caching system
has made it possible to drastically reduce the load on database servers
and significantly improve site performance.
The software was then publicly released under the BSD license that
allowed it to be implemented by other web giants and the inevitable
addition of many features and constant performance enhancement.
Among the most famous memcached users we find informatics giants
such as WordPress, Wikipedia, Flickr, Twitter, YouTube, Digg and
Facebook.
MEMCACHED IN PHP
<?php
// Get Connection
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);
// Set a value
$memcached->set('foo', 'bar', 7200);
$memcached->set('integer', 12345678, 7200);
$memcached->set('boolean', true, 7200);
$memcached->set('array', ['apple', 'banana', 'pear'], 7200);
$memcached->set('object', serialize(new MyAwesomeClass()), 7200);
// Get a value
$memcached->get(‘foo');
// Update a value
$memcached->replace('foo', 'barbar', 10200);
// Change TTL
$memcached->touch('foo', 29000);
// Delete a value
$memcached->delete('foo');
// Flush the cache
$memcached->flush();
MEMCACHED IN PHP(2)
<?php
// ..
$memcached = new Memcached();
$memcached->addServer('localhost', 11211);
$myCacheKey = 'my_cache_key';
$row = $cache->get($myCacheKey);
if (!$row) {
// Issue painful query to mysql
$sql = "SELECT * FROM table WHERE id = :id";
$dbo->prepare($sql);
$stmt->bindValue(':id', $someId, PDO::PARAM_INT);
$row = $stmt->fetch(PDO::FETCH_OBJ);
$memcached->set($myCacheKey, serialize($row));
}
// Now I have access to $row, where I can do what I need to
// And for subsequent calls, the data will be pulled from cache and skip
// the query altogether
var_dump(unserialize($row));
REDIS
Redis is an in-memory database open-source software project sponsored
by Redis Labs. It is networked, in-memory, and stores keys with optional
durability.
REDIS
Redis is an in-memory database open-source software project sponsored
by Redis Labs. It is networked, in-memory, and stores keys with optional
durability.
The name Redis means REmote DIctionary Server. 

Salvatore Sanfilippo, the original developer of Redis, was hired by
VMware in March, 2010. In May, 2013, Redis was sponsored by Pivotal
Software (a VMware spin-off). In June 2015, development became
sponsored by Redis Labs.
REDIS
Redis is an in-memory database open-source software project sponsored
by Redis Labs. It is networked, in-memory, and stores keys with optional
durability.
The name Redis means REmote DIctionary Server. 

Salvatore Sanfilippo, the original developer of Redis, was hired by
VMware in March, 2010. In May, 2013, Redis was sponsored by Pivotal
Software (a VMware spin-off). In June 2015, development became
sponsored by Redis Labs.
According to monthly rankings by DB-Engines.com, Redis is often ranked
the most popular key-value database. Redis has also been ranked the #4
NoSQL database in user satisfaction and market presence based on
user reviews, the most popular NoSQL database in containers, and the #1
NoSQL database among Top 50 Developer Tools & Services.
REDIS
Redis is an in-memory database open-source software project sponsored
by Redis Labs. It is networked, in-memory, and stores keys with optional
durability.
The name Redis means REmote DIctionary Server. 

Salvatore Sanfilippo, the original developer of Redis, was hired by
VMware in March, 2010. In May, 2013, Redis was sponsored by Pivotal
Software (a VMware spin-off). In June 2015, development became
sponsored by Redis Labs.
According to monthly rankings by DB-Engines.com, Redis is often ranked
the most popular key-value database. Redis has also been ranked the #4
NoSQL database in user satisfaction and market presence based on
user reviews, the most popular NoSQL database in containers, and the #1
NoSQL database among Top 50 Developer Tools & Services.
Someone defines Redis as “Memcached on Steroids”.
REDIS IN PHP
PRedis [5] is flexible and feature-complete Redis client for PHP and
HHVM by Daniele Alessandri.
[5] https://github.com/nrk/predis
REDIS DATA TYPES:
STRINGS
The Redis String type is the simplest type of value you can associate with
a Redis key. It is the only data type in Memcached, so it is also very
natural for newcomers to use it in Redis.
REDIS DATA TYPES:
STRINGS
The Redis String type is the simplest type of value you can associate with
a Redis key. It is the only data type in Memcached, so it is also very
natural for newcomers to use it in Redis.
If you don’t provide a ttl, the element will be persisted permanenty.
<?php
// Get Connection
$client = new PRedisClient();
// Set a string
$client->set('foo', 'bar', 7200);
$client->set('integer', 12345678, 7200);
$client->set('boolean', true, 7200);
$client->set('array', ['apple', 'banana', 'pear'], 7200);
$client->set('object', serialize(new MyAwesomeClass()), 7200);
// delete a value
$client->del(‘foo’);
// Get a string value
$client->get(‘foo');
REDIS DATA TYPES: LISTS
Redis lists are collections of string elements sorted according to the order
of insertion. They are basically linked lists.
REDIS DATA TYPES: LISTS
Redis lists are collections of string elements sorted according to the order
of insertion. They are basically linked lists.
<?php
// Set a hash
$client->lpush(’buylist’, ’apple');
$client->lpush(’buylist’, ’pie’);
$client->rpush(’buylist’, ’pineapple’);
// Get a string value
$client->lrange(‘buylist’, 0, -1); // [‘pie’, ‘apple’, ‘pineapple’]
// Remove the last two occurrences of ‘apple’ in the list
$client->lrem,(‘buylist’, -2, ’apple');
REDIS DATA TYPES: SETS
Redis Sets are collections of unique, unsorted string elements.
REDIS DATA TYPES: SETS
Redis Sets are collections of unique, unsorted string elements.
<?php
// Create ‘tag:user:1’ a set
$client->sadd(’tags:user:1’, ’apple');
$client->sadd(’tags:user:1’, ’pie');
$client->sadd(’tags:user:1’, ’pineapple’);
// Get a set value
$client->smembers(‘tags:user:1’); // [‘apple’, ‘pie’, ’pineapple’]
$client->srem(’tags:user:1’, ’pineapple’); // removes ‘pineapple’ key
REDIS DATA TYPES: SETS
Redis Sets are collections of unique, unsorted string elements.
<?php
// Create ‘tag:user:1’ a set
$client->sadd(’tags:user:1’, ’apple');
$client->sadd(’tags:user:1’, ’pie');
$client->sadd(’tags:user:1’, ’pineapple’);
// Get a set value
$client->smembers(‘tags:user:1’); // [‘apple’, ‘pie’, ’pineapple’]
$client->srem(’tags:user:1’, ’pineapple’); // removes ‘pineapple’ key
<?php
// Create some set
$client->sadd(’car:make:ford’, ’fiesta');
$client->sadd(’car:make:ford’, ’focus');
$client->sadd(’car:make:maserati’, ’quattroporte’);
// Retrieve all ford molds
$client->smembers(‘car:make:ford’); // [‘fiesta’, ‘focus’]
CREATE AN INDEX
REDIS DATA TYPES:
SORTED SETS
Similar to Sets but where every string element is associated to a floating
number value, called score. The elements are always taken sorted by
their score, so unlike Sets it is possible to retrieve a range of elements
REDIS DATA TYPES:
SORTED SETS
Similar to Sets but where every string element is associated to a floating
number value, called score. The elements are always taken sorted by
their score, so unlike Sets it is possible to retrieve a range of elements
<?php // Create fruits sorted set
$client->zadd(’fruits’, 1, ’apple’);
$client->zadd(’fruits’, 2, ’pie’);
$client->zadd(’fruits’, 2.2, ’pineapple’);
// get fruits sorted set
$client->zrange(‘fruits’, 0, 1, [‘withscores’ => true]);
$client->zrem(’fruits’, ’pineapple’); // removes ‘pineapple’ key
REDIS DATA TYPES:
SORTED SETS
Similar to Sets but where every string element is associated to a floating
number value, called score. The elements are always taken sorted by
their score, so unlike Sets it is possible to retrieve a range of elements
<?php // Create fruits sorted set
$client->zadd(’fruits’, 1, ’apple’);
$client->zadd(’fruits’, 2, ’pie’);
$client->zadd(’fruits’, 2.2, ’pineapple’);
// get fruits sorted set
$client->zrange(‘fruits’, 0, 1, [‘withscores’ => true]);
$client->zrem(’fruits’, ’pineapple’); // removes ‘pineapple’ key
<?php // Create fruits sorted set
$client->zadd(’fruits’, 0, ’apple’);
$client->zadd(’fruits’, 0, ’pie’);
$client->zadd(’fruits’, 0, ’pineapple’);
// Get all fruits sorted set with scores
$client->zrangebylex(‘fruits’, 0, -1, [‘limit’ => [20, 5]]);
LEXICOGRAPHICAL SORTING
REDIS DATA TYPES:
HASHES
Hashes, which are maps composed of fields associated with values.
Both the field and the value are strings
While hashes are handy to represent objects, actually the number of fields
you can put inside a hash has no practical limits (other than available
memory), so you can use hashes in many different ways inside your
application.
REDIS DATA TYPES:
HASHES
Hashes, which are maps composed of fields associated with values.
Both the field and the value are strings
While hashes are handy to represent objects, actually the number of fields
you can put inside a hash has no practical limits (other than available
memory), so you can use hashes in many different ways inside your
application.
<?php
// Set a hash
$client->hset(’user:1’, ’name’, ‘Mauro');
$client->hset(’user:1’, ’surname’, ‘Cassani');
$client->hset(’user:1’, ’email’, ‘mauretto1978@yahoo.it’);
// Get a string value
$client->hget(‘user:1’, ’name’); // Mauro
// Delete hash
$client->hdel(‘user:1’, ’name’); // deletes Mauro
// Get a string value
$client->hgetall(‘user:1’); // full array
REDIS KEYS AND SCANS
➤ KEYS - returns all keys matching pattern.
REDIS KEYS AND SCANS
➤ KEYS - returns all keys matching pattern.
➤ SCAN - iterates the set of keys in the currently selected Redis database.
REDIS KEYS AND SCANS
➤ KEYS - returns all keys matching pattern.
➤ SCAN - iterates the set of keys in the currently selected Redis database.
➤ SSCAN - iterates elements of Sets types.
REDIS KEYS AND SCANS
➤ KEYS - returns all keys matching pattern.
➤ SCAN - iterates the set of keys in the currently selected Redis database.
➤ SSCAN - iterates elements of Sets types.
➤ HSCAN - iterates fields of Hash types and their associated values.
REDIS KEYS AND SCANS
➤ KEYS - returns all keys matching pattern.
➤ SCAN - iterates the set of keys in the currently selected Redis database.
➤ SSCAN - iterates elements of Sets types.
➤ HSCAN - iterates fields of Hash types and their associated values.
➤ ZSCAN - iterates elements of Sorted Set types and their associated scores.
REDIS KEYS AND SCANS
<?php
$client->keys(’user:*’) // Search for all keys starting by user
foreach (new IteratorKeyspace($client, 'predis:*') as $key) { // SCAN
}
foreach (new IteratorSetKey($client, 'predis:set') as $member) { //
SSCAN
}
foreach (new IteratorSortedSetKey($client, 'predis:zset') as $member =>
$rank) { // ZSCAN
}
foreach (new IteratorHashKey($client, 'predis:hset') as $field =>
$value) { // HSCAN
}
➤ KEYS - returns all keys matching pattern.
➤ SCAN - iterates the set of keys in the currently selected Redis database.
➤ SSCAN - iterates elements of Sets types.
➤ HSCAN - iterates fields of Hash types and their associated values.
➤ ZSCAN - iterates elements of Sorted Set types and their associated scores.
BRIEF COMPARISON
APCU MEMCACHED REDIS
documentation + ++ +++
(multi)get ✓ ✓
(multi)set ✓ ✓
incr./decr. ✓ ✓ ✓
delete ✓ ✓ ✓
expiration(ttl) ✓ ✓ ✓
range queries ✓
data types ✓
persistance ✓
BRIEF COMPARISON (2)
APCU MEMCACHED REDIS
clustering ✓ ✓
multi-threaded ✓
replication ✓
key length 256 bytes 512 Mb
max value size 1 Mb 1 Mb 512 Mb
data volume
max size
3.5 TiB 4.7 TiB+
read/write +++ +++ ++
storage type in memory in memory disk + in memory
cli ✓ ✓
REAL WORLD USE CASE
Think on this:
➤ You have some lists coming from your database or your API;
REAL WORLD USE CASE
Think on this:
➤ You have some lists coming from your database or your API;
➤ You want to perform some queries on your lists;
REAL WORLD USE CASE
Think on this:
➤ You have some lists coming from your database or your API;
➤ You want to perform some queries on your lists;
➤ For example, imagine you want to display hundred of POIs in Google
Maps, and allow the user to make some query via a dropdown
menu, or maybe you want to allow your users to perform a simple
text search on your list;
REAL WORLD USE CASE
Think on this:
➤ You have some lists coming from your database or your API;
➤ You want to perform some queries on your lists;
➤ For example, imagine you want to display hundred of POIs in Google
Maps, and allow the user to make some query via a dropdown
menu, or maybe you want to allow your users to perform a simple
text search on your list;
➤ You want your site is super-fast (so you won’t to make more queries on
you db);
REAL WORLD USE CASE
Think on this:
➤ You have some lists coming from your database or your API;
➤ You want to perform some queries on your lists;
➤ For example, imagine you want to display hundred of POIs in Google
Maps, and allow the user to make some query via a dropdown
menu, or maybe you want to allow your users to perform a simple
text search on your list;
➤ You want your site is super-fast (so you won’t to make more queries on
you db);
➤ Of course, you need to cache your data!
REAL WORLD USE CASE
Think on this:
➤ You have some lists coming from your database or your API;
➤ You want to perform some queries on your lists;
➤ For example, imagine you want to display hundred of POIs in Google
Maps, and allow the user to make some query via a dropdown
menu, or maybe you want to allow your users to perform a simple
text search on your list;
➤ You want your site is super-fast (so you won’t to make more queries on
you db);
➤ Of course, you need to cache your data!
HOW TO ACHIEVE IT?
APPROACH “A”
<?php
// With Memcached
if(!$m->get(‘lista')){ // apcu_fetch with APCu
$m->set('lista', $arrayOfElements, $ttl); // apcu_store with APCu
}
foreach ($m->get('lista') as $key => $item){ // apcu_fetch with APCu
$item = unserialize($item); // ...
}
APPROACH “A”
<?php
// With Redis
if(!$c->keys('lista')){
foreach ($arrayOfElements as $item){
$c->hset('lista', $item->{id}, serialize($item));
}
}
foreach ($c->hgetall('lista') as $key => $item){
$item = unserialize($item); // ...
}
<?php
// With Memcached
if(!$m->get(‘lista')){ // apcu_fetch with APCu
$m->set('lista', $arrayOfElements, $ttl); // apcu_store with APCu
}
foreach ($m->get('lista') as $key => $item){ // apcu_fetch with APCu
$item = unserialize($item); // ...
}
APPROACH “B”
<?php // With Memcached
foreach ($originalArray as $element) {
$m->set('lista:'.$element->id, serialize($element), $ttl); // apcu_store
$arrayOfIdElements[(string) $element->id] = 'lista:'.$element->id;
}
$m->set('lista', $arrayOfIdElements, $ttl);
foreach ($m->get('lista') as $key){ // apcu_fetch with APCu
$item = $m->get($key); // ... // apcu_fetch with APCu
}
APPROACH “B”
<?php // With Redis
$list = $c->keys('lista:*');
if(!$list){
foreach ($arrayOfElements as $item){
$c->hset('lista:'.$item->id, 'element', serialize($item));
}
}
foreach ($list as $item) {
$item = unserialize($c->hget($item, 'element'));
}
<?php // With Memcached
foreach ($originalArray as $element) {
$m->set('lista:'.$element->id, serialize($element), $ttl); // apcu_store
$arrayOfIdElements[(string) $element->id] = 'lista:'.$element->id;
}
$m->set('lista', $arrayOfIdElements, $ttl);
foreach ($m->get('lista') as $key){ // apcu_fetch with APCu
$item = $m->get($key); // ... // apcu_fetch with APCu
}
SOLUTION: CHUNK!
<?php // With Memcached
$m->set(‘lista:counter', count($arrayOfElements));
if(!$m->get(‘lista:chunk-1’)){
foreach (array_chunk($arrayOfElements, 1000) as $chunk_number => $item){
$arrayToPersist = [];
foreach ($item as $key => $value){
$arrayToPersist[$key] = $value;
}
$m->set(‘lista:chunk-‘.($chunk_number + 1), $arrayToPersist);
}
}
SOLUTION: CHUNK!
$number = ceil($m->get(‘lista:counter') / 1000);
$list = [];
for ($i=1; $i<=$number; $i++){
if(empty($list)){
$list = $m->get(‘lista:chunk-1’);
} else {
$list = array_merge($collection, $m->get(‘lista:chunk-'.$i));
}
}
foreach ($list as $key => $item){
// ...
}
<?php // With Memcached
$m->set(‘lista:counter', count($arrayOfElements));
if(!$m->get(‘lista:chunk-1’)){
foreach (array_chunk($arrayOfElements, 1000) as $chunk_number => $item){
$arrayToPersist = [];
foreach ($item as $key => $value){
$arrayToPersist[$key] = $value;
}
$m->set(‘lista:chunk-‘.($chunk_number + 1), $arrayToPersist);
}
}
SOLUTION: CHUNK! (2)
<?php // With Redis
$c->set(‘lista:counter', count($arrayOfElements));
if(!$c->hgetall(‘lista:chunk-1’)){
foreach (array_chunk($arrayOfElements, 1000) as $chunk_number =>
$item){
foreach ($item as $key => $value){
$c->hset(‘lista:chunk-‘.($chunk_number+1), $key, $value);
}
}
SOLUTION: CHUNK! (2)
<?php // With Redis
$c->set(‘lista:counter', count($arrayOfElements));
if(!$c->hgetall(‘lista:chunk-1’)){
foreach (array_chunk($arrayOfElements, 1000) as $chunk_number =>
$item){
foreach ($item as $key => $value){
$c->hset(‘lista:chunk-‘.($chunk_number+1), $key, $value);
}
}
$number = ceil($c->get(‘lista:counter') / 1000);
$list = [];
for ($i=1; $i<=$number; $i++){
if(empty($list)){
$list = $c->hgetall(‘lista:chunk-1');
} else {
$list = array_merge($collection, $c->hgetall(‘lista:chunk-'.
$i));
}
}
foreach ($list as $key => $item){
// ...
}
IN-MEMORY LIST
In-memory List [6] is a PHP library that allows you to create and store in
memory your lists, and then quickly retrieve and perform queries on it.
[6] https://github.com/mauretto78/in-memory-list
ARCHITECTURE
Domain
Entities + Factory
Client + QB
ARCHITECTURE
Domain
InfrastructureEntities + Factory
Client + QB
Repo + Drivers
ARCHITECTURE
Domain
Infrastructure
Application
Entities + Factory
Client + QB
Repo + Drivers
DOMAIN MODEL
ListCollection
$items
$uuid
$headers
ListCollectionUuid
$uuid
Here is the UML Diagram of Domain Modal:
ListElement
$uuid
$body
ListElementUuid
$uuid
BASIC USAGE
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array);
BASIC USAGE
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array);
foreach ($collection as $element){
$item = $client->item($element);
// ...
}
Now you can iterate over all elements:
DRIVERS
<?php
use InMemoryListApplicationClient;
$client = new Client('apcu'); // Apcu
You can use APCU, Memcached or Redis:
DRIVERS
<?php
use InMemoryListApplicationClient;
$client = new Client('apcu'); // Apcu
$client = new Client('memcached', $memcached_params); // Memcached
You can use APCU, Memcached or Redis:
DRIVERS
$client = new Client('redis', $redis_params); // Redis
<?php
use InMemoryListApplicationClient;
$client = new Client('apcu'); // Apcu
$client = new Client('memcached', $memcached_params); // Memcached
You can use APCU, Memcached or Redis:
PARAMETERS
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
➤ uuid - uuid of list
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
➤ uuid - uuid of list
➤ element-uuid - uuid for the list elements
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
➤ uuid - uuid of list
➤ element-uuid - uuid for the list elements
➤ headers - headers array for the list
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
➤ uuid - uuid of list
➤ element-uuid - uuid for the list elements
➤ headers - headers array for the list
➤ index - add the list elements to cache index or not
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
➤ uuid - uuid of list
➤ element-uuid - uuid for the list elements
➤ headers - headers array for the list
➤ index - add the list elements to cache index or not
➤ chunk-size - the chunks size in which the array will be splitted
(integer)
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
PARAMETERS
When use create method to generate a list, you can provide to it a
parameters array. The allowed keys are:
➤ uuid - uuid of list
➤ element-uuid - uuid for the list elements
➤ headers - headers array for the list
➤ index - add the list elements to cache index or not
➤ chunk-size - the chunks size in which the array will be splitted
(integer)
➤ ttl - time to live of the list (in seconds)
<?php
use InMemoryListApplicationClient;
$array = [...];
$client = new Client();
$collection = $client->create($array, $parameters);
QUERIES
<?php
use InMemoryListApplicationClient;
use InMemoryListApplicationQueryBuilder;
$array = [...];
$client = new Client();
$collection = $client->create($array, [‘uuid' => 'simple-array']);
$qb = new QueryBuilder($collection);
$qb
->addCriteria('title', 'Mario', 'CONTAINS')
->addCriteria('group_id', '45')
->addCriteria('rate', '3', '>')
->orderBy(‘title')
->limit(30);
foreach ($qb->getResults() as $element){
$item = $client->item($element);
// ...
}
A SIMPLE BENCHMARK
<?php
$start = microtime(true);
foreach (range($from, $to) as $number) {
$array[] = [
'id' => $number,
'name' => 'Name '.$number,
'email' => 'Email'.$number,
];
}
$apiArray = json_encode($array);
$client = new Client($driver, $params);
$collection = $client->findListByUuid('range-list') ?: $client-
>create(json_decode($apiArray), [‘uuid' => 'range-list', 

‘element-uuid’ => 'id']);
foreach ($collection as $element) {
$item = $client->item($element);
echo '<strong>id</strong>: '.$item->id.'<br>';
echo '<strong>name</strong>: '.$item->name.'<br>';
echo '<strong>email</strong>: '.$item->email.'<br>';
}
echo ' ELAPSED TIME: '.$time_elapsed_secs = microtime(true) - $start;
BENCHMARK RESULTS
seconds
0
0.75
1.5
2.25
3
number of items
5000 10000 20000 30000 40000 50000
var_dump (Redis) echo (Redis) var_dump (MC)
echo (MC) var_dump (Apcu) echo (Apcu)
FINAL RECAP: WHO WINS?
Small Projects No great differences
High traffic websites ✓ Memcached
Real-time applications, 

secondary database persist
✓ Redis
THANK YOU!
ANY QUESTIONS?

Caching objects-in-memory

  • 1.
  • 2.
    IN-MEMORY CACHING OBJECTS TECHNIQUES MauroCassani, PUG ROMA 30th May, 2017
  • 3.
  • 4.
    WHAT IS CACHE? Incomputing, a cache, is a hardware or software component that stores data so future requests for that data can be served faster; the data stored in a cache might be the result of an earlier computation, or the duplicate of data stored elsewhere.[1] “ “ [1] https://en.wikipedia.org/wiki/Cache_(computing)
  • 5.
    CACHING TECHNIQUES There aredifferent caching methods that we can use with PHP: ➤ Caching content
 We can cache content in PHP by saving the final output of a specific script into the filesystem then simply serving it like a static file for a specific period of time instead of executing the original script.
  • 6.
    CACHING TECHNIQUES There aredifferent caching methods that we can use with PHP: ➤ Caching content
 We can cache content in PHP by saving the final output of a specific script into the filesystem then simply serving it like a static file for a specific period of time instead of executing the original script. ➤ Database Cache
 Caching the caching is done by the database server itself. This works by caching the results of the query so the query is only parsed the first time it runs and in the succeeding requests it won’t be parsed since the results from the specific query is already cached by the database server.
  • 7.
    CACHING TECHNIQUES There aredifferent caching methods that we can use with PHP: ➤ Caching content
 We can cache content in PHP by saving the final output of a specific script into the filesystem then simply serving it like a static file for a specific period of time instead of executing the original script. ➤ Database Cache
 Caching the caching is done by the database server itself. This works by caching the results of the query so the query is only parsed the first time it runs and in the succeeding requests it won’t be parsed since the results from the specific query is already cached by the database server. ➤ Memory Cache
 Memory caching techniques are widely used; they use the volatile memory data and are a lot more faster than caching in the file system.
  • 8.
    MEMORY CACHING Memory cachingtechniques are widely used; they use the volatile memory data and are a lot more faster than caching in the file system. ➤ APCU [2]
 Alternative PHP Cache User Cache (APCU) provides a full backwards compatible API to the shared memory userland cache provided by APC. [2] http://php.net/manual/en/intro.apcu.php
  • 9.
    MEMORY CACHING Memory cachingtechniques are widely used; they use the volatile memory data and are a lot more faster than caching in the file system. ➤ APCU [2]
 Alternative PHP Cache User Cache (APCU) provides a full backwards compatible API to the shared memory userland cache provided by APC. ➤ MEMCACHED [3]
 Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering. [2] http://php.net/manual/en/intro.apcu.php
 [3] https://memcached.org/
  • 10.
    MEMORY CACHING Memory cachingtechniques are widely used; they use the volatile memory data and are a lot more faster than caching in the file system. ➤ APCU [2]
 Alternative PHP Cache User Cache (APCU) provides a full backwards compatible API to the shared memory userland cache provided by APC. ➤ MEMCACHED [3]
 Memcached is an in-memory key-value store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, or page rendering. ➤ REDIS [4]
 Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. [2] http://php.net/manual/en/intro.apcu.php
 [3] https://memcached.org/
 [4] https://redis.io/
  • 11.
    APCU APCu (APC UserCache) is APC stripped of opcode caching. The first APCu codebase was versioned 4.0.0, it was forked from the head of the APC master branch at the time. PHP 7 support is available as of APCu 5.0.0. APCu can provide a compatibility mode, such that it can provide a drop in replacement for the applicable parts of APC.
  • 12.
    APCU IN PHP <?php //Set a value apcu_store('foo', 'bar', 7200); apcu_store('integer', 12345678, 7200); apcu_store('boolean', true, 7200); apcu_store('array', ['apple', 'banana', 'pear'], 7200); apcu_store('object', serialize(new MyAwesomeClass()), 7200); // Get a value apcu_fetch(‘foo’); // Delete a value apcu_delete(‘foo’); // Flush the cache apcu_clear_cache();
  • 13.
    APCU IN PHP(2) <?php //.. $myCacheKey = 'my_cache_key'; $row = apcu_fetch($myCacheKey); if (!$row) { // Issue painful query to mysql $sql = "SELECT * FROM table WHERE id = :id"; $dbo->prepare($sql); $stmt->bindValue(':id', $someId, PDO::PARAM_INT); $row = $stmt->fetch(PDO::FETCH_OBJ); apcu_store($myCacheKey, serialize($row)); } // Now I have access to $row, where I can do what I need to // And for subsequent calls, the data will be pulled from cache and skip // the query altogether var_dump(unserialize($row));
  • 14.
    MEMCACHED Memcached is adistributed caching system in RAM for objects, and is widely used in dynamic web applications to relieve the load on the database, making it possible to serve some of the data to which access is most frequent, directly from RAM memory .
  • 15.
    MEMCACHED Memcached is adistributed caching system in RAM for objects, and is widely used in dynamic web applications to relieve the load on the database, making it possible to serve some of the data to which access is most frequent, directly from RAM memory . Memcached was created in 2003 by the company operating LiveJournal, Danga Interactive, which had to handle more than 20 million exponential dynamic daily requests. The adoption of this innovative caching system has made it possible to drastically reduce the load on database servers and significantly improve site performance.
  • 16.
    MEMCACHED Memcached is adistributed caching system in RAM for objects, and is widely used in dynamic web applications to relieve the load on the database, making it possible to serve some of the data to which access is most frequent, directly from RAM memory . Memcached was created in 2003 by the company operating LiveJournal, Danga Interactive, which had to handle more than 20 million exponential dynamic daily requests. The adoption of this innovative caching system has made it possible to drastically reduce the load on database servers and significantly improve site performance. The software was then publicly released under the BSD license that allowed it to be implemented by other web giants and the inevitable addition of many features and constant performance enhancement. Among the most famous memcached users we find informatics giants such as WordPress, Wikipedia, Flickr, Twitter, YouTube, Digg and Facebook.
  • 17.
    MEMCACHED IN PHP <?php //Get Connection $memcached = new Memcached(); $memcached->addServer('localhost', 11211); // Set a value $memcached->set('foo', 'bar', 7200); $memcached->set('integer', 12345678, 7200); $memcached->set('boolean', true, 7200); $memcached->set('array', ['apple', 'banana', 'pear'], 7200); $memcached->set('object', serialize(new MyAwesomeClass()), 7200); // Get a value $memcached->get(‘foo'); // Update a value $memcached->replace('foo', 'barbar', 10200); // Change TTL $memcached->touch('foo', 29000); // Delete a value $memcached->delete('foo'); // Flush the cache $memcached->flush();
  • 18.
    MEMCACHED IN PHP(2) <?php //.. $memcached = new Memcached(); $memcached->addServer('localhost', 11211); $myCacheKey = 'my_cache_key'; $row = $cache->get($myCacheKey); if (!$row) { // Issue painful query to mysql $sql = "SELECT * FROM table WHERE id = :id"; $dbo->prepare($sql); $stmt->bindValue(':id', $someId, PDO::PARAM_INT); $row = $stmt->fetch(PDO::FETCH_OBJ); $memcached->set($myCacheKey, serialize($row)); } // Now I have access to $row, where I can do what I need to // And for subsequent calls, the data will be pulled from cache and skip // the query altogether var_dump(unserialize($row));
  • 19.
    REDIS Redis is anin-memory database open-source software project sponsored by Redis Labs. It is networked, in-memory, and stores keys with optional durability.
  • 20.
    REDIS Redis is anin-memory database open-source software project sponsored by Redis Labs. It is networked, in-memory, and stores keys with optional durability. The name Redis means REmote DIctionary Server. 
 Salvatore Sanfilippo, the original developer of Redis, was hired by VMware in March, 2010. In May, 2013, Redis was sponsored by Pivotal Software (a VMware spin-off). In June 2015, development became sponsored by Redis Labs.
  • 21.
    REDIS Redis is anin-memory database open-source software project sponsored by Redis Labs. It is networked, in-memory, and stores keys with optional durability. The name Redis means REmote DIctionary Server. 
 Salvatore Sanfilippo, the original developer of Redis, was hired by VMware in March, 2010. In May, 2013, Redis was sponsored by Pivotal Software (a VMware spin-off). In June 2015, development became sponsored by Redis Labs. According to monthly rankings by DB-Engines.com, Redis is often ranked the most popular key-value database. Redis has also been ranked the #4 NoSQL database in user satisfaction and market presence based on user reviews, the most popular NoSQL database in containers, and the #1 NoSQL database among Top 50 Developer Tools & Services.
  • 22.
    REDIS Redis is anin-memory database open-source software project sponsored by Redis Labs. It is networked, in-memory, and stores keys with optional durability. The name Redis means REmote DIctionary Server. 
 Salvatore Sanfilippo, the original developer of Redis, was hired by VMware in March, 2010. In May, 2013, Redis was sponsored by Pivotal Software (a VMware spin-off). In June 2015, development became sponsored by Redis Labs. According to monthly rankings by DB-Engines.com, Redis is often ranked the most popular key-value database. Redis has also been ranked the #4 NoSQL database in user satisfaction and market presence based on user reviews, the most popular NoSQL database in containers, and the #1 NoSQL database among Top 50 Developer Tools & Services. Someone defines Redis as “Memcached on Steroids”.
  • 23.
    REDIS IN PHP PRedis[5] is flexible and feature-complete Redis client for PHP and HHVM by Daniele Alessandri. [5] https://github.com/nrk/predis
  • 24.
    REDIS DATA TYPES: STRINGS TheRedis String type is the simplest type of value you can associate with a Redis key. It is the only data type in Memcached, so it is also very natural for newcomers to use it in Redis.
  • 25.
    REDIS DATA TYPES: STRINGS TheRedis String type is the simplest type of value you can associate with a Redis key. It is the only data type in Memcached, so it is also very natural for newcomers to use it in Redis. If you don’t provide a ttl, the element will be persisted permanenty. <?php // Get Connection $client = new PRedisClient(); // Set a string $client->set('foo', 'bar', 7200); $client->set('integer', 12345678, 7200); $client->set('boolean', true, 7200); $client->set('array', ['apple', 'banana', 'pear'], 7200); $client->set('object', serialize(new MyAwesomeClass()), 7200); // delete a value $client->del(‘foo’); // Get a string value $client->get(‘foo');
  • 26.
    REDIS DATA TYPES:LISTS Redis lists are collections of string elements sorted according to the order of insertion. They are basically linked lists.
  • 27.
    REDIS DATA TYPES:LISTS Redis lists are collections of string elements sorted according to the order of insertion. They are basically linked lists. <?php // Set a hash $client->lpush(’buylist’, ’apple'); $client->lpush(’buylist’, ’pie’); $client->rpush(’buylist’, ’pineapple’); // Get a string value $client->lrange(‘buylist’, 0, -1); // [‘pie’, ‘apple’, ‘pineapple’] // Remove the last two occurrences of ‘apple’ in the list $client->lrem,(‘buylist’, -2, ’apple');
  • 28.
    REDIS DATA TYPES:SETS Redis Sets are collections of unique, unsorted string elements.
  • 29.
    REDIS DATA TYPES:SETS Redis Sets are collections of unique, unsorted string elements. <?php // Create ‘tag:user:1’ a set $client->sadd(’tags:user:1’, ’apple'); $client->sadd(’tags:user:1’, ’pie'); $client->sadd(’tags:user:1’, ’pineapple’); // Get a set value $client->smembers(‘tags:user:1’); // [‘apple’, ‘pie’, ’pineapple’] $client->srem(’tags:user:1’, ’pineapple’); // removes ‘pineapple’ key
  • 30.
    REDIS DATA TYPES:SETS Redis Sets are collections of unique, unsorted string elements. <?php // Create ‘tag:user:1’ a set $client->sadd(’tags:user:1’, ’apple'); $client->sadd(’tags:user:1’, ’pie'); $client->sadd(’tags:user:1’, ’pineapple’); // Get a set value $client->smembers(‘tags:user:1’); // [‘apple’, ‘pie’, ’pineapple’] $client->srem(’tags:user:1’, ’pineapple’); // removes ‘pineapple’ key <?php // Create some set $client->sadd(’car:make:ford’, ’fiesta'); $client->sadd(’car:make:ford’, ’focus'); $client->sadd(’car:make:maserati’, ’quattroporte’); // Retrieve all ford molds $client->smembers(‘car:make:ford’); // [‘fiesta’, ‘focus’] CREATE AN INDEX
  • 31.
    REDIS DATA TYPES: SORTEDSETS Similar to Sets but where every string element is associated to a floating number value, called score. The elements are always taken sorted by their score, so unlike Sets it is possible to retrieve a range of elements
  • 32.
    REDIS DATA TYPES: SORTEDSETS Similar to Sets but where every string element is associated to a floating number value, called score. The elements are always taken sorted by their score, so unlike Sets it is possible to retrieve a range of elements <?php // Create fruits sorted set $client->zadd(’fruits’, 1, ’apple’); $client->zadd(’fruits’, 2, ’pie’); $client->zadd(’fruits’, 2.2, ’pineapple’); // get fruits sorted set $client->zrange(‘fruits’, 0, 1, [‘withscores’ => true]); $client->zrem(’fruits’, ’pineapple’); // removes ‘pineapple’ key
  • 33.
    REDIS DATA TYPES: SORTEDSETS Similar to Sets but where every string element is associated to a floating number value, called score. The elements are always taken sorted by their score, so unlike Sets it is possible to retrieve a range of elements <?php // Create fruits sorted set $client->zadd(’fruits’, 1, ’apple’); $client->zadd(’fruits’, 2, ’pie’); $client->zadd(’fruits’, 2.2, ’pineapple’); // get fruits sorted set $client->zrange(‘fruits’, 0, 1, [‘withscores’ => true]); $client->zrem(’fruits’, ’pineapple’); // removes ‘pineapple’ key <?php // Create fruits sorted set $client->zadd(’fruits’, 0, ’apple’); $client->zadd(’fruits’, 0, ’pie’); $client->zadd(’fruits’, 0, ’pineapple’); // Get all fruits sorted set with scores $client->zrangebylex(‘fruits’, 0, -1, [‘limit’ => [20, 5]]); LEXICOGRAPHICAL SORTING
  • 34.
    REDIS DATA TYPES: HASHES Hashes,which are maps composed of fields associated with values. Both the field and the value are strings While hashes are handy to represent objects, actually the number of fields you can put inside a hash has no practical limits (other than available memory), so you can use hashes in many different ways inside your application.
  • 35.
    REDIS DATA TYPES: HASHES Hashes,which are maps composed of fields associated with values. Both the field and the value are strings While hashes are handy to represent objects, actually the number of fields you can put inside a hash has no practical limits (other than available memory), so you can use hashes in many different ways inside your application. <?php // Set a hash $client->hset(’user:1’, ’name’, ‘Mauro'); $client->hset(’user:1’, ’surname’, ‘Cassani'); $client->hset(’user:1’, ’email’, ‘mauretto1978@yahoo.it’); // Get a string value $client->hget(‘user:1’, ’name’); // Mauro // Delete hash $client->hdel(‘user:1’, ’name’); // deletes Mauro // Get a string value $client->hgetall(‘user:1’); // full array
  • 36.
    REDIS KEYS ANDSCANS ➤ KEYS - returns all keys matching pattern.
  • 37.
    REDIS KEYS ANDSCANS ➤ KEYS - returns all keys matching pattern. ➤ SCAN - iterates the set of keys in the currently selected Redis database.
  • 38.
    REDIS KEYS ANDSCANS ➤ KEYS - returns all keys matching pattern. ➤ SCAN - iterates the set of keys in the currently selected Redis database. ➤ SSCAN - iterates elements of Sets types.
  • 39.
    REDIS KEYS ANDSCANS ➤ KEYS - returns all keys matching pattern. ➤ SCAN - iterates the set of keys in the currently selected Redis database. ➤ SSCAN - iterates elements of Sets types. ➤ HSCAN - iterates fields of Hash types and their associated values.
  • 40.
    REDIS KEYS ANDSCANS ➤ KEYS - returns all keys matching pattern. ➤ SCAN - iterates the set of keys in the currently selected Redis database. ➤ SSCAN - iterates elements of Sets types. ➤ HSCAN - iterates fields of Hash types and their associated values. ➤ ZSCAN - iterates elements of Sorted Set types and their associated scores.
  • 41.
    REDIS KEYS ANDSCANS <?php $client->keys(’user:*’) // Search for all keys starting by user foreach (new IteratorKeyspace($client, 'predis:*') as $key) { // SCAN } foreach (new IteratorSetKey($client, 'predis:set') as $member) { // SSCAN } foreach (new IteratorSortedSetKey($client, 'predis:zset') as $member => $rank) { // ZSCAN } foreach (new IteratorHashKey($client, 'predis:hset') as $field => $value) { // HSCAN } ➤ KEYS - returns all keys matching pattern. ➤ SCAN - iterates the set of keys in the currently selected Redis database. ➤ SSCAN - iterates elements of Sets types. ➤ HSCAN - iterates fields of Hash types and their associated values. ➤ ZSCAN - iterates elements of Sorted Set types and their associated scores.
  • 42.
    BRIEF COMPARISON APCU MEMCACHEDREDIS documentation + ++ +++ (multi)get ✓ ✓ (multi)set ✓ ✓ incr./decr. ✓ ✓ ✓ delete ✓ ✓ ✓ expiration(ttl) ✓ ✓ ✓ range queries ✓ data types ✓ persistance ✓
  • 43.
    BRIEF COMPARISON (2) APCUMEMCACHED REDIS clustering ✓ ✓ multi-threaded ✓ replication ✓ key length 256 bytes 512 Mb max value size 1 Mb 1 Mb 512 Mb data volume max size 3.5 TiB 4.7 TiB+ read/write +++ +++ ++ storage type in memory in memory disk + in memory cli ✓ ✓
  • 44.
    REAL WORLD USECASE Think on this: ➤ You have some lists coming from your database or your API;
  • 45.
    REAL WORLD USECASE Think on this: ➤ You have some lists coming from your database or your API; ➤ You want to perform some queries on your lists;
  • 46.
    REAL WORLD USECASE Think on this: ➤ You have some lists coming from your database or your API; ➤ You want to perform some queries on your lists; ➤ For example, imagine you want to display hundred of POIs in Google Maps, and allow the user to make some query via a dropdown menu, or maybe you want to allow your users to perform a simple text search on your list;
  • 47.
    REAL WORLD USECASE Think on this: ➤ You have some lists coming from your database or your API; ➤ You want to perform some queries on your lists; ➤ For example, imagine you want to display hundred of POIs in Google Maps, and allow the user to make some query via a dropdown menu, or maybe you want to allow your users to perform a simple text search on your list; ➤ You want your site is super-fast (so you won’t to make more queries on you db);
  • 48.
    REAL WORLD USECASE Think on this: ➤ You have some lists coming from your database or your API; ➤ You want to perform some queries on your lists; ➤ For example, imagine you want to display hundred of POIs in Google Maps, and allow the user to make some query via a dropdown menu, or maybe you want to allow your users to perform a simple text search on your list; ➤ You want your site is super-fast (so you won’t to make more queries on you db); ➤ Of course, you need to cache your data!
  • 49.
    REAL WORLD USECASE Think on this: ➤ You have some lists coming from your database or your API; ➤ You want to perform some queries on your lists; ➤ For example, imagine you want to display hundred of POIs in Google Maps, and allow the user to make some query via a dropdown menu, or maybe you want to allow your users to perform a simple text search on your list; ➤ You want your site is super-fast (so you won’t to make more queries on you db); ➤ Of course, you need to cache your data! HOW TO ACHIEVE IT?
  • 50.
    APPROACH “A” <?php // WithMemcached if(!$m->get(‘lista')){ // apcu_fetch with APCu $m->set('lista', $arrayOfElements, $ttl); // apcu_store with APCu } foreach ($m->get('lista') as $key => $item){ // apcu_fetch with APCu $item = unserialize($item); // ... }
  • 51.
    APPROACH “A” <?php // WithRedis if(!$c->keys('lista')){ foreach ($arrayOfElements as $item){ $c->hset('lista', $item->{id}, serialize($item)); } } foreach ($c->hgetall('lista') as $key => $item){ $item = unserialize($item); // ... } <?php // With Memcached if(!$m->get(‘lista')){ // apcu_fetch with APCu $m->set('lista', $arrayOfElements, $ttl); // apcu_store with APCu } foreach ($m->get('lista') as $key => $item){ // apcu_fetch with APCu $item = unserialize($item); // ... }
  • 52.
    APPROACH “B” <?php //With Memcached foreach ($originalArray as $element) { $m->set('lista:'.$element->id, serialize($element), $ttl); // apcu_store $arrayOfIdElements[(string) $element->id] = 'lista:'.$element->id; } $m->set('lista', $arrayOfIdElements, $ttl); foreach ($m->get('lista') as $key){ // apcu_fetch with APCu $item = $m->get($key); // ... // apcu_fetch with APCu }
  • 53.
    APPROACH “B” <?php //With Redis $list = $c->keys('lista:*'); if(!$list){ foreach ($arrayOfElements as $item){ $c->hset('lista:'.$item->id, 'element', serialize($item)); } } foreach ($list as $item) { $item = unserialize($c->hget($item, 'element')); } <?php // With Memcached foreach ($originalArray as $element) { $m->set('lista:'.$element->id, serialize($element), $ttl); // apcu_store $arrayOfIdElements[(string) $element->id] = 'lista:'.$element->id; } $m->set('lista', $arrayOfIdElements, $ttl); foreach ($m->get('lista') as $key){ // apcu_fetch with APCu $item = $m->get($key); // ... // apcu_fetch with APCu }
  • 54.
    SOLUTION: CHUNK! <?php //With Memcached $m->set(‘lista:counter', count($arrayOfElements)); if(!$m->get(‘lista:chunk-1’)){ foreach (array_chunk($arrayOfElements, 1000) as $chunk_number => $item){ $arrayToPersist = []; foreach ($item as $key => $value){ $arrayToPersist[$key] = $value; } $m->set(‘lista:chunk-‘.($chunk_number + 1), $arrayToPersist); } }
  • 55.
    SOLUTION: CHUNK! $number =ceil($m->get(‘lista:counter') / 1000); $list = []; for ($i=1; $i<=$number; $i++){ if(empty($list)){ $list = $m->get(‘lista:chunk-1’); } else { $list = array_merge($collection, $m->get(‘lista:chunk-'.$i)); } } foreach ($list as $key => $item){ // ... } <?php // With Memcached $m->set(‘lista:counter', count($arrayOfElements)); if(!$m->get(‘lista:chunk-1’)){ foreach (array_chunk($arrayOfElements, 1000) as $chunk_number => $item){ $arrayToPersist = []; foreach ($item as $key => $value){ $arrayToPersist[$key] = $value; } $m->set(‘lista:chunk-‘.($chunk_number + 1), $arrayToPersist); } }
  • 56.
    SOLUTION: CHUNK! (2) <?php// With Redis $c->set(‘lista:counter', count($arrayOfElements)); if(!$c->hgetall(‘lista:chunk-1’)){ foreach (array_chunk($arrayOfElements, 1000) as $chunk_number => $item){ foreach ($item as $key => $value){ $c->hset(‘lista:chunk-‘.($chunk_number+1), $key, $value); } }
  • 57.
    SOLUTION: CHUNK! (2) <?php// With Redis $c->set(‘lista:counter', count($arrayOfElements)); if(!$c->hgetall(‘lista:chunk-1’)){ foreach (array_chunk($arrayOfElements, 1000) as $chunk_number => $item){ foreach ($item as $key => $value){ $c->hset(‘lista:chunk-‘.($chunk_number+1), $key, $value); } } $number = ceil($c->get(‘lista:counter') / 1000); $list = []; for ($i=1; $i<=$number; $i++){ if(empty($list)){ $list = $c->hgetall(‘lista:chunk-1'); } else { $list = array_merge($collection, $c->hgetall(‘lista:chunk-'. $i)); } } foreach ($list as $key => $item){ // ... }
  • 58.
    IN-MEMORY LIST In-memory List[6] is a PHP library that allows you to create and store in memory your lists, and then quickly retrieve and perform queries on it. [6] https://github.com/mauretto78/in-memory-list
  • 59.
  • 60.
  • 61.
  • 62.
    DOMAIN MODEL ListCollection $items $uuid $headers ListCollectionUuid $uuid Here isthe UML Diagram of Domain Modal: ListElement $uuid $body ListElementUuid $uuid
  • 63.
    BASIC USAGE <?php use InMemoryListApplicationClient; $array= [...]; $client = new Client(); $collection = $client->create($array);
  • 64.
    BASIC USAGE <?php use InMemoryListApplicationClient; $array= [...]; $client = new Client(); $collection = $client->create($array); foreach ($collection as $element){ $item = $client->item($element); // ... } Now you can iterate over all elements:
  • 65.
    DRIVERS <?php use InMemoryListApplicationClient; $client =new Client('apcu'); // Apcu You can use APCU, Memcached or Redis:
  • 66.
    DRIVERS <?php use InMemoryListApplicationClient; $client =new Client('apcu'); // Apcu $client = new Client('memcached', $memcached_params); // Memcached You can use APCU, Memcached or Redis:
  • 67.
    DRIVERS $client = newClient('redis', $redis_params); // Redis <?php use InMemoryListApplicationClient; $client = new Client('apcu'); // Apcu $client = new Client('memcached', $memcached_params); // Memcached You can use APCU, Memcached or Redis:
  • 68.
    PARAMETERS <?php use InMemoryListApplicationClient; $array =[...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 69.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 70.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: ➤ uuid - uuid of list <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 71.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: ➤ uuid - uuid of list ➤ element-uuid - uuid for the list elements <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 72.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: ➤ uuid - uuid of list ➤ element-uuid - uuid for the list elements ➤ headers - headers array for the list <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 73.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: ➤ uuid - uuid of list ➤ element-uuid - uuid for the list elements ➤ headers - headers array for the list ➤ index - add the list elements to cache index or not <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 74.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: ➤ uuid - uuid of list ➤ element-uuid - uuid for the list elements ➤ headers - headers array for the list ➤ index - add the list elements to cache index or not ➤ chunk-size - the chunks size in which the array will be splitted (integer) <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 75.
    PARAMETERS When use createmethod to generate a list, you can provide to it a parameters array. The allowed keys are: ➤ uuid - uuid of list ➤ element-uuid - uuid for the list elements ➤ headers - headers array for the list ➤ index - add the list elements to cache index or not ➤ chunk-size - the chunks size in which the array will be splitted (integer) ➤ ttl - time to live of the list (in seconds) <?php use InMemoryListApplicationClient; $array = [...]; $client = new Client(); $collection = $client->create($array, $parameters);
  • 76.
    QUERIES <?php use InMemoryListApplicationClient; use InMemoryListApplicationQueryBuilder; $array= [...]; $client = new Client(); $collection = $client->create($array, [‘uuid' => 'simple-array']); $qb = new QueryBuilder($collection); $qb ->addCriteria('title', 'Mario', 'CONTAINS') ->addCriteria('group_id', '45') ->addCriteria('rate', '3', '>') ->orderBy(‘title') ->limit(30); foreach ($qb->getResults() as $element){ $item = $client->item($element); // ... }
  • 77.
    A SIMPLE BENCHMARK <?php $start= microtime(true); foreach (range($from, $to) as $number) { $array[] = [ 'id' => $number, 'name' => 'Name '.$number, 'email' => 'Email'.$number, ]; } $apiArray = json_encode($array); $client = new Client($driver, $params); $collection = $client->findListByUuid('range-list') ?: $client- >create(json_decode($apiArray), [‘uuid' => 'range-list', 
 ‘element-uuid’ => 'id']); foreach ($collection as $element) { $item = $client->item($element); echo '<strong>id</strong>: '.$item->id.'<br>'; echo '<strong>name</strong>: '.$item->name.'<br>'; echo '<strong>email</strong>: '.$item->email.'<br>'; } echo ' ELAPSED TIME: '.$time_elapsed_secs = microtime(true) - $start;
  • 78.
    BENCHMARK RESULTS seconds 0 0.75 1.5 2.25 3 number ofitems 5000 10000 20000 30000 40000 50000 var_dump (Redis) echo (Redis) var_dump (MC) echo (MC) var_dump (Apcu) echo (Apcu)
  • 79.
    FINAL RECAP: WHOWINS? Small Projects No great differences High traffic websites ✓ Memcached Real-time applications, 
 secondary database persist ✓ Redis
  • 80.