Высокие concurrency счетчики без осколков
Этот вопрос касается двух реализаций счетчиков, которые предназначены для масштабирования без осколков (с компромиссом, который они могут недооценивать в некоторых ситуациях):
Мои вопросы:
- Что касается №1: Выполнение
memcache.decr()
в отложенной транзакционной задаче кажется излишним. Если memcache.decr()
выполняется за пределами транзакции, я думаю, что в худшем случае транзакция терпит неудачу, и мы пропускаем подсчет того, что мы уменьшаем. Могу ли я игнорировать некоторые другие проблемы, которые могут возникнуть при этом?
- Каковы существенные компромиссы между двумя реализациями?
Вот компромиссы, которые я вижу:
-
2 не требует транзакций хранилища данных.
- Для получения значения счетчика # 2 требуется выборка хранилища данных, а при # 1 обычно требуется только
memcache.get()
и memcache.add()
.
- При добавлении счетчика оба вызова
memcache.incr()
. Периодически # 2 добавляет задачу в очередь задач, в то время как # 1 транзакционно выполняет сбор данных. # 1 также всегда выполняет memcache.add()
(чтобы проверить, настало ли время для сохранения счетчика в хранилище данных).
<я > Выводы
(без фактических тестов производительности):
-
1 обычно должен быть быстрее при получении счетчика (# 1 memcache vs # 2 datastore). Хотя # 1 также должен выполнить дополнительный memcache.add()
.
- Тем не менее, # 2 должно быть быстрее при обновлении счетчиков (# 1 datastore get + put vs # 2 задает задачу).
- С другой стороны, С# 1 вам нужно быть более осторожным с интервалом обновления, поскольку квота очереди задач почти на 100 раз меньше, чем API-интерфейсы хранилища данных или memcahce.
Ответы
Ответ 1
Переход к хранилищу данных, скорее всего, будет дороже, чем переход через memcache. Иначе memcache не будет полезен в первую очередь: -)
Я бы порекомендовал первый вариант.
Если у вас есть разумная скорость запроса, вы можете реализовать ее еще проще:
1) update the value in memcache
2) if the returned updated value is evenly divisible by N
2.1) add N to the datastore counter
2.2) decrement memcache by N
Предполагается, что вы можете установить достаточно длинный тайм-аут в вашем memcache, чтобы жить между последовательными событиями, но если события настолько скудны, что ваш memcache истечет, скорее всего, вам не нужен счетчик "high concurrency": )
Для более крупных сайтов, полагаясь на один memcache, чтобы делать такие вещи, как подсчет общего количества просмотров страницы, вы можете столкнуться с трудностями; в этом случае вы действительно хотите очертить свои memcaches и обновить случайный экземпляр счетчика; агрегирование счетчиков произойдет с помощью обновления базы данных.
Однако при использовании memcache будьте осторожны, что некоторые клиентские API будут считать, что один тайм-аут означает, что это значение отсутствует. Если пакет TCP SYN в экземпляр memcache удаляется, это означает, что ваш запрос ошибочно предполагает, что данных нет. (Аналогичные проблемы могут возникнуть с UDP для memcache)
Ответ 2
Memcache очищается, вы теряете счетчик. УЧ. Использование базы данных mysql или решения NOSQL разрешит эту проблему с возможным поражением производительности. (Redis, Tokyotyrant, MongoDB и т.д.) Может не иметь такой производительности.
Имейте в виду, что вы можете сделать 2 действия:
- Храните счетчик memcache только по причинам высокой производительности.
- сохранить журнал, а затем получить более точные показатели.