Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PyCon Ukraine 2014 – Redis as Main database for Python project (russian)

PyCon Ukraine 2014 – Redis as Main database for Python project (russian)

Использование Redis как основной базы данных для Python проекта, ORM, основные проблемы и решения.

Max Klymyshyn

November 02, 2014
Tweet

More Decks by Max Klymyshyn

Other Decks in Programming

Transcript

  1. О чем разговор О чем это ‣ При чем тут

    Python ‣ Почему Redis ‣ Инструменты в Python ‣ Redis и ORM
  2. Типичный проект При чем тут Python ‣ Завязан на SQL

    базу ‣ Используется Django или Что-то + SQLAlchemy ‣ Реже используют Mongo или Couchdb ‣ Кеш – memcached или redis
  3. При чем тут Python ‣ Уперлись в скорость создания индекса

    CouchDB ‣ Постепенно мигрируем с CouchDB в Redis ‣ Активно используем Redis для очередей ‣ Активно используем для Pub/Sub ‣ Акционные предложения целиком в Redis
  4. Проблемы При чем тут Python ‣ Реляционные и объектные базы

    работают с диском, а значит медленнее RAM ‣ Встроены разные механизмы кеширования ‣ Все в конечном итоге упираются в скорость записи или чтения
  5. Дешево, но быстро При чем тут Python ‣ Время программистов

    уходит на оптимизации ‣ Любые тормоза в работе уменьшают конверсию/количество довольных клиентов ‣ Память сейчас стоит намного меньше времени
  6. Python? При чем тут Python ‣ Часто Redis уже интегрирован

    как cache backend ‣ Там сессии, кеш вьюх и все стандартизированное фреймворком
  7. Python + Redis и продвинутые проекты При чем тут Python

    ‣ Структуры данных типа set, hash ‣ Cчетчики ‣ Очереди ‣ Pub/Sub
  8. Традиционные базы данных Redis & Persistence ‣ Гарантируют целостность ‣

    Размер базы упирается в размер диска ‣ Шардинг ‣ SQL или ORM - абстракция над ним
  9. Под капотом Redis & Persistence ‣ По умолчанию данные записываются

    в Linux раз в 30 секунд (упрощенно) ‣ Но можно настроить базу на сброс на диск сразу после вызова записи ‣ И это будет очень медленно
  10. Redis & Persistence Клиент шлет данные на запись База получает

    данные на запись (в памяти) База вызывает write (данные в буфере ядра) Ядро сбрасывает буферы на диск (данные попадают в кеш диска) Диск физически записывает данные
  11. Redis & Persistence Клиент шлет данные на запись База получает

    данные на запись (в памяти) База вызывает write (данные в буфере ядра) Ядро сбрасывает буферы на диск (данные попадают в кеш диска) Диск физически записывает данные POWER OUTAGE PROCESS KILL
  12. Fsync Redis & Persistence ‣ Можно увеличить надежность с помощью

    системного вызова fsync ‣ Но это приведет к постоянной записи на диск ‣ Пользователи будут недовольны
  13. Снимки Snapshottings ‣ Snapshottings (или RDB) - простейший режим персистентности

    в редисе ‣ Создает снимок во времени при достижении определенных условий: таймаута и количество измененных ключей. Напр. 100 новых записей и последний снимок создан более, чем 2 минуты назад
  14. Ограниченная надежность Redis & Persistence ‣ Надежность ограничена условиями ‣

    Гарантирует, что запись будет целостной в конкретный момент времени (в append-only режиме) ‣ Все, что записано до создания следующего снимка будет утеряно
  15. AOF – Append Only File Redis & Persistence ‣ Это

    основная система персистентности в Redis ‣ Суть туповата – если операция записи модифицирует данные, эта операция записывается в AOF ‣ Лог точно в том же формате, что и клиентская команда
  16. Интересные возможности Redis & Persistence ‣ Благодаря тупизне можно транслировать

    команды на другой инстанс с помощью netcat ‣ После рестарта Redis проходится по всем командам из AOF, это может быть долго
  17. Always growing file Redis & Persistence ‣ AOF всегда растущий,

    если он становится слишком большим - Redis пересоздает его целиком ‣ Вместо чтения старого файла, Redis создает минимальный набор команд для воспроизведения данных, которые находятся в памяти
  18. Надежность Redis & Persistence ‣ Пока новый AOF файл генерируется,

    текущие транзакции дописываются в старый файл и в буфер ‣ Когда новый файл готов команды из буфера дописываются в него и старый файл подменяется новым
  19. Режимы AOF Redis & Persistence ‣ appendfsync no – fsync

    не выполняется вовсе, в AOF запись выполняется с помощью write ‣ appendfsync everysec – данные записываются с помощью write и синхронизируются с диском раз в секунду с помощью fsync ‣ appednfsync always – самый меденный способ записи. Fsync + write, но делается group commit
  20. Что предлагают другие DB Redis & Persistence ‣ PostgreSQL: fsync,

    synchronous_commit ‣ MySQL InnoDB: innodb_flush_log_at_trx_commit
  21. Инструменты Инструменты ‣ redis-py - самый распространенный клиент ‣ tornado-redis

    - async redis client for Tornado ‣ txredis - async redis client for Twisted ‣ redis-proxy - read/write splitting proxy ‣ nydus - clustering & routing library by Disqus
  22. Транзакции Инструменты def client_side_incr(pipe): current_value = pipe.get('OUR-SEQUENCE-KEY') next_value = int(current_value)

    + 1 pipe.multi() pipe.set('OUR-SEQUENCE-KEY', next_value) r.transaction(client_side_incr, 'OUR-SEQUENCE-KEY')
  23. Pub/Sub Инструменты p = r.pubsub() p.subscribe('my-first-channel', 'my-second-channel', …) # Processing

    messages while True: message = p.get_message() if not message: sleep(1) continue # .. do something with message ### Sending messages r.publish('my-first-channel', 'some data')
  24. Server Side Scripting on LUA Инструменты r = redis.StrictRedis() lua

    = """ local value = redis.call('GET', KEYS[1]) value = tonumber(value) return value * ARGV[1]""" multiply = r.register_script(lua) r.set('foo', 2) multiply(keys=['foo'], args=[5]) # 10
  25. Атомарность Инструменты ‣ Скрипты на Lua выполняются атомарно – команды

    Redis не будут выполнены до конца обработки скрипта. Медленные скрипты нет смысла запускать ‣ Та же история с MULTI/EXEC – команды выполняются атомарно ‣ Если процесс redis убит посреди транзакции, файл AOF может быть поврежден, для починки есть тулза redis-check-aof
  26. Типы данных в Redis Типы данных ‣ List ‣ Set

    ‣ SortedSet ‣ Hash ‣ Bitmap ‣ HyperLogLogs
  27. ROM

  28. Основные фичи ROM ‣ Декларативно определять модель ‣ JSON поля,

    datetime ‣ Составные уникальные ключи ‣ ForeignKey, OneToMany, ManyToOne ‣ Выборки по типу Django ORM ‣ Full-word, Prefix, Suffix, Pattern индексы
  29. Simple Model ORM import redis import rom rom.util.set_connection_settings(host=‘myhost', db=7) #

    All models to be handled by rom # must derived from rom.Model class User(rom.Model): email = rom.String( required=True, unique=True, suffix=True) salt = rom.String() hash = rom.String() created_at = rom.Float(default=time.time)
  30. Отношения ORM class MyModel(Model): col = ManyToOne('OtherModelName') class MyModel(Model): col

    = ForeignModel(DjangoModel) class MyModel(Model): col = OneToMany('OtherModelName', on_delete='restrict') ocol = OneToMany('ModelName', on_delete='no action')
  31. Выборки ORM user = User(email_addrss='[email protected]') user.save() # session.commit() or session.flush()

    works too user = User.get_by(email_address='[email protected]') user = User.get(5) users = User.get([2, 6, 1, 7]) user = User.get_by(email_address='[email protected]') # gets up to 25 users created in the last 24 hours users = User.get_by( created_at=(time.time()-86400, time.time()), _limit=(0, 25))
  32. Еще инструменты ORM ‣ redisco – Python Containers and Simple

    Models for Redis (+1 ORM) ‣ analytics – realtime trackings of different events in the system ‣ restmq - redis queue engine with REST interface
  33. Redis - это база данных с предсказуемым результатом выполнения любой

    команды. Для каждой команды есть конкретная сложность, описанная в документации. Все что нужно – калькулятор и скорость RAM What the business?
  34. Кто пошел на это Realworld examples ‣ YouPorn, Pornhub &

    whole porn holding ‣ Cgraigslist ‣ SkillPages ‣ Disqus – аналитика и метрики ‣ HipChat – XMPP state ‣ Twitter
  35. Data sources 1. http://redis.io/topics/cluster-spec 2. http://redis.io/topics/persistence 3. http://oldblog.antirez.com/post/redis-persistence- demystified.html 4.

    https://muut.com/blog/technology/redis-as-primary- datastore-wtf.html 5. https://chris-lamb.co.uk/posts/distributing-locking-python- and-redis 6. https://charlesleifer.com/blog/powerful-autocomplete- with-redis-in-under-200-lines-of-python/ 7. http://restmq.com