SlideShare une entreprise Scribd logo
1  sur  64
Télécharger pour lire hors ligne
BUILDING TO SCALE

                            David Cramer
                           twitter.com/zeeg



Tuesday, February 26, 13
The things we build will not
                    and can not last




Tuesday, February 26, 13
Who am I?




Tuesday, February 26, 13
Tuesday, February 26, 13
Tuesday, February 26, 13
Tuesday, February 26, 13
What do we mean by scale?




Tuesday, February 26, 13
DISQUS
                 Massive traffic with a long tail


                                                  Sentry
                                 Counters and event aggregation




                 tenXer
                 More stats than we can count



Tuesday, February 26, 13
Does one size fit all?




Tuesday, February 26, 13
Practical Storage




Tuesday, February 26, 13
Postgres is the foundation of DISQUS




Tuesday, February 26, 13
MySQL powers the tenXer graph store




Tuesday, February 26, 13
Sentry is built on SQL




Tuesday, February 26, 13
Databases are not the problem




Tuesday, February 26, 13
Compromise




Tuesday, February 26, 13
Scaling is about Predictability




Tuesday, February 26, 13
Augment SQL with [technology]




Tuesday, February 26, 13
Tuesday, February 26, 13
Simple solutions using Redis
                           (I like Redis)




Tuesday, February 26, 13
Counters




Tuesday, February 26, 13
Counters are everywhere




Tuesday, February 26, 13
Counters in SQL
                           UPDATE table SET counter = counter + 1;




Tuesday, February 26, 13
Counters in Redis
                                  INCR counter 1
                             >>> redis.incr('counter')




Tuesday, February 26, 13
Counters in Sentry

                           event ID 1   event ID 2   event ID 3




                           Redis INCR   Redis INCR   Redis INCR




                                        SQL Update




Tuesday, February 26, 13
Counters in Sentry

                ‣
                     INCR event_id in Redis
                ‣
                     Queue buffer incr task
                      ‣
                           5 - 10s explicit delay


                ‣
                     Task does atomic GET event_id and DEL
                     event_id (Redis pipeline)
                ‣
                     No-op If GET is not > 0
                ‣
                     One SQL UPDATE per unique event per
                     delay



Tuesday, February 26, 13
Counters in Sentry (cont.)


                     Pros
                ‣
                     Solves database row lock contention
                ‣
                     Redis nodes are horizontally scalable
                ‣
                     Easy to implement


                     Cons
                ‣
                     Too many dummy (no-op) tasks




Tuesday, February 26, 13
Alternative Counters

                             event ID 1      event ID 2      event ID 3




                           Redis ZINCRBY   Redis ZINCRBY   Redis ZINCRBY




                                            SQL Update




Tuesday, February 26, 13
Sorted Sets in Redis




                           > ZINCRBY events ad93a 1
                           {ad93a: 1}

                           > ZINCRBY events ad93a 1
                           {ad93a: 2}

                           > ZINCRBY events d2ow3 1
                           {ad93a: 2, d2ow3: 1}



Tuesday, February 26, 13
Alternative Counters


                ‣
                     ZINCRBY events event_id in Redis
                ‣
                     Cron buffer flush


                ‣
                     ZRANGE events to get pending updates
                ‣
                     Fire individual task per update
                      ‣
                           Atomic ZSCORE events event_id and
                           ZREM events event_id to get and flush
                           count.



Tuesday, February 26, 13
Alternative Counters (cont.)



                     Pros
                ‣
                     Removes (most) no-op tasks
                ‣
                     Works without a complex queue due to no
                     required delay on jobs


                     Cons
                ‣
                     Single Redis key stores all pending updates




Tuesday, February 26, 13
Activity Streams




Tuesday, February 26, 13
Streams are everywhere




Tuesday, February 26, 13
Streams in SQL


                           class Activity:
                               SET_RESOLVED = 1
                               SET_REGRESSION = 6

                               TYPE = (
                                   (SET_RESOLVED, 'set_resolved'),
                                   (SET_REGRESSION, 'set_regression'),
                               )

                               event      =   ForeignKey(Event)
                               type       =   IntegerField(choices=TYPE)
                               user       =   ForeignKey(User, null=True)
                               datetime   =   DateTimeField()
                               data       =   JSONField(null=True)




Tuesday, February 26, 13
Streams in SQL (cont.)




                       >>> Activity(event, SET_RESOLVED, user, now)
                       "David marked this event as resolved."

                       >>> Activity(event, SET_REGRESSION, datetime=now)
                       "The system marked this event as a regression."

                       >>> Activity(type=DEPLOY_START, datetime=now)
                       "A deploy started."

                       >>> Activity(type=SET_RESOLVED, datetime=now)
                       "All events were marked as resolved"




Tuesday, February 26, 13
Stream == View == Cache




Tuesday, February 26, 13
Views as a Cache



                      TIMELINE = []
                      MAX = 500

                      def on_event_creation(event):
                          global TIMELINE

                           TIMELINE.insert(0, event)
                           TIMELINE = TIMELINE[:MAX]

                      def get_latest_events(num=100):
                          return TIMELINE[:num]



Tuesday, February 26, 13
Views in Redis



                  class Timeline(object):
                      def __init__(self):
                          self.db = Redis()

                           def add(self, event):
                               score = float(event.date.strftime('%s.%m'))
                               self.db.zadd('timeline', event.id, score)

                           def list(self, offset=0, limit=-1):
                               return self.db.zrevrange(
                                   'timeline', offset, limit)




Tuesday, February 26, 13
Views in Redis (cont.)




                  MAX_SIZE = 10000

                  def add(self, event):
                      score = float(event.date.strftime('%s.%m'))

                           # increment the key and trim the data to avoid
                           # data bloat in a single key
                           with self.db.pipeline() as pipe:
                               pipe.zadd(self.key, event.id, score)
                               pipe.zremrange(self.key, event.id, MAX_SIZE, -1)




Tuesday, February 26, 13
Queuing




Tuesday, February 26, 13
Introducing Celery




Tuesday, February 26, 13
RabbitMQ or Redis




Tuesday, February 26, 13
Asynchronous Tasks




                      # Register the task
                      @task(exchange=”event_creation”)
                      def on_event_creation(event_id):
                          counter.incr('events', event_id)


                      # Delay execution
                      on_event_creation(event.id)




Tuesday, February 26, 13
Fanout

                      @task(exchange=”counters”)
                      def incr_counter(key, id=None):
                          counter.incr(key, id)


                      @task(exchange=”event_creation”)
                      def on_event_creation(event_id):
                          incr_counter.delay('events', event_id)
                          incr_counter.delay('global')


                      # Delay execution
                      on_event_creation(event.id)




Tuesday, February 26, 13
Object Caching




Tuesday, February 26, 13
Object Cache Prerequisites




                ‣
                     Your database can't handle the read-load


                ‣
                     Your data changes infrequently


                ‣
                     You can handle slightly worse performance




Tuesday, February 26, 13
Distributing Load with Memcache


                           Memcache 1        Memcache 2        Memcache 3




                           Event   ID   01   Event   ID   02   Event   ID   03
                           Event   ID   04   Event   ID   05   Event   ID   06
                           Event   ID   07   Event   ID   08   Event   ID   09
                           Event   ID   10   Event   ID   11   Event   ID   12
                           Event   ID   13   Event   ID   14   Event   ID   15




Tuesday, February 26, 13
Querying the Object Cache

                      def make_key(model, id):
                          return '{}:{}'.format(model.__name__, id)

                      def get_by_ids(model, id_list):
                          model_name = model.__name__
                          keys = map(make_key, id_list)

                           res = cache.get_multi()

                           pending = set()
                           for id, value in res.iteritems():
                               if value is None:
                                   pending.add(id)

                           if pending:
                               mres = model.objects.in_bulk(pending)

                               cache.set_multi({make_key(o.id): o for o in mres})

                               res.update(mres)

                           return res



Tuesday, February 26, 13
Pushing State




                      def save(self):
                          cache.set(make_key(type(self), self.id), self)


                      def delete(self):
                          cache.delete(make_key(type(self), self.id)




Tuesday, February 26, 13
Redis for Persistence


                             Redis 1           Redis 2           Redis 3




                           Event   ID   01   Event   ID   02   Event   ID   03
                           Event   ID   04   Event   ID   05   Event   ID   06
                           Event   ID   07   Event   ID   08   Event   ID   09
                           Event   ID   10   Event   ID   11   Event   ID   12
                           Event   ID   13   Event   ID   14   Event   ID   15




Tuesday, February 26, 13
Routing with Nydus


                      # create a cluster of Redis connections which
                      # partition reads/writes by (hash(key) % size)

                      from nydus.db import create_cluster

                      redis = create_cluster({
                          'engine': 'nydus.db.backends.redis.Redis',
                          'router': 'nydus.db...redis.PartitionRouter',
                          'hosts': {
                              {0: {'db': 0} for n in xrange(10)},
                          }
                      })


                               github.com/disqus/nydus

Tuesday, February 26, 13
Planning for the Future




Tuesday, February 26, 13
One of the largest problems for
         Disqus is network-wide moderation




Tuesday, February 26, 13
Be Mindful of Features




Tuesday, February 26, 13
Sentry's Team Dashboard




                ‣
                     Data limited to a single team
                ‣
                     Simple views which could be materialized
                ‣
                     Only entry point for "data for team"


Tuesday, February 26, 13
Sentry's Stream View




                ‣
                     Data limited to a single project
                ‣
                     Each project could map to a different DB



Tuesday, February 26, 13
Preallocate Shards




Tuesday, February 26, 13
redis-1


                           DB0   DB1    DB2      DB3   DB4




                           DB5   DB6    DB7      DB8   DB9




Tuesday, February 26, 13
redis-1


                           DB0   DB1    DB2      DB3   DB4




             When a physical machine becomes
            overloaded migrate a chunk of shards
                    to another machine.

                                       redis-2


                           DB5   DB6    DB7      DB8   DB9




Tuesday, February 26, 13
Takeaways




Tuesday, February 26, 13
Enhance your database
                          Don't replace it




Tuesday, February 26, 13
Queue Everything




Tuesday, February 26, 13
Learn to say no
                            (to features)




Tuesday, February 26, 13
Complex problems do not
               require complex solutions




Tuesday, February 26, 13
QUESTIONS?



Tuesday, February 26, 13

Contenu connexe

Plus de it-people

«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...it-people
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАНit-people
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банкit-people
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Coit-people
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНСit-people
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...it-people
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologiesit-people
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn Systemit-people
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologiesit-people
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндексit-people
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...it-people
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognicianit-people
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...it-people
 
ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...
ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...
ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...it-people
 
ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...
ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...
ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...it-people
 
"Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ...
"Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ..."Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ...
"Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ...it-people
 
"Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже...
"Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже..."Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже...
"Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже...it-people
 
"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ
"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ
"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИit-people
 
"Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З...
"Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З..."Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З...
"Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З...it-people
 
"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс
"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс
"Коммуникация в распределенной команде" Жаринов Андрей, Яндексit-people
 

Plus de it-people (20)

«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
 
ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...
ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...
ЗАВИСИМОСТИ В КОМПОНЕНТНОМ ВЕБЕ, ПРИГОТОВЛЕННЫЕ ПРАВИЛЬНО, Гриненко Владимир,...
 
ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...
ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...
ПРАКТИЧЕСКИЙ ОПЫТ ИСПОЛЬЗОВАНИЯ REACT NATIVE + REDUX, Краснояров Станислав, R...
 
"Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ...
"Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ..."Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ...
"Как повысить мотивацию удаленных разработчиков и повысить значимость каждой ...
 
"Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже...
"Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже..."Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже...
"Профессиональное выгорание менеджера проекта" Орлов Александр, Школа менедже...
 
"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ
"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ
"Как поднять цену в разы и не потерять в продажах?" Калаев Дмитрий, ФРИИ
 
"Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З...
"Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З..."Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З...
"Как работать из 20 разных городов с ощущением, что находитесь в 1 комнате" З...
 
"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс
"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс
"Коммуникация в распределенной команде" Жаринов Андрей, Яндекс
 

Dernier

UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024D Cloud Solutions
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsSafe Software
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Will Schroeder
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Brian Pichman
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfAijun Zhang
 

Dernier (20)

UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024Artificial Intelligence & SEO Trends for 2024
Artificial Intelligence & SEO Trends for 2024
 
201610817 - edge part1
201610817 - edge part1201610817 - edge part1
201610817 - edge part1
 
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration WorkflowsIgniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
Apres-Cyber - The Data Dilemma: Bridging Offensive Operations and Machine Lea...
 
Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )Building Your Own AI Instance (TBLC AI )
Building Your Own AI Instance (TBLC AI )
 
Machine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdfMachine Learning Model Validation (Aijun Zhang 2024).pdf
Machine Learning Model Validation (Aijun Zhang 2024).pdf
 

