• Home
  • Учебник по ExtJS
  • О сайте
  •  



    Эффективная работа с глобальными счетчиками

    Оригинал статьи – http://blog.appenginefan.com/2008/06/efficient-global-counters.html

    Одним из примеров, как не нужно работать с глобальными счетчиками – тот наивный подход, который я использовал в прошлом (сохранять счетчик в объекте и обновлять его в транзакции) является бутылочным горлышком, который реально уменьшает производительность приложения. Вместо этого рекомендуется использовать механизм по разделению  счетчика на несколько составляющих, относящихся к разным группам объектов. Примерный код может выглядеть так:

    from google.appengine.ext import db
    import random
    
    SHARDS_PER_COUNTER = 20
    
    class CounterShard(db.Model):
      name = db.StringProperty(required=True)
      count = db.IntegerProperty(default=0)
    
    def GetCount(nameOfCounter):
      result = 0
      for shard in CounterShard.gql('WHERE name=:1', nameOfCounter):
        result += shard.count
      return result
    
    def ChangeCount(nameOfCounter, delta):
      shard_id = '/%s/%s' % (
         nameOfCounter, random.randint(1, SHARDS_PER_COUNTER))
      def update():
       shard = CounterShard.get_by_key_name(shard_id)
       if shard:
         shard.count += delta
       else:
         shard = CounterShard(
             key_name=shard_id, name=nameOfCounter, count=delta)
       shard.put()
      db.run_in_transaction(update)
    

    Очень интересное решение, но можно сделать еще лучше с помощью использования интерфейса Memcache API, путем сохранения значения счетчика в памяти и обновления его при необходимости. Следующий пример показывает, как можно установить период устаревания значения счетчика на одну минуту:

    def GetCount(nameOfCounter):
      memcache_id = '/CounterShard/%s' %  nameOfCounter
      result = memcache.get(memcache_id)
      if not (result == None):
        return result
      result = 0
     for shard in CounterShard.gql('WHERE name=:1', nameOfCounter):
       result += shard.count
      memcache.set(memcache_id, result, 60)
      return result
    

    One Response to “Эффективная работа с глобальными счетчиками”

    1. [...] Замечание по производительности: Приведенный выше пример показывает неэффективную работу с счетчиками, однако он указан только для объяснения принципов работы. На практике же необходимо использовать разделение счетчиков. [...]

    Leave a Reply