- PVSM.RU - https://www.pvsm.ru -
Добрый день!
В этой статье мы расскажем о том, как мы работаем с кешем в plus1.wapstart.ru [1], какие проблемы у нас возникали и как мы решали некоторые частные случаи.
Под «кешем» в этой статье я буду понимать какое-то быстрое хранилище, которое может использоваться, в том числе, и для кеширования. При этом хранилище должно обладать стандартизированным интерфейсом.
Сервер/хранилище — это какое-нибудь приложение, которое может хранить данные и давать к ним доступ по интерфейсу, который описан ниже. Например, этим приложением может быть memcached.
Мы используем фреймворк onPHP [2]. В нем есть абстрактный класс CachePeer, от которого должны наследоваться все реализации кешей. Интерфейс любой реализации сводится к следующим методам.
abstract public function get($key);
abstract public function delete($key);
abstract public function increment($key, $value);
abstract public function decrement($key, $value);
abstract protected function store(
$action, $key, $value, $expires = Cache::EXPIRES_MEDIUM
);
abstract public function append($key, $data);
В нашем мире существуют следующие реализации CachePeer (кликабельно)
[3]
На этой диаграмме представлены как реализации хранилищ (см. мост [4]), так и разнообразные декораторы [5], решающие частные задачи.
В onphp есть поддержка работы c Redis [6]; Memcached — целых две реализации: на сокетах [7] и с использованием Memcache [8] (http://php.net/Memcache [9]); мы можем работать с SharedMemory [10]. Если ничего из этого в инсталляции нет, то мы будем работать с памятью приложения [11].
Не смотря на все многообразие поддерживаемых технологий, мне не известно ни одного проекта на onphp, который бы использовал что-то отличное от Memcached.
Memcached правит этим миром. :)
У нас есть две реализации Memcache по следующим причинам:
Мы практически повсеместно используем PeclMemcached, который подключается к серверу через расширение Memcache. При прочих равных он работает быстрее и к тому же поддерживает pconnect [14].
С альтернативной библиотекой (MemcacheD [12]) у нас как-то не сложилось. Я пробовал писать под нее реализацию, но на тот момент (около двух лет назад) она была не очень стабильна.
Когда соотношение проектов на одну кеширующую систему становится больше одного, то следует использовать WatermarkedPeer [15]. Его смысл сводится к методу getActualWatermark(). Например, реализация get становится такой
public function get($key)
{
return $this->peer->get($this->getActualWatermark().$key);
}
Это позволяет избежать конфликта ключей. Данные из разных проектов/классов/ и т.д. будут записаны под разными ключами. В остальном — этот кеш является стандартным декоратором к какой-нибудь реализации хранилища.
Если вам необходимо разнести данные по множеству кеширующих систем, то можно либо воспользоваться кластером мемкеша из поставки php, либо взять один из наших аггрегатных кешей. У нас их несколько:
На этом более-менее стандартная часть заканчивается. Большинству приложений должно хватить этого набора реализаций для создания нормальной системы кеширования.
MultiCachePeer::create(
PeclMemcached::create('localhost', 11211),
array(
PeclMemcached::create('meinherzbrennt', 11211),
PeclMemcached::create('links234', 11211),
PeclMemcached::create('sonne', 11211),
PeclMemcached::create('ichwill', 11211),
PeclMemcached::create('feuerfrei', 11211),
PeclMemcached::create('mutter', 11211),
PeclMemcached::create('spieluhr', 11211)
)
);
$cache =
new SequentialCache(
PeclMemcached::create('master', 11211, 0.1), //третий параметр конструктора - это таймаут.
array(
PeclMemcached::create('backup', 11211, 0.1),
)
)
Т.к. практически все реализации используют паттерн декоратор, то их можно вполне успешно комбинировать.
Например, допустима такая конструкция:
$swordfish =
ReadOnlyPeer::create(
new SequentialCache(
PeclMemcached::create('localhost', 9898, 0.1),
array(
PeclMemcached::create('backup', 9898, 0.1),
)
)
);
Или даже такая:
$swordfish =
CascadeCache::create(
PeclMemcached::create('unix:///var/run/memcached_sock/memcached.sock', 0),
ReadOnlyPeer::create(
new SequentialCache(
PeclMemcached::create('localhost', 9898, 0.1),
array(
PeclMemcached::create('backup', 9898, 0.1),
)
)
),
CascadeCache::NEGATIVE_CACHE_OFF
);
В этом случае данные будут сначала искаться в локальном мемкеше, доступном по unix-socket, в случае если их там нет, то будет запрошен «мемкеш» localhost:9898. А в случае, если он недоступен, то backup:9898. При этом, приложение знает, что из кешей на портах 9898 можно только читать, но не писать.
На этом возможности кешей из onphp не заканчиваются. Можно делать совершенно разные конфигурации, которые будут покрывать ваши задачи. CachePeer из onphp — это круто.
ps. Когда-то давно здесь [30] говорили о цикле статей про onphp. Начало положено этим постом. В будущем мы затронем другие темы, связанные с фреймворком и его применением в plus1.wapstart.ru.
pps. Пользуясь случаем, сообщаю, что мы ищем людей:
hantim.ru/jobs/11163-veduschiy-qa-menedzher-rukovoditel-otdela-testirovaniya [31]
hantim.ru/jobs/11111-veduschiy-php-razrabotchik-team-leader [32]
Автор: dovg
Источник [33]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/19833
Ссылки в тексте:
[1] plus1.wapstart.ru: https://plus1.wapstart.ru/
[2] onPHP: https://github.com/onPHP/onphp-framework
[3] Image: http://cs307900.userapi.com/v307900364/1bf1/tJ4bdm4M2CE.jpg
[4] мост: http://en.wikipedia.org/wiki/Bridge_pattern
[5] декораторы: http://en.wikipedia.org/wiki/Decorator_pattern
[6] Redis: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/DB/NoSQL/RedisNoSQL.class.php
[7] на сокетах: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/Memcached.class.php
[8] Memcache: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/PeclMemcached.class.php
[9] http://php.net/Memcache: http://php.net/Memcache
[10] SharedMemory: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/SharedMemory.class.php
[11] памятью приложения: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/RuntimeMemory.class.php
[12] http://php.net/Memcached: http://php.net/Memcached
[13] master: https://github.com/onPHP/onphp-framework/blob/master/core/Cache/SocketMemcached.class.php
[14] pconnect: http://www.php.net/manual/ru/memcache.pconnect.php
[15] WatermarkedPeer: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/WatermarkedPeer.class.php
[16] AggregateCache: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/AggregateCache.class.php
[17] mt_rand: http://ru2.php.net/manual/en/function.mt-rand.php
[18] mt_srand: http://ru2.php.net/manual/en/function.mt-srand.php
[19] просто: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/AggregateCache.class.php#L63
[20] SimpleAggregateCache: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/SimpleAggregateCache.class.php
[21] CyclicAggregateCache: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/CyclicAggregateCache.class.php
[22] last.fm: http://www.last.fm/user/dovg
[23] здесь: http://www.last.fm/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients
[24] здесь: http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html
[25] DebugCachePeer: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/DebugCachePeer.class.php
[26] ReadOnlyPeer: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/ReadOnlyPeer.class.php
[27] рыба: https://github.com/WapStart/swordfishd
[28] CascadeCache: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/CascadeCache.class.php
[29] SequentialCache: https://github.com/WapStart/onphp-framework/blob/1.0-wapstart/core/Cache/SequentialCache.class.php
[30] здесь: http://habrahabr.ru/post/94972/
[31] hantim.ru/jobs/11163-veduschiy-qa-menedzher-rukovoditel-otdela-testirovaniya: http://hantim.ru/jobs/11163-veduschiy-qa-menedzher-rukovoditel-otdela-testirovaniya
[32] hantim.ru/jobs/11111-veduschiy-php-razrabotchik-team-leader: http://hantim.ru/jobs/11111-veduschiy-php-razrabotchik-team-leader
[33] Источник: http://habrahabr.ru/post/158311/
Нажмите здесь для печати.