Настройка: веб-сайт с высокой посещаемостью и список URL-адресов изображений, которые мы хотим отобразить. У нас есть одно место для изображения, и каждый элемент в наборе URL-адресов изображений имеет целевой процент отображения в течение дня. Пример:

  • Изображение 1 – 10 %
  • Изображение2 – 30 %
  • Изображение3 – 60 %

Поскольку объем трафика может меняться изо дня в день, я делаю проценты в блоках по 1000. Изображения также должны выбираться случайным образом, но при этом точно соответствовать распределению.

Вопрос. Я внедрил POC-код для этого в memcache, но меня не устраивает способ хранения данных (множество хеш-ключей, сопоставленных «основной записью» с метаданными). Это также должно иметь возможность вернуться к базе данных, если серверы memcache перестанут работать. Меня также беспокоят проблемы параллелизма для основной записи.

Есть ли более простой способ сделать это? Возможно, быстрый запрос mysql или лучший способ добавить в это memcache?

Благодарность

0
cham 30 Май 2009 в 19:18
Я думаю, что вы не получили никаких ответов, потому что ваша проблема неясна.
 – 
Galen
31 Май 2009 в 01:25

2 ответа

Вы можете сделать то, что сказали, предварительно сгенерировав блок из 1000 значений, указывающих на изображения, которые вы вернете:

$distribution = "011022201111202102100120 ..." # exactly evenly distributed

Затем сохраните этот блок в MySQL и в кэше памяти и используйте другой ключ (как в MySQL, так и в кэше памяти) для хранения текущего значения индекса для указанной выше строки. Всякий раз, когда выполняется скрипт изображения, увеличивайте значение в memcache. Если memcache выходит из строя, вместо этого перейдите к MySQL (UPDATE, затем SELECT; возможно, есть лучший способ выполнить эту часть).

Чтобы синхронизировать memcache и MySQL, вы можете выполнить задание cron, скопировав текущее значение индекса из memcache в MySQL. Вы потеряете некоторую точность, но это может быть не критично в этой ситуации.

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

Грубо говоря :

function FetchImageFname( )
{
  $images = array( 0 => 'image1.jpg', 1 => 'image2.jpg', 2 => 'image3.jpg' );
  $distribution = FetchDistribution( );
  $currentindex = FetchCurrentIndex( );

  $x = 0;
  while( $distribution[$currentindex] == '' && $x < 10 );
  {
    IncrementCurrentDistribKey( );
    $distribution = FetchDistribution( );
    $currentindex = FetchCurrentIndex( );
    $x++;
  }

  if( $distribution[$currentindex] == '' )
  {
    // XXX Tried and failed. Send error to central logs.
    return( $images[0] );
  }

  return( $distribution[$currentindex] );
}

function FetchDistribution( )
{
  $current_distib_key = FetchCurrentDistribKey( );
  $distribution = FetchFromMemcache( $current_distrib_key );
  if( !$distribution )
    $distribution = FetchFromMySQL( $current_distrib_key );
  return $distribution;
}

function FetchCurrentIndex( )
{
  $current_index = MemcacheIncrement( 'foo' );
  if( $current_index === false )
    $current_index = MySQLIncrement( 'foo' );
  return $current_index;
}

.. и т.д. Имена функций немного воняют, но я думаю, вы поняли идею. Когда сервер memcache снова заработает, вы сможете скопировать данные из MySQL обратно в memcache, и он будет мгновенно реактивирован.

1
user153275user153275 9 Авг 2009 в 17:58

Попадание в базу данных, скорее всего, займет больше времени, поэтому я бы придерживался memcache. У вас будет больше проблем с параллелизмом при использовании MySQL, чем с memcache. memcache лучше оснащен для обработки большого количества запросов, и если серверы выйдут из строя, это будет наименьшей из ваших проблем на веб-сайте с высоким трафиком.

Возможно, эксперт по MySQL сможет добавить сюда хорошую структуру запроса, если вы дадите нам больше деталей.

0
David Weitz 31 Май 2009 в 07:15