frantic
+1
1. А я думал, что такой способ не используют в крупных проектах. Часто вижу комментарии, где это называют костылем.

С вопросом я немного не так выразился. Как я понял в данном случае базы синхронизируются на прямую, как бы они это делали и в условиях расположения на одной стойке.

А как вообще синхронизируются данные (базы, файлы) между дата центрами? Ведь, например, знать о определенном юзере (его аватарке, настройках и.т.д) порой нужно в обоих центрах. Да и запись в них тоже по идее может быть из любого места. Что будет при одновременной записи в двух местах.
frantic
0
заменив его хорошо зарекомендовавшей себя “master-master” репликацией между площадками

Меня интересуют два вопроса:
1. как вы делаете «master-master» репликацию между mysql базами?
2. как синхронизируются дынные между территориально удаленными серверами?

Можно об этом рассказать или хотя бы дать источники. Сколько я этим не интересовался. Везде говорили, что «master-master» в mysql дает кашу в данных. А на территориально удаленных серверах есть задержка.

frantic
0
Было бы очень удобно добавить следующие функции:
  • Настройка репликации. Например, не реплицировать определенный папки в дереве. К примеру папку кэша. Или файлы по маске. К примеру, svn/git.
  • Синхранизация с сервером. Единовременное скачивание с сервера всего дерева файлов на клиент по запросу пользователя. Т.е. репликация в обратную сторону с сохранением фильтров репликации. К примеру, программист ведет разработку с разных компов. Дома и с работы. Поработав на работе, он приходит домой, нажимает кнопку синхранизации и получает у себя на компе свежее дерево файлов с которым можно работать
frantic
0
Статья как раз во время! Хотел потеснить облачный хостинг.
Ловите виртуальный плюс в карму.

frantic
0
Да. Обычно Varnish учат игнорировать куки.
Например так.

sub vcl_recv {
  unset req.http.cookie;
}


Или делают это более хитрее. Для примера можно посмотреть посмотреть конфиги Varnish, когда его ставят перед Drupal или Wordpress. В любом случае без модификации самого приложения не обойтись.
frantic
0
1. Varnish по-умолчанию не кэширует страницы при наличии куки.

2. Кука создается всегда при старте сессии. Не стартовать сессию для не авторизованных пользователей в Symfony нельзя, пользуясь стандартным механизмом Security Component.

3. Научить Varnish игнорировать конкретную куку можно, но как по ней различить авторизованного пользователя(кэшировать нельзя) и не авторизованного(кэшировать можно) я пока не придумал и не нашел.

4. уникальная кука — имелось ввиду значение.
frantic
+2
Правильно. И на уровне Symfony это работает. Но Varnish видя куку не авторизованного пользователя это дело не кэширует. Как различить в Varnish авторизованного и не авторизованного пользователя я пока не нашел.
frantic
+1
Вы правы, переименовал.
frantic
+5
Symfony очень удобный и производительный фреймворк. Даже метафреймворк. На его базе можно создавать множество различных приложений. В том числе и фреймворков. Например, Silex.

Есть просто некоторые вещи, которые неудобно делать. А именно, проекты где контент меняется в зависимости от авторизации пользователя. Причем когда этого контента много. Как в случае с хабром. И то это проблема больше реализации кэша, чем самого Symfony. Ничто не мешает написать свою оболочку.
frantic
0
Конечно, можно. В моем случае хоть и не идентичные, но очень схожие.
Там и там последние публикации с одинаковым набором данных: заголовок, автор, блог.
Естественно это сравнение приблизительно!
frantic
0
А можно подробнее? Я не понял, что вы имеете ввиду.
frantic
+1
http://dvjournal.ru/
Мое хобби. Первый проект на Symfony2. Дизайн и программирование — моё. Еще и пишу статьи.
frantic
+2
Очень интересная ситуация!

Из access.log
87.250.254.242 - - [30/Nov/2010:23:59:56 +0300] GET /slovo/poizi/671.htm HTTP/1.1 "200" 4240 "-" "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/ "-"

* This source code was highlighted with Source Code Highlighter.


Из моего кэтчера пауков:
Nov 30 23:59:56 symfony [err] [Yandex] Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots) [If-Modified-Since: Tue, 23 Nov 2010 02:59:34 GMT][<хост>/slovo/poizi/671.htm]

* This source code was highlighted with Source Code Highlighter.


Код кэтчера такой:
$pattern = '/(google)|(yandex)|(scooter)|(stack)|(aport)|(lycos)|(fast)|(rambler)/msi';

    if(isset($_SERVER['HTTP_USER_AGENT']) && preg_match($pattern, $_SERVER['HTTP_USER_AGENT'], $out))
    {
      $bot = self::$se[strtolower($out[0])];
      $agent = $_SERVER['HTTP_USER_AGENT'];

      $message = '['.$bot.'] '.$agent.' [If-Modified-Since: '.(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : 'no').']['.$request->getUri().']';
      sfContext::getInstance()->getLogger()->err($message); 
    }


* This source code was highlighted with Source Code Highlighter.


Получается робот все спрашивает как надо!

frantic
+8
Автор молодец. Написать за 2 недели сервер и клиент, да еще с учетом масштабирования. Плюс дизайн сделать (хоть не супер, но все же хоть что-то).
Я как разработчик проникся уважением.
Многопоточные сервера писать это вам не плюшки в магазине покупать.

Эх, мне бы такую производительность.

frantic
+3
пошла реклама конкурентов ))))
frantic
0
storeCacheInfo: false — отключает )
frantic
+2
> $cacheManager->remove('@sf_cache_partial?module=index&action=_listingBlock&sf_cache_key=*');

Лучше не использовать звездочки (*) при чистке кэша при условии использования memcache. Так как при удалении со звездочкой используется метод removePattern, который проходит по всем ключам из кэша и удаляет нужные по маске. Так вот хранятся эти все ключи там же в memcache в отдельной записи [prefix]_metadata c expire равной 0. Может случится ситуация, когда объем записи превысит лимит. ( у меня случилось к слову ) А дальше у сами додумайте ).

Отключить сохранение ключей в одну запись можно параметром:

storeCacheInfo: true

В версия symfony < 1.2.9 эти ключи добавлялись даже без удаления дубликатов:
protected function setCacheInfo($key)
 {
  $keys = $this->memcache->get($this->getOption('prefix').'_metadata');
  if (!is_array($keys))
  {
   $keys = array();
  }
  $keys[] = $this->getOption('prefix').$key;
  $this->memcache->set($this->getOption('prefix').'_metadata', $keys, 0);
 }


* This source code was highlighted with Source Code Highlighter.


Сейчас ситуация лучше, ключи удаляются:
protected function setCacheInfo($key, $delete = false)
 {
  $keys = $this->memcache->get($this->getOption('prefix').'_metadata');
  if (!is_array($keys))
  {
   $keys = array();
  }

  if ($delete)
  {
    if (($k = array_search($this->getOption('prefix').$key, $keys)) !== false)
    {
     unset($keys[$k]);
    }
  }
  else
  {
   if (!in_array($this->getOption('prefix').$key, $keys))
   {
    $keys[] = $this->getOption('prefix').$key;
   }
  }

  $this->memcache->set($this->getOption('prefix').'_metadata', $keys, 0);
 }


* This source code was highlighted with Source Code Highlighter.
frantic
0
В каждый партиал или компонент можно передавать с параметрами sf_cache_key. В этом случае ключ не генерируется, генерируете его вы сами.

Или вы можете переопределить обработчик генерации ключей. В settings.yml сразу после .settings определить параметр cache_namespace_callable.

Например
cache_namespace_callable: [«CacheGenerator», «generateCacheKey»]
frantic
0
Я понял принцип о котором вы говорите. Обдумаю как его применить в узких местах проекта. Я думаю он не противоречит, а даже дополняет то, к чему я пришел. Спасибо.

p.s. Вот только не знаю в знак благодарности минусовать вас или плюсовать :)
frantic
+1
слабовато разбираетесь в кэшировании

