Я хотел бы использовать PHP 7. Однако, похоже, нет возможности для кэширование памяти значения ключа.
XCache не будет доступен для PHP 7 в течение некоторого времени.
Есть ли доступная альтернатива для PHP 7?
Или есть способ использовать Opcache PHP7 для реализации кэширования памяти значения ключа?
Я бы предложил использовать Memcached, особенно если вы беспокоитесь о производительности.
Хотя вы и правы, что APC (u) намного быстрее, чем Memcache, вы не принимаете во внимание, что к тому времени, когда вы будете беспокоиться об этих показателях, вы будете работать на нескольких серверах и APC (u) не может быть разделен между узлами.
Вы можете использовать один экземпляр или кластер Memcache для обслуживания любого количества серверов приложений. Масштабируемость является более важной задачей при разработке современных приложений, чем «сколько производительности я могу выжать из одного сервера?»
Сказав это, ваша альтернатива APCu, который имеет все функции, к которым вы привыкли от APC. Он помечен как стабильный с PHP7, но я бы не рекомендовал это из-за его одноузловой природы & невозможность правильно работать с fastcgi.
APCU является в прямом смысле APC без кэширования кода (они взяли код APC, удалили кэш байт-кода и выпустили его как APCU). Это замена замены. Точно так же, как пользовательский кеш APC, он хранит данные в том же процессе, что и среда выполнения PHP, поэтому использование значения похоже на получение обычной переменной, а следовательно, и скорости.
Другой подход (который я не пробовал, но звучит очень интересно) заключается в использовании opcache в качестве кэша значений ключей. это graphiq пост содержит больше деталей, но, к сожалению, никакого реального кода (и обратите внимание на комментарии Керри Шваба).
Суть этого заключается в том, чтобы убедиться, что opcache включен и имеет достаточно памяти, выделенной для данных, которые необходимо кэшировать, а затем что-то вроде следующего (см. Статью, ознакомьтесь с ней полностью). Срок действия кэша (кроме удаления вручную) также должен быть обработан, но его нетрудно добавить (например, обернуть ваши данные в содержащий объект со временем истечения и проверить его в cache_get
, удаление и игнорирование записи, если срок ее действия истек).
function cache_set($key, $val) {
$val = var_export($val, true);
// HHVM fails at __set_state, so just use object cast for now
$val = str_replace('stdClass::__set_state', '(object)', $val);
// Write to temp file first to ensure atomicity
$tmp = "/tmp/$key." . uniqid('', true) . '.tmp';
file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX);
rename($tmp, "/tmp/$key");
}
function cache_get($key) {
@include "/tmp/$key";
return isset($val) ? $val : false;
}
Из-за opcache это работает как кэш в памяти, но это избегает издержек сериализации и десериализации. Я думаю, что cache_set должен также вызвать opcache_invalidate
при написании (и в cache_delete
функция, которая не существует в их примерах), но в противном случае это звучит нормально для кеша, который не должен быть разделен между серверами.
Изменить: Пример реализации с истечением срока действия кэша (с точностью до секунды, может использовать microtime(true)
если требуется большая точность) ниже. Минимальное тестирование на самом деле сделано, и я отбросил замену HHVM, поэтому YMMV. Предложения по улучшению приветствуются.
class Cache {
private $root;
private $compile;
private $ttl;
public function __construct($options = []) {
$this->options = array_merge(
array(
'root' => sys_get_temp_dir(),
'ttl' => false,
),
$options
);
$this->root = $this->options['root'];
$this->ttl = $this->options['ttl'];
}
public function set($key, $val, $ttl = null) {
$ttl = $ttl === null ? $this->ttl : $ttl;
$file = md5($key);
$val = var_export(array(
'expiry' => $ttl ? time() + $ttl : false,
'data' => $val,
), true);
// Write to temp file first to ensure atomicity
$tmp = $this->root . '/' . $file . '.' . uniqid('', true) . '.tmp';
file_put_contents($tmp, '<?php $val = ' . $val . ';', LOCK_EX);
$dest = $this->root . '/' . $file;
rename($tmp, $dest);
opcache_invalidate($dest);
}
public function get($key) {
@include $this->root . '/' . md5($key);
// Not found
if (!isset($val)) return null;
// Found and not expired
if (!$val['expiry'] || $val['expiry'] > time()) return $val['data'];
// Expired, clean up
$this->remove($key);
}
public function remove($key) {
$dest = $this->root . '/' . md5($key);
if (@unlink($dest)) {
// Invalidate cache if successfully written
opcache_invalidate($dest);
}
}
}