mirror of https://github.com/friendica/friendica
Merge pull request #4549 from MrPetovan/task/4518-add-memcached-support
[develop] Performance: Add memcached support/Improve database cache (redux)pull/4561/head
commit
cc688e2b4f
@ -1,11 +1,13 @@
|
||||
Table cache
|
||||
===========
|
||||
|
||||
Stores temporary data
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ------------ | ---------------------------------- | ------------ | ---- | --- | ------------------- | ----- |
|
||||
| k | horizontal width + url or resource | varchar(255) | NO | PRI | NULL | |
|
||||
| v | OEmbed response from site | text | NO | | NULL | |
|
||||
| k | cache key | varchar(255) | NO | PRI | NULL | |
|
||||
| v | cached serialized value | text | NO | | NULL | |
|
||||
| expires | datetime of cache expiration | datetime | NO | MUL | 0001-01-01 00:00:00 | |
|
||||
| updated | datetime of cache insertion | datetime | NO | MUL | 0001-01-01 00:00:00 | |
|
||||
| expire_mode | | int(11) | NO | | 0 | |
|
||||
|
||||
Return to [database documentation](help/database)
|
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use dba;
|
||||
use Friendica\Core\Cache;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
/**
|
||||
* Database Cache Driver
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class DatabaseCacheDriver implements ICacheDriver
|
||||
{
|
||||
public function get($key)
|
||||
{
|
||||
$cache = dba::selectFirst('cache', ['v'], ['`k` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
|
||||
|
||||
if (DBM::is_result($cache)) {
|
||||
$cached = $cache['v'];
|
||||
$value = @unserialize($cached);
|
||||
|
||||
// Only return a value if the serialized value is valid.
|
||||
// We also check if the db entry is a serialized
|
||||
// boolean 'false' value (which we want to return).
|
||||
if ($cached === serialize(false) || $value !== false) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function set($key, $value, $duration = Cache::MONTH)
|
||||
{
|
||||
$fields = [
|
||||
'v' => serialize($value),
|
||||
'expires' => DateTimeFormat::utc('now + ' . Cache::duration($duration) . ' seconds'),
|
||||
'updated' => DateTimeFormat::utcNow()
|
||||
];
|
||||
|
||||
return dba::update('cache', $fields, ['k' => $key], true);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
return dba::delete('cache', ['k' => $key]);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return dba::delete('cache', ['`expires` < NOW()']);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use Friendica\Core\Cache;
|
||||
|
||||
/**
|
||||
* Cache Driver Interface
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
interface ICacheDriver
|
||||
{
|
||||
/**
|
||||
* Fetches cached data according to the key
|
||||
*
|
||||
* @param string $key The key to the cached data
|
||||
*
|
||||
* @return mixed Cached $value or "null" if not found
|
||||
*/
|
||||
public function get($key);
|
||||
|
||||
/**
|
||||
* Stores data in the cache identified by the key. The input $value can have multiple formats.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
* @param mixed $value The value to store
|
||||
* @param integer $duration The cache lifespan, must be one of the Cache constants
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set($key, $value, $duration = Cache::MONTH);
|
||||
|
||||
|
||||
/**
|
||||
* Delete a key from the cache
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($key);
|
||||
|
||||
/**
|
||||
* Remove outdated data from the cache
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clear();
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Cache;
|
||||
|
||||
/**
|
||||
* Memcache Cache Driver
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class MemcacheCacheDriver extends BaseObject implements ICacheDriver
|
||||
{
|
||||
/**
|
||||
* @var Memcache
|
||||
*/
|
||||
private $memcache;
|
||||
|
||||
public function __construct($memcache_host, $memcache_port)
|
||||
{
|
||||
if (!class_exists('Memcache', false)) {
|
||||
throw new \Exception('Memcache class isn\'t available');
|
||||
}
|
||||
|
||||
$this->memcache = new \Memcache();
|
||||
|
||||
if (!$this->memcache->connect($memcache_host, $memcache_port)) {
|
||||
throw new \Exception('Expected Memcache server at ' . $memcache_host . ':' . $memcache_port . ' isn\'t available');
|
||||
}
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$return = null;
|
||||
|
||||
// We fetch with the hostname as key to avoid problems with other applications
|
||||
$cached = $this->memcache->get(self::getApp()->get_hostname() . ':' . $key);
|
||||
|
||||
// @see http://php.net/manual/en/memcache.get.php#84275
|
||||
if (is_bool($cached) || is_double($cached) || is_long($cached)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
$value = @unserialize($cached);
|
||||
|
||||
// Only return a value if the serialized value is valid.
|
||||
// We also check if the db entry is a serialized
|
||||
// boolean 'false' value (which we want to return).
|
||||
if ($cached === serialize(false) || $value !== false) {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function set($key, $value, $duration = Cache::MONTH)
|
||||
{
|
||||
// We store with the hostname as key to avoid problems with other applications
|
||||
return $this->memcache->set(
|
||||
self::getApp()->get_hostname() . ":" . $key,
|
||||
serialize($value),
|
||||
MEMCACHE_COMPRESSED,
|
||||
Cache::duration($duration)
|
||||
);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
return $this->memcache->delete($key);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Cache;
|
||||
|
||||
/**
|
||||
* Memcached Cache Driver
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class MemcachedCacheDriver extends BaseObject implements ICacheDriver
|
||||
{
|
||||
/**
|
||||
* @var Memcached
|
||||
*/
|
||||
private $memcached;
|
||||
|
||||
public function __construct(array $memcached_hosts)
|
||||
{
|
||||
if (!class_exists('Memcached', false)) {
|
||||
throw new \Exception('Memcached class isn\'t available');
|
||||
}
|
||||
|
||||
$this->memcached = new \Memcached();
|
||||
|
||||
$this->memcached->addServers($memcached_hosts);
|
||||
|
||||
if (count($this->memcached->getServerList()) == 0) {
|
||||
throw new \Exception('Expected Memcached servers aren\'t available, config:' . var_export($memcached_hosts, true));
|
||||
}
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$return = null;
|
||||
|
||||
// We fetch with the hostname as key to avoid problems with other applications
|
||||
$value = $this->memcached->get(self::getApp()->get_hostname() . ':' . $key);
|
||||
|
||||
if ($this->memcached->getResultCode() === \Memcached::RES_SUCCESS) {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function set($key, $value, $duration = Cache::MONTH)
|
||||
{
|
||||
// We store with the hostname as key to avoid problems with other applications
|
||||
return $this->memcached->set(
|
||||
self::getApp()->get_hostname() . ":" . $key,
|
||||
$value,
|
||||
Cache::duration($duration)
|
||||
);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
return $this->memcached->delete($key);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue