Этот вопрос касается двух реализаций счетчиков, которые предназначены для масштабирования без осколков (с компромиссом, который они могут недооценивать в некоторых ситуациях):
- http://appengine-cookbook.appspot.com/recipe/high-concurrency-counters-without-sharding/ (код в комментариях)
- http://blog.notdot.net/2010/04/High-concurrency-counters-without-sharding
Мои вопросы:
- Что касается №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.