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

C.R.E.A.M. (Cache Rules Everything Around Me)

C.R.E.A.M. (Cache Rules Everything Around Me)

Slides for my C.R.E.A.M. (Cache Rules Everything Around Me) talk at Loadays 2013. #loadays #load13

Thijs Feryn

April 06, 2013
Tweet

More Decks by Thijs Feryn

Other Decks in Technology

Transcript

  1. <?php try{ $m = new Memcached(); $m->addServer('localhost',11211); if($m->add('key1','value1',10) === false){

    throw new Exception($m->getResultMessage()); } if($m->set('key2','value2',10) === false){ throw new Exception($m->getResultMessage()); } if($m- >setMulti(array('key3'=>'value3','key4'=>'value4'), 10) === false){ throw new Exception($m->getResultMessage()); } } catch(Exception $e) { echo "Error: ".$e.PHP_EOL; } Create
  2. <?php $m = new Memcached(); $m->addServer('localhost',11211); $value1 = $m->get('key1'); $result

    = $m->getMulti(array('key2','key3','key4')); var_dump($value1,$result); Retrieve
  3. <?php try{ $m = new Memcached(); $m->addServer('localhost',11211); if($m->set('key1','value1',10) === false){

    throw new Exception($m->getResultMessage()); } if($m->replace('key1','azerty',10) === false){ throw new Exception($m->getResultMessage()); } if($m- >setMulti(array('key1'=>'value1','key2'=>'value2'), 10) === false){ throw new Exception($m->getResultMessage()); } } catch(Exception $e) { echo "Error: ".$e.PHP_EOL; } Update
  4. <?php try{ $m = new Memcached(); $m->addServer('localhost',11211); if($m->delete('key1') === false){

    throw new Exception($m->getResultMessage()); } if($m- >deleteMulti(array('key2','key3','key4')) === false){ throw new Exception($m->getResultMessage()); } } catch(Exception $e) { echo "Error: ".$e.PHP_EOL; } Delete
  5. <?php $m = new Memcached(); //$m- >setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT); $m->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE,true); $servers =

    array( array('localhost', 11211), array('localhost', 11212), array('localhost', 11213) ); $m->addServers($servers); for($i=0; $i<10;$i++){ if(($value = $m->get($i)) === false){ $value = date('Y-m-d H:i:s'); $m->set($i, $value); echo "<strong>$i</strong> not in cache, setting to $value <br / >".PHP_EOL; echo "Error: ".$m->getResultMessage()." (".$m->getResultCode().")<hr / >".PHP_EOL; } else { echo "Value for <strong>$i</strong>: $value <br />".PHP_EOL; } } High availability
  6. Keys <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379, 'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->set('key1', 'This is key1'); $client->expire('key1',10); $client->expire('key2',10); $client->set('key2', 'This is key2'); $client->persist('key2'); $client->set('key3', 'This is key3'); $client->del('key3'); $client->rename('key2','key3'); var_dump( $client->keys('k*'), $client->get('key1'), $client->exists('key3'), $client->ttl('key1'), $client->type('key1') );
  7. Strings <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379, 'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->set('key1', 'This is key1'); $client->setex('key2', 10, 'This is key2'); $client->set('key3', 1); $client->incr('key3'); $client->incrby('key3',2); $client- >mset('key4','This is key4','key5','This is key5'); var_dump( $client->strlen('key1'), $client->ttl('key2'), $client->getset('key1','New value for key1'), $client->get('key1'), $client->mget('key4','key5') );
  8. Hashes <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379,'data base'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->hset('hash1', 'name', 'Name for hash1'); $client->hmset('hash1', 'id', 1, 'status','ok'); $client->hset('hash2', 'name', 'Name for hash2'); $client->hsetnx('hash2', 'id', 1); $client->hincrby('hash3','id',1); $client->hset('hash2', 'bla', 'bla'); $client->hdel('hash2','bla'); var_dump( $client->hexists('hash1','id'), $client->hget('hash1','id'), $client->hgetall('hash1'), $client->hkeys('hash2'), $client->hvals('hash2'), $client->hlen('hash2'), $client->hmget('hash1','id','name') );
  9. Lists <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379, 'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->rpush('list1', 'b', 'c', 'e','f','g'); $client->lpush('list1','a'); $client->linsert('list1','BEFORE','e','d'); $client->ltrim('list1',0,2); var_dump( $client->lindex('list1',0), $client->llen('list1'), $client->lpop('list1'), $client->lrange('list1',0,2) );
  10. Sets <?php require __DIR__.'/autoload.php'; $server = array('host'=> '127.0.0.1','port'=> 6379 ,'database'

    => 0); $client = new Predis\Client($server); $client->flushdb(); $client->sadd('set1','a','b','c',3,5,1); $client->sadd('set2',0,1,2); $client->smove('set1','set2',3); $client->srem('set1',5); var_dump( $client->scard('set1'), $client->smembers('set1'), $client->sismember('set1','f'), $client->srandmember('set1',2), $client->sinter('set1','set2'), $client->sdiff('set1','set2'), $client->sunion('set1','set2') );
  11. <?php apc_add('key1','This is key1', 10); apc_add('key2','This is key2'); apc_add('key3',2); apc_delete('key2');

    apc_store('key2','bla',12); var_dump( apc_exists('key1'), apc_exists(array('key2','key3')), apc_inc('key3'), apc_dec('key3',12), apc_fetch('key1'), apc_clear_cache('user'), apc_fetch('key1') );
  12. <?php var_dump(apc_sma_info()); array(4) { ["num_seg"]=> int(1) ["seg_size"]=> float(33554352) ["avail_mem"]=> float(29335064)

    ["block_lists"]=> array(1) { [0]=> array(1) { [0]=> array(2) { ["size"]=> int(29335040) ["offset"]=> int(4219344) } } } }
  13. <?php if($_SERVER['REQUEST_METHOD'] == 'GET'){ $output = ob_get_contents(); ob_end_clean(); $key =

    md5('http://'.$_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI']); apc_store($key,$output,20); echo $output; } Append
  14. Only get & HEAD No cookie & auth headers No

    set-cookie headers cache ttl > 0 No vary “*” When will varnish cache?
  15. sub vcl_recv { if (req.restarts == 0) { if (req.http.x-forwarded-for)

    { set req.http.X-Forwarded-For = req.http.X-Forwarded-For + “, ” + client.ip; } else { set req.http.X-Forwarded-For = client.ip; } } if (req.request != “GET” && req.request != “HEAD” && req.request != “PUT” && req.request != “POST” && req.request != “TRACE” && req.request != “OPTIONS” && req.request != “DELETE”) { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } if (req.request != “GET” && req.request != “HEAD”) { /* We only deal with GET and HEAD by default */ return (pass); } if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } return (lookup); }
  16. sub vcl_pipe { # Note that only the first request

    to the backend will have # X-Forwarded-For set. If you use X-Forwarded-For and want to # have it set for all requests, make sure to have: # set bereq.http.connection = "close"; # here. It is not set by default as it might break some broken web # applications, like IIS with NTLM authentication. return (pipe); } sub vcl_pass { return (pass); } sub vcl_hash { hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } return (hash); }
  17. sub vcl_hit { return (deliver); } sub vcl_miss { return

    (fetch); } sub vcl_fetch { if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") { " " /* " " * Mark as "Hit-For-Pass" for the next 2 minutes " " */ " " set beresp.ttl = 120 s; " " return (hit_for_pass); } return (deliver); } sub vcl_deliver { return (deliver); }
  18. sub vcl_error { set obj.http.Content-Type = "text/html; charset=utf-8"; set obj.http.Retry-After

    = "5"; synthetic {" <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>"} + obj.status + " " + obj.response + {"</title> </head> <body> <h1>Error "} + obj.status + " " + obj.response + {"</h1> <p>"} + obj.response + {"</p> <h3>Guru Meditation:</h3> <p>XID: "} + req.xid + {"</p> <hr> <p>Varnish cache server</p> </body> </html> "}; return (deliver); } sub vcl_init { " return (ok); } sub vcl_fini { " return (ok); }
  19. 4+05:26:25 Hitrate.ratio:.......10......100......254 Hitrate.avg:.....0.8486...0.7619...0.7285 .....1760818.........6.99.........4.82.client_conn.;.Client.connections.accepted ....11088687........25.96........30.36.client_req.;.Client.requests.received .....8042715........11.98........22.02.cache_hit.;.Cache.hits .....2609561........11.98.........7.15.cache_miss.;.Cache.misses .......47104.........1.00.........0.13.backend_conn.;.Backend.conn..success .........610.........0.00.........0.00.backend_fail.;.Backend.conn..failures .....2998265........12.98.........8.21.backend_reuse.;.Backend.conn..reuses

    .......12081.........0.00.........0.03.backend_toolate.;.Backend.conn..was.closed .....3010356........13.98.........8.24.backend_recycle.;.Backend.conn..recycles ..........13.........0.00.........0.00.backend_retry.;.Backend.conn..retry .........520.........0.00.........0.00.fetch_head.;.Fetch.head .....2857965........11.98.........7.83.fetch_length.;.Fetch.with.Length ......151309.........2.00.........0.41.fetch_chunked.;.Fetch.chunked ........4404.........0.00.........0.01.fetch_close.;.Fetch.wanted.close .........676.........0.00.........0.00.fetch_failed.;.Fetch.failed .......31164.........0.00.........0.09.fetch_304.;.Fetch.no.body.(304) .........220...........................n_sess_mem.;.N.struct.sess_mem ..........53...........................n_sess.;.N.struct.sess .......29540...........................n_object.;.N.struct.object .......29561...........................n_objectcore.;.N.struct.objectcore ........5058...........................n_objecthead.;.N.struct.objecthead ........2613...........................n_waitinglist.;.N.struct.waitinglist ...........3...........................n_vbc.;.N.struct.vbc ..........22...........................n_wrk.;.N.worker.threads ........1789.........0.00.........0.00.n_wrk_create.;.N.worker.threads.created
  20. ...11.SessionOpen..c.12.12.12.1.53727.:80 ...11.ReqStart.....c.12.12.12.1.53727.1401010767 ...11.RxRequest....c.GET ...11.RxURL........c./ ...11.RxProtocol...c.HTTP/1.1 ...11.RxHeader.....c.Host:.12.12.12.6 ...11.RxHeader.....c.User;Agent:.Mozilla/5.0.(Macintosh;.Intel.Mac.OS.X.10.8;.rv:17.0). Gecko/20100101.Firefox/17.0 ...11.RxHeader.....c.Accept:.text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8

    ...11.RxHeader.....c.Accept;Language:.nl,en;q=0.7,fr;be;q=0.3 ...11.RxHeader.....c.Accept;Encoding:.gzip,.deflate ...11.RxHeader.....c.Connection:.keep;alive ...11.VCL_call.....c.recv.lookup ...11.VCL_call.....c.hash ...11.Hash.........c./ ...11.Hash.........c.12.12.12.6 ...11.VCL_return...c.hash ...11.VCL_call.....c.miss.fetch ...11.Backend......c.13.default.default ...11.TTL..........c.1401010767.RFC.0.;1.;1.1357920021.0.1357920020.0.0 ...11.VCL_call.....c.fetch ...11.TTL..........c.1401010767.VCL.120.;1.;1.1357920021.;0 ...11.VCL_return...c.hit_for_pass ...11.ObjProtocol..c.HTTP/1.1 ...11.ObjResponse..c.OK ...11.ObjHeader....c.Date:.Fri,.11.Jan.2013.16:00:20.GMT ...11.ObjHeader....c.Server:.Apache ...11.ObjHeader....c.X;Powered;By:.PHP/5.3.2;1ubuntu4.18 ...11.ObjHeader....c.Cache;Control:.no;cache,.no;store,.max;age=0 Client,
  21. ...11.VCL_return...c.hit_for_pass ...11.ObjProtocol..c.HTTP/1.1 ...11.ObjResponse..c.OK ...11.ObjHeader....c.Date:.Fri,.11.Jan.2013.16:00:20.GMT ...11.ObjHeader....c.Server:.Apache ...11.ObjHeader....c.X;Powered;By:.PHP/5.3.2;1ubuntu4.18 ...11.ObjHeader....c.Cache;Control:.no;cache,.no;store,.max;age=0 ...11.ObjHeader....c.Vary:.Accept;Encoding ...11.ObjHeader....c.Content;Encoding:.gzip ...11.ObjHeader....c.Content;Length:.119

    ...11.ObjHeader....c.Content;Type:.text/html ...11.Gzip.........c.u.F.;.119.336.80.80.887 ...11.VCL_call.....c.deliver.deliver ...11.TxProtocol...c.HTTP/1.1 ...11.TxStatus.....c.200 ...11.TxResponse...c.OK ...11.TxHeader.....c.Server:.Apache ...11.TxHeader.....c.X;Powered;By:.PHP/5.3.2;1ubuntu4.18 ...11.TxHeader.....c.Cache;Control:.no;cache,.no;store,.max;age=0 ...11.TxHeader.....c.Vary:.Accept;Encoding ...11.TxHeader.....c.Content;Encoding:.gzip ...11.TxHeader.....c.Content;Type:.text/html ...11.TxHeader.....c.Content;Length:.119 ...11.TxHeader.....c.Accept;Ranges:.bytes ...11.TxHeader.....c.Date:.Fri,.11.Jan.2013.16:00:20.GMT ...11.TxHeader.....c.X;Varnish:.1401010767 ...11.TxHeader.....c.Age:.0 ...11.TxHeader.....c.Via:.1.1.varnish ...11.TxHeader.....c.Connection:.keep;alive ...11.Length.......c.119 ...11.ReqEnd.......c.1401010767.1357920020.712090731.1357920020.727306366.0.000087738. Client,
  22. ...13.BackendClose.;.default ...13.BackendOpen..b.default.127.0.0.1.51597.127.0.0.1.8080 ...13.TxRequest....b.GET ...13.TxURL........b./ ...13.TxProtocol...b.HTTP/1.1 ...13.TxHeader.....b.Host:.12.12.12.6 ...13.TxHeader.....b.User;Agent:.Mozilla/5.0.(Macintosh;.Intel.Mac.OS.X.10.8;.rv:17.0). Gecko/20100101.Firefox/17.0 ...13.TxHeader.....b.Accept:.text/html,application/xhtml+xml,application/xml;q=0.9,*/ *;q=0.8

    ...13.TxHeader.....b.Accept;Language:.nl,en;q=0.7,fr;be;q=0.3 ...13.TxHeader.....b.X;Forwarded;For:.12.12.12.1 ...13.TxHeader.....b.X;Varnish:.1401010767 ...13.TxHeader.....b.Accept;Encoding:.gzip ...13.RxProtocol...b.HTTP/1.1 ...13.RxStatus.....b.200 ...13.RxResponse...b.OK ...13.RxHeader.....b.Date:.Fri,.11.Jan.2013.16:00:20.GMT ...13.RxHeader.....b.Server:.Apache ...13.RxHeader.....b.X;Powered;By:.PHP/5.3.2;1ubuntu4.18 ...13.RxHeader.....b.Cache;Control:.no;cache,.no;store,.max;age=0 ...13.RxHeader.....b.Vary:.Accept;Encoding ...13.RxHeader.....b.Content;Encoding:.gzip ...13.RxHeader.....b.Content;Length:.119 ...13.RxHeader.....b.Content;Type:.text/html ...13.Fetch_Body...b.4(length).cls.0.mklen.1 ...13.Length.......b.119 ...13.BackendReuse.b.default Backend,
  23. sub.vcl_recv.{ ........if.(req.request.==."PURGE").{ ban("req.http.host.==.".+.req.http.host.+.". &&.req.url.==.".+.req.url); error.200."Banned"; ........} } Ban sub.vcl_recv.{ ........if.(req.request.==."PURGE").{

    ............ban("req.http.host.==.".+.req.http.host.+. ".&&.req.url.~.".+.req.url); error.200."Banned"; ........} } Ban,URL, pattern Ban,URL Name, doesn’t, matter
  24. <html> <body> <table> <tr> <td colspan="2" > <esi:include src="/header.php" />

    </td> </tr> <tr> <td><esi:include src="/menu.php" /></td> <td><esi:include src="/main.php" /></td> </tr> <tr> <td colspan="2" > <esi:include src="/footer.php" /> </td> </tr> </table> </body>
  25. location / { proxy_pass http://localhost:8080; proxy_set_header X-Real-IP $remote_addr; proxy_cache my-cache;

    proxy_cache_key "$scheme$request_method$host $request_uri"; proxy_cache_valid 200 302 60m; proxy_cache_valid 404 1m; }
  26. location ~ /purge(/.*) { proxy_cache_purge my-cache "$scheme $request_method$host$1";" } ✓

    Requires,ngx_cache_purge ✓ Requires,separate,“purge”,URL,(buggy,behaviour) ✓ https://github.com/FRiCKLE/ngx_cache_purge
  27. server { listen 80; root /var/www/; ! location / {

    try_files $uri $uri/ /index.php; } location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; }! }
  28. location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php;

    include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_cache my-cache; fastcgi_cache_key "$scheme$request_method$host $request_uri"; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500; } FastCGI, cache,to, cache,zone
  29. upstream my_memcached { " server my.memcached.org:11211; " server my.other.memcached.org:11211;" }

    upstream my_fpm { " server my.fpm.org:9000; " server my.other.fpm.org:9000;" } Upstream, servers Loadbalancing
  30. location ~ \.php$ { set $memcached_key $request_uri; memcached_pass my_memcached; memcached_next_upstream

    not_found; default_type "text/html; charset=utf-8"; error_page 404 405 502 = @php; }! location @php { default_type "text/html; charset=utf-8"; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass my_fpm; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $request_filename; }
  31. <?php $contents = date("Y-m-d H:i:s"); $m = new Memcached(); $m->addServer('localhost',11211);

    $m->set($_SERVER['REQUEST_URI'], $contents,3600); echo $contents; Save,to, Memcached,&, output