Cakefest 2015
New York, NY
@dchancogne
![](https://pbs.twimg.com/profile_images/2678827459/a1d9ca2d94e329636cc753133b98525a.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/dchancogne/images/856233/T_Logo.png)
TR
CKR
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383667/Screen_Shot_2015-05-15_at_3.59.10_PM.png)
TR
CKR
![](http://ecx.images-amazon.com/images/I/51yMzuNROjL._SY344_BO1,204,203,200_.jpg)
Custom Cache
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
Custom Cache
Redis Cache
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
![](http://png-2.findicons.com/files/icons/2773/pictonic_free/512/dbs_redis.png)
Custom Cache
Redis Cache
Fallback Cache
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
![](http://png-2.findicons.com/files/icons/2773/pictonic_free/512/dbs_redis.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
traackr/cakephp-cache-engines
![](https://cdn0.iconfinder.com/data/icons/octicons/1024/git-branch-512.png)
dvlp
packages/traackr/cache-engines
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1432927/logo-composer-transparent-black.png)
![](https://cdn0.iconfinder.com/data/icons/octicons/1024/git-branch-512.png)
cake3
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
CUSTOM
CACHE ENGINE
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
![](https://cdn0.iconfinder.com/data/icons/huge-black-icons/512/Options.png)
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
class
CacheEngine
class CustomCacheEngine
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
class Cake\Cache\
CacheEngine
class CustomCacheEngine
CakePHP 3.0
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
write
($key,$value)
read
increment
::
($key)
($key,$offset=1)
::
::
delete
($key)
::
decrement
($key,$offset=1)
::
clear
($check)
::
clearGroup
($group)
::
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
key
($key)
::
Project Name
project_name
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
init
($config=array())
::
/**
* Initialize the cache engine
*
* Called automatically by the cache frontend.
* Merge the runtime config with the defaults
* before use.
*
* @param array $config Associative array of parameters
* for the engine
* @return bool True if the engine has been successfully
* initialized, false if not
*/
init
($config=array())
::
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
![](http://www.creawavestudio.com/www/static/website/img/gear.png)
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
Plugin/<plugin-name>
composer/installers
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1432927/logo-composer-transparent-black.png)
+
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
vendor/<vendor>/<plugin>
cakephp/plugin-installer
CakePHP 3.0
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1432927/logo-composer-transparent-black.png)
+
![](http://www.aparajayah.com/img/staticpage/small/51dd5de9-62e4-49f6-9e71-36c7d8acb077.png)
Recap
![](https://cdn0.iconfinder.com/data/icons/huge-black-icons/512/Options.png)
![](http://www.creawavestudio.com/www/static/website/img/gear.png)
Extend CacheEngine class
Implement init() & key()
Install as plugin
A Redis
Cache Engine
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
Cache
Invalidation
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
project:<id>:<data>
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
PROJECT
123
456
META
ASSETS
USERS
/
\
/
\
/
\
|
|
...
...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
project : 123 : users
project : 123 : assets
project : 123 : meta
project : 123 : meta
project : 123 : assets
project : 123 : users
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
PROJECT
123
456
META
ASSETS
USERS
/
\
/
\
/
\
|
|
...
...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
project : 123 : *
project : 123 : users
project : 123 : assets
project : 123 : meta
↓
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
project : 123
project : 123 : users
project : 123 : assets
project : 123 : meta
↓
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
RedisTree
Cache Engine
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
delete
("project:123")
::
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
SET
key value
GET
key
DEL
key [key ...]
KEYS
pattern
SADD
key member
KEYS
pattern
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1427908/Options-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
public function write($key, $value) {
$key_elms = explode(":", $key);
// Create an array of all nodes
$path = '';
for ( $i = 0; $i < sizeof($key_elms)-1; $i++) {
$path .= ( $i == 0 ? '' : ":" ) . $key_elms[$i];
$this->redis->sadd("redis_tree_nodes", $path);
}
return $this->redis->set($key, $value);
} // End function write()
public function write($key, $value) {
} // End function write()
public function write($key, $value) {
return $this->redis->set($key, $value);
} // End function write()
public function write($key, $value) {
$key_elms = explode(":", $key);
return $this->redis->set($key, $value);
} // End function write()
public function write($key, $value) {
$key_elms = explode(":", $key);
$this->redis->sadd("redis_tree_nodes", $path);
return $this->redis->set($key, $value);
} // End function write()
Redis Tree Cache Engine
Handles all nodes in key
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
Redis Tree Cache Engine
project : 123 : users : dave
project,
project:123, project:123:users
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
public function delete($key) {
// Determine if the key is a node
if ( $this->redis->sismember("redis_tree_nodes", $key) === 1 ) {
$key_node = $key;
$key .= ':*';
}
// Retrieve all keys to delete
$keys = $this->redis->keys($key);
// Delete node from list of nodes
$this->redis->srem("redis_tree_nodes", $key_node);
// Delete
return $this->redis->del($keys);
} // End function delete()
public function delete($key) {
// Delete
return $this->redis->del($keys);
} // End function delete()
public function delete($key) {
// Determine if the key is a node
if ( $this->redis->sismember("redis_tree_nodes", $key) === 1 ) {
}
// Delete
return $this->redis->del($keys);
} // End function delete()
public function delete($key) {
// Determine if the key is a node
if ( $this->redis->sismember("redis_tree_nodes", $key) === 1 ) {
$key_node = $key;
$key .= ':*';
}
// Delete
return $this->redis->del($keys);
} // End function delete()
public function delete($key) {
// Determine if the key is a node
if ( $this->redis->sismember("redis_tree_nodes", $key) === 1 ) {
$key_node = $key;
$key .= ':*';
}
// Retrieve all keys to delete
$keys = $this->redis->keys($key);
// Delete
return $this->redis->del($keys);
} // End function delete()
Redis Tree Cache Engine
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1427916/warning-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
"Consider KEYS as a command that should only be used in production environments with extreme care"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
clear
($check)
::
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
SCAN
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1415390/dbs_redis-white.png)
Recap
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1427966/lightbulb-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1427908/Options-white.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1427916/warning-white.png)
Facilitate cache invalidation
write() & delete()
Production considerations
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
Fallback
Cache Engine
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
![](http://png-2.findicons.com/files/icons/2773/pictonic_free/512/dbs_redis.png)
![](http://www.clker.com/cliparts/N/r/R/Z/7/q/shaded-flames-hi.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1428394/redis-cluster.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
![](http://4vector.com/i/free-vector-worried-about-a-bill-clip-art_109214_Worried_About_A_Bill_clip_art_medium.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
Fallback
Cache Engine
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
Fallback
Cache Engine
Secondary
passive
Primary
active
/
\
![](http://www.hailhailmedia.com/wp-content/uploads/2014/09/x.png)
Secondary
active
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
Fallback
Cache Engine
Secondary
FILE
Primary
REDIS
/
\
Distributed, uncertain & fast vs Server side, reliable & slower
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
![](https://cdn0.iconfinder.com/data/icons/huge-black-icons/512/Options.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
public function init($settings = array()) {
} // End function init()
public function init($settings = array()) {
parent::init($settings);
} // End function init()
public function init($settings = array()) {
parent::init($settings);
Cache::config("Primary", $this->settings['primary']);
Cache::config("Secondary", $this->settings['secondary']);
} // End function init()
public function init($settings = array()) {
parent::init($settings);
Cache::config("Primary", $this->settings['primary']);
Cache::config("Secondary", $this->settings['secondary']);
$this->activeCache = "Primary";
} // End function init()
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
public function write($key, $value) {
} // End function write()
public function write($key, $value) {
return Cache::write($key, $value, $this->activeCache);
} // End function write()
public function write($key, $value) {
try {
return Cache::write($key, $value, $this->activeCache);
}
catch (Exception $e) {
}
} // End function write()
public function write($key, $value) {
try {
return Cache::write($key, $value, $this->activeCache);
}
catch (Exception $e) {
$this->fallback();
}
} // End function write()
public function write($key, $value) {
try {
return Cache::write($key, $value, $this->activeCache);
}
catch (Exception $e) {
$this->fallback();
return Cache::write($key, $value, $this->activeCache);
}
} // End function write()
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
protected function fallback($setPrimary = false) {
if ( $setPrimary )
$this->activeCache = "Primary";
else
$this->activeCache = "Secondary";
} // End function fallback()
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
![](http://www.creawavestudio.com/www/static/website/img/gear.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
// Sessions caching
Cache::config('sessions', array(
'engine' => "Fallback",
'name' => 'sessions',
'primary' => array(
'engine' => "RedisTree",
'server' => "redis-server"
'prefix' => 'app:sessions:'
),
'secondary' => array(
// alternate cache if Redis fails
'engine' => "FileTree",
'path' => TMP.'/sessions/',
'prefix' => 'session_'
)
));
// Sessions caching
Cache::config('sessions', array(
'engine' => "Fallback",
'primary' => array(
),
'secondary' => array(
)
));
// Sessions caching
Cache::config('sessions', array(
'engine' => "Fallback",
'name' => 'sessions',
'primary' => array(
'engine' => "RedisTree",
'server' => "redis-server"
'prefix' => 'app:sessions:'
),
'secondary' => array(
// alternate cache if Redis fails
'engine' => "FileTree",
'path' => TMP.'/sessions/',
'prefix' => 'session_'
)
));
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
![](http://fc00.deviantart.net/fs71/i/2013/014/a/f/like_thumb_psd_by_yardbunny-d5rjjas.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1383631/failover-bw.png)
Recap
![](https://s3.amazonaws.com/media-p.slid.es/uploads/159409/images/1429980/lightbulb.png)
![](https://cdn0.iconfinder.com/data/icons/huge-black-icons/512/Options.png)
Simple, fault tolerant cache
Active + Passive approach
Thank You
https://slides.com/dchancogne/cache-engine
Build a wicked smaht cache engine
By David Chancogne
Build a wicked smaht cache engine
Build a wicked smaht cache engine
- 1,321