17
/ / REDIS. КАК МЫ БОРОЛИСЬ СО СЛОЖНОСТЬЮ Minsk Python Meetup, март 2014 Роман Иманкулов Doist Inc @rdotpy

Redis. Как мы боролись со сложностью

Embed Size (px)

DESCRIPTION

Redis – это инструмент, который должен быть в арсенале любого разработчика. В докладе Роман расскажет, как Redis помогает Todoist обслуживать сотни тысяч пользователей и подкупает простотой и изяществом своих решений. Автор: Роман Иманкулов (компания Doist.io).

Citation preview

Page 1: Redis. Как мы боролись со сложностью

 /   / 

REDIS. КАК МЫ БОРОЛИСЬСО СЛОЖНОСТЬЮ

Minsk Python Meetup, март 2014

Роман Иманкулов Doist Inc @rdotpy

Page 2: Redis. Как мы боролись со сложностью
Page 3: Redis. Как мы боролись со сложностью

реализация — linked lists

REDIS LISTS

Python Redis

>>> foo[1] = "val" LSET foo 1 val

>>> len(foo) LLEN foo

>>> foo.append("val") LPUSH foo val

... и так далее

Page 4: Redis. Как мы боролись со сложностью

REDIS SETSPython Redis

>>> foo = {1, 2, 3, 4} SADD foo 1 2 3 4

>>> set1 & set2 SINTER set1 set2

>>> set1 + set2 SUNION set1 set2

>>> set3 = set1 + set2 SUNIONSTORE set3 set1 set2

... и так далее

Page 5: Redis. Как мы боролись со сложностью

REDIS HASHESPython Redis

>>> foo = {"spam": 1, "egg": 2} HMSET foo spam 1 egg 2

>>> foo['spam'] HGET foo spam

>>> 'spam' in foo HEXISTS foo spam

>>> foo.setdefault('spam', 1) HSETNX foo spam 1

... и так далее

Page 6: Redis. Как мы боролись со сложностью

USER TIMELINE И ЭКСПОНЕНЦИАЛЬНЫЙ РОСТ ДАННЫХ

Page 7: Redis. Как мы боролись со сложностью

USER TIMELINE И ЭКСПОНЕНЦИАЛЬНЫЙ РОСТ ДАННЫХ

Page 8: Redis. Как мы боролись со сложностью

USER TIMELINE И ЭКСПОНЕНЦИАЛЬНЫЙ РОСТ ДАННЫХ

Page 9: Redis. Как мы боролись со сложностью

USER TIMELINE И ЭКСПОНЕНЦИАЛЬНЫЙ РОСТ ДАННЫХfixedlist: решение в пару строк кода

def add_to_timeline(user_id, record, max_records=100): """ добавить новую запись в timeline пользователя """ redis.lpush('timeline:%s' % user_id, record) redis.ltrim('timeline:%s' % user_id, 0, max_records) def get_timeline(user_id): """ вернуть все записи из timeline """ return redis.lrange("timeline:%s" % user_id, 0, -1) .

Page 10: Redis. Как мы боролись со сложностью

АСИНХРОННОЕ ВЫПОЛНЕНИЕ КОМАНДускорение загрузки веб-страницвыравнивание нагрузки на сервергоризонтальное масштабирование

Page 11: Redis. Как мы боролись со сложностью

АСИНХРОННОЕ ВЫПОЛНЕНИЕ КОМАНДsimple_queue: ещё одно решение в пару строк кода

def enqueue(func, *args, **kwargs): """ помещаем функцию вместе с аргументами в очередь """ queue_name = kwargs.pop('_queue', 'simple_queue') redis.lpush(queue_name, pickle.dumps([func, args, kwargs])) def worker(queue='simple_queue'): """ получаем и исполняем элементы из очереди """ while True: _, value = redis.brpop(queue) func, args, kwargs = pickle.loads(value) print func(*args, **kwargs) .

Page 12: Redis. Как мы боролись со сложностью

СБОР И АНАЛИЗ СТАТИСТИКИ. RETENTION ANALYSISкак понять, что вы на правильном пути

Кто из пользователей, активных в последнюю неделю/месяц/год, по-прежнему активен?Кто из сделавших действие X также выполнил действие Y?Как это изменилось после того, как вы реализовали новуюфишку Z?

Page 13: Redis. Как мы боролись со сложностью

СБОР И АНАЛИЗ СТАТИСТИКИ. RETENTION ANALYSISбитовые операции со строками

# отметим активность пользователя 123 28.03.2014 SETBIT active-2014-03-28 123 1 # проверим, были ли 123 активен 1 января 2014 GETBIT active-2014-01-01 123 # посчитем общее количество активных пользователей 1 янв BITCOUNT active-2014-01-01 # кто зарегистрировался вчера, а заплатил сегодня? BITOP AND paid-report signed-up-2014-03-27 paid-2014-03-28 .

Page 14: Redis. Как мы боролись со сложностью

СБОР И АНАЛИЗ СТАТИСТИКИ. RETENTION ANALISYSbitmapist: сбор статистики в Redis

# отметим активность пользователя >>> bitmapist.mark_event('active', 123) # проверим, был ли 123 активен 1 января 2014 >>> activity = bitmapist.DayEvents('active', 2014, 1, 1) >>> 123 in activity True # кто зарегистрировался вчера, а заплатил сегодня? >>> signed_up = bitmapist.DayEvents('signed_up', 2014, 3, 27) >>> paid = bitmapist.DayEvents('paid', 2014, 3, 28) >>> report = bitmapist.BitOpAnd(signed_up, paid) >>> len(report) 5

Page 15: Redis. Как мы боролись со сложностью

СБОР И АНАЛИЗ СТАТИСТИКИ. RETENTION ANALYSISbitmapist.cohort: красивые таблички

>>> dates_data = get_dates_data(select1='task:updated', select2='task:completed', time_group='days') >>> html_data = render_html_data(dates_data, time_group='days') .

Page 16: Redis. Как мы боролись со сложностью

БОЛЬШЕ ИНФОРМАЦИИОфициальная документация RedisRedis-клиент для PythonБлог автора Redis. Salvatore Sanfilippo aka AntirezRedis. The Hacker's Database. Выступление Amir S. на pycon.ruReleasing bitmapist.cohort - or how we saved over $2000/month!

Page 17: Redis. Как мы боролись со сложностью

 /   / 

СПАСИБО! ВОПРОСЫ?Роман Иманкулов Doist Inc @rdotpy