PHP-статистика Объект хранится в памяти Параллельные обновления = потеря данных?

Я хочу абстрагировать статистику, рассчитывая на объекты в моей системе, до одного места. В настоящий момент каждый объект увеличивает счетчик в своей строке в таблице MySQL, т. UPDATE sometable SET views = views + 1 WHERE id = ?

Чтобы получить значительное увеличение производительности вместо того, чтобы записывать это обновление в БД каждый раз, когда объект используется, я хотел бы использовать apc для хранения объекта singleton analytics в счетчиках наращивания памяти внутри этого объекта и периодически сохранять этот объект обратно в БД.

Однако я правильно понимаю, что если два человека посещают одну и ту же страницу и увеличивают объект статистики, возможно, что одно из представлений может быть потеряно, если оба они делают $obj->views = $obj->views + 1 потому что объект статистики из apc будет иметь одинаковое общее количество просмотров, они оба увеличивают один и впоследствии перезаписывают друг друга.

Как мне обойти это?

Related of "PHP-статистика Объект хранится в памяти Параллельные обновления = потеря данных?"

Если вы действуете в три этапа:

  • получение записи от APC
  • работаю над этим
  • отталкивая его обратно в APC

Тогда, да, у вас могут быть проблемы с параллелизмом.

Лучшим решением было бы иметь одну запись APC для каждого из ваших счетчиков; и используйте apc_inc() чтобы apc_inc() ее.

Вероятно, это означает, что у вас много записей (по одному на каждый счетчик), но это также означает, что в большинстве sitautions (при добавлении счетчиков, что будет сделано больше всего) вам не придется заботиться о параллелизме: APC будет справитесь с этим для вас.

Остается только проблема, когда вы захотите:

  • Извлеките значение счетчика,
  • Храните это значение в базе данных,
  • И сбросьте счетчик.

Там вы снова столкнетесь с проблемами параллелизма.

Два решения:

  • Считайте, что это не повторится (эта операция должна быть довольно редкими, по сравнению с приростом) и согласиться потерять немного данных
  • Сделка с блокирующим меканизмом:
    • Создайте запись APC, в которой говорится, что «этот счетчик заблокирован»
    • Сделайте выборку + вещь БД + сброс
    • Удалить блокировку
    • Тем временем, если какой-либо другой скрипт хочет увеличить счетчик, он должен проверить, существует ли блокировка; и если да, подождите пару миллисекунд, пока блокировка не будет удалена.

Как пара боковых, теперь:

  • Вы можете делать то же самое с memcached, в тот день, когда вам нужно несколько веб-серверов – см. Memcache::increment
  • В обоих случаях APC и memcached являются кэшированием меканизма , а не постоянными хранилищами данных! Это означает, что они могут выселять ваши данные всякий раз, когда им это нужно (это произойдет, когда у них недостаточно памяти для новых записей или когда ваши записи станут слишком старыми)

Во втором случае вы можете переключиться на другое решение, которое:

  • Быстрее, чем MySQL
  • Сохранять на диск