Знаете, эта фраза поставила меня в тупик. Объясню почему — цикл моих статей не о том, в чем я слабо разбираюсь или не разбираюсь. Они, если вы посмотрите еще раз повнимательнее — о том, как я разобрался с насущными задачами

Цель была поставлена при решении рабочей задачи, а спортивного вопроса — разбираюсь или нет — не стояло вообще.

Общие фразы вашего комментария отнюдь не свидетельствуют о том, что вы разбираетесь в этом больше…

Странно. Если разбираетесь — напишите как и в чем в отдельном посте. Понимаю, что клеить ярлык проще…

Предложите решение лучше — с удовольствием почитаю и приму на вооружение!
frantic
0
Написал не туда. Ответ.
frantic
+2
Изначально было так и реализовано, только без наблюдателя. В самой модели писался метод cleanCache, который и отвечал за чистку кэша view.

Постараюсь объяснить на примере.
Возьмем к примеру пользователя. У нас есть модель его самого, модель аватарки, картинок, профайла и т.д. и 10 разных блоков с этими данными в разных комбинациях. Пользователь сменил пол и мне надо сбросить во всех 10 блоках кэш, сменил город — в 8, аватарку — 5 и т.д. Добавили еще блок, бежим по всем классам, меняем метод cleanCache. Дизайн поменялся, опять меняем методы чистки кэша. К тому же на сайте не только юзер ;)

Да можно сделать наблюдателя, попытать упростить все это дело. Но зачем?

Понимаете, мы изменили подход. В шаблон приходят данные уже из кэша. Мне не надо думать о связях. О валидации. Модель все сделает за меня.
frantic
+3
С трудом могу представить где может сильно выйграть мемкеш, за счёт уменьшения объёма данных в несколько раз

а мы и не говорим о сильном выиграше. Просто приятно когда объем кэша уменьшается с 400 мб до 100Мб.

как могут добавить проблем сложные шаблоны — вполне представляю

Согласен. Но в Symfony пока нет шаблонизатора. Все пишется в php. Некоторые партиалы/компоненты конечно приходится кэшировать. Тем не менее сопровождать проект стало легче. Ведь основной причиной перехода на кэширование модели была простота валидации данных.
frantic
0
Предыдущий коммент отправился не вовремя ). Опишу подробнее.

$oUser->save(); Обновит кэш вызовом метода (addInstanceToPool($this)).
$oUser->delete(); Удалит из кэша объект (removeInstanceFromPool()).
UserPeer::retrieveByPk(); Положит объект в кэш, если его там нет (getInstanceFromPool, addInstanceToPool())
UserPeer::doDelete(); очистит весь кэш модели, если в него передадут объект Criteria (clearInstancePool()) или конкретный объект (removeInstanceFromPool()), если передадут PK.

Таким образом, если мы будем менять данные в базе только через модель, за актуальность отвечает Propel, иначе — мы сами.
frantic
0
Каждый раз когда вызывается метод save у propel объекта, обновляется и кэш (addInstanceToPool($this)).

frantic
0
Точно. Спасибо за информацию. Обязательно попробую. Единственное, что огорчает, что это решение не из коробки (
frantic
0
1. У меня иное немного мнение на этот счет. Дело в том, что если использовать join'ов в Propel'e продолжая пример указанный в статье на 20 объектов фоток создастся 20 экземпляров объекта юзера, а не один на всех.
2. Согласен, но ведь это скорее рекомендация, а не необходимость )
3. Согласен.
frantic
0
>что при обновлении/создании объекта модели надо обновлять пул (и кэш) или он обновляется автоматически
Обновлять пул не надо, т.к. при вызове метода save обновленный объект кладется в пул автоматически. Необходимо только переопределить 4 указанных в статье метода.

>А в сторону Doctrine не смотрели?
Нет не смотрел. Но там кажется эта ситуация решена.
frantic
–1
Propel устанавливается плагинов в Symfony и обновляется непосредственно его разработчиками. Если мне необходимо переопределить генератор кода, то надо изменять плагин. А это значит я меняю код фреймворка.
В документации по Symfony способа обойти эту ситуацию я не нашел. Если знаете, поделитесь ссылкой.