David Cramer: Building to scale

  • 1. BUILDING TO SCALE David Cramer twitter.com/zeeg Tuesday, February 26, 13
  • 2. The things we build will not and can not last Tuesday, February 26, 13
  • 3. Who am I? Tuesday, February 26, 13
  • 7. What do we mean by scale? Tuesday, February 26, 13
  • 8. DISQUS Massive traffic with a long tail Sentry Counters and event aggregation tenXer More stats than we can count Tuesday, February 26, 13
  • 9. Does one size fit all? Tuesday, February 26, 13
  • 11. Postgres is the foundation of DISQUS Tuesday, February 26, 13
  • 12. MySQL powers the tenXer graph store Tuesday, February 26, 13
  • 13. Sentry is built on SQL Tuesday, February 26, 13
  • 14. Databases are not the problem Tuesday, February 26, 13
  • 16. Scaling is about Predictability Tuesday, February 26, 13
  • 17. Augment SQL with [technology] Tuesday, February 26, 13
  • 19. Simple solutions using Redis (I like Redis) Tuesday, February 26, 13
  • 22. Counters in SQL UPDATE table SET counter = counter + 1; Tuesday, February 26, 13
  • 23. Counters in Redis INCR counter 1 >>> redis.incr('counter') Tuesday, February 26, 13
  • 24. Counters in Sentry event ID 1 event ID 2 event ID 3 Redis INCR Redis INCR Redis INCR SQL Update Tuesday, February 26, 13
  • 25. Counters in Sentry ‣ INCR event_id in Redis ‣ Queue buffer incr task ‣ 5 - 10s explicit delay ‣ Task does atomic GET event_id and DEL event_id (Redis pipeline) ‣ No-op If GET is not > 0 ‣ One SQL UPDATE per unique event per delay Tuesday, February 26, 13
  • 26. Counters in Sentry (cont.) Pros ‣ Solves database row lock contention ‣ Redis nodes are horizontally scalable ‣ Easy to implement Cons ‣ Too many dummy (no-op) tasks Tuesday, February 26, 13
  • 27. Alternative Counters event ID 1 event ID 2 event ID 3 Redis ZINCRBY Redis ZINCRBY Redis ZINCRBY SQL Update Tuesday, February 26, 13
  • 28. Sorted Sets in Redis > ZINCRBY events ad93a 1 {ad93a: 1} > ZINCRBY events ad93a 1 {ad93a: 2} > ZINCRBY events d2ow3 1 {ad93a: 2, d2ow3: 1} Tuesday, February 26, 13
  • 29. Alternative Counters ‣ ZINCRBY events event_id in Redis ‣ Cron buffer flush ‣ ZRANGE events to get pending updates ‣ Fire individual task per update ‣ Atomic ZSCORE events event_id and ZREM events event_id to get and flush count. Tuesday, February 26, 13
  • 30. Alternative Counters (cont.) Pros ‣ Removes (most) no-op tasks ‣ Works without a complex queue due to no required delay on jobs Cons ‣ Single Redis key stores all pending updates Tuesday, February 26, 13
  • 33. Streams in SQL class Activity: SET_RESOLVED = 1 SET_REGRESSION = 6 TYPE = ( (SET_RESOLVED, 'set_resolved'), (SET_REGRESSION, 'set_regression'), ) event = ForeignKey(Event) type = IntegerField(choices=TYPE) user = ForeignKey(User, null=True) datetime = DateTimeField() data = JSONField(null=True) Tuesday, February 26, 13
  • 34. Streams in SQL (cont.) >>> Activity(event, SET_RESOLVED, user, now) "David marked this event as resolved." >>> Activity(event, SET_REGRESSION, datetime=now) "The system marked this event as a regression." >>> Activity(type=DEPLOY_START, datetime=now) "A deploy started." >>> Activity(type=SET_RESOLVED, datetime=now) "All events were marked as resolved" Tuesday, February 26, 13
  • 35. Stream == View == Cache Tuesday, February 26, 13
  • 36. Views as a Cache TIMELINE = [] MAX = 500 def on_event_creation(event): global TIMELINE TIMELINE.insert(0, event) TIMELINE = TIMELINE[:MAX] def get_latest_events(num=100): return TIMELINE[:num] Tuesday, February 26, 13
  • 37. Views in Redis class Timeline(object): def __init__(self): self.db = Redis() def add(self, event): score = float(event.date.strftime('%s.%m')) self.db.zadd('timeline', event.id, score) def list(self, offset=0, limit=-1): return self.db.zrevrange( 'timeline', offset, limit) Tuesday, February 26, 13
  • 38. Views in Redis (cont.) MAX_SIZE = 10000 def add(self, event): score = float(event.date.strftime('%s.%m')) # increment the key and trim the data to avoid # data bloat in a single key with self.db.pipeline() as pipe: pipe.zadd(self.key, event.id, score) pipe.zremrange(self.key, event.id, MAX_SIZE, -1) Tuesday, February 26, 13
  • 41. RabbitMQ or Redis Tuesday, February 26, 13
  • 42. Asynchronous Tasks # Register the task @task(exchange=”event_creation”) def on_event_creation(event_id): counter.incr('events', event_id) # Delay execution on_event_creation(event.id) Tuesday, February 26, 13
  • 43. Fanout @task(exchange=”counters”) def incr_counter(key, id=None): counter.incr(key, id) @task(exchange=”event_creation”) def on_event_creation(event_id): incr_counter.delay('events', event_id) incr_counter.delay('global') # Delay execution on_event_creation(event.id) Tuesday, February 26, 13
  • 45. Object Cache Prerequisites ‣ Your database can't handle the read-load ‣ Your data changes infrequently ‣ You can handle slightly worse performance Tuesday, February 26, 13
  • 46. Distributing Load with Memcache Memcache 1 Memcache 2 Memcache 3 Event ID 01 Event ID 02 Event ID 03 Event ID 04 Event ID 05 Event ID 06 Event ID 07 Event ID 08 Event ID 09 Event ID 10 Event ID 11 Event ID 12 Event ID 13 Event ID 14 Event ID 15 Tuesday, February 26, 13
  • 47. Querying the Object Cache def make_key(model, id): return '{}:{}'.format(model.__name__, id) def get_by_ids(model, id_list): model_name = model.__name__ keys = map(make_key, id_list) res = cache.get_multi() pending = set() for id, value in res.iteritems(): if value is None: pending.add(id) if pending: mres = model.objects.in_bulk(pending) cache.set_multi({make_key(o.id): o for o in mres}) res.update(mres) return res Tuesday, February 26, 13
  • 48. Pushing State def save(self): cache.set(make_key(type(self), self.id), self) def delete(self): cache.delete(make_key(type(self), self.id) Tuesday, February 26, 13
  • 49. Redis for Persistence Redis 1 Redis 2 Redis 3 Event ID 01 Event ID 02 Event ID 03 Event ID 04 Event ID 05 Event ID 06 Event ID 07 Event ID 08 Event ID 09 Event ID 10 Event ID 11 Event ID 12 Event ID 13 Event ID 14 Event ID 15 Tuesday, February 26, 13
  • 50. Routing with Nydus # create a cluster of Redis connections which # partition reads/writes by (hash(key) % size) from nydus.db import create_cluster redis = create_cluster({ 'engine': 'nydus.db.backends.redis.Redis', 'router': 'nydus.db...redis.PartitionRouter', 'hosts': { {0: {'db': 0} for n in xrange(10)}, } }) github.com/disqus/nydus Tuesday, February 26, 13
  • 51. Planning for the Future Tuesday, February 26, 13
  • 52. One of the largest problems for Disqus is network-wide moderation Tuesday, February 26, 13
  • 53. Be Mindful of Features Tuesday, February 26, 13
  • 54. Sentry's Team Dashboard ‣ Data limited to a single team ‣ Simple views which could be materialized ‣ Only entry point for "data for team" Tuesday, February 26, 13
  • 55. Sentry's Stream View ‣ Data limited to a single project ‣ Each project could map to a different DB Tuesday, February 26, 13
  • 57. redis-1 DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7 DB8 DB9 Tuesday, February 26, 13
  • 58. redis-1 DB0 DB1 DB2 DB3 DB4 When a physical machine becomes overloaded migrate a chunk of shards to another machine. redis-2 DB5 DB6 DB7 DB8 DB9 Tuesday, February 26, 13
  • 60. Enhance your database Don't replace it Tuesday, February 26, 13
  • 62. Learn to say no (to features) Tuesday, February 26, 13
  • 63. Complex problems do not require complex solutions Tuesday, February 26, 13