Upload
tanya-denisyuk
View
7.093
Download
2
Embed Size (px)
Citation preview
План доклада
• Начать с какого-нибудь банального утверждения
• Раскритиковать проверенную временем технологию
• Представить собственное сомнительное решение
• ???
• PROFIT!!!
Response Times: The 3 Important Limits
• до 0.1 секундыПользователь манипулирует объектами напрямую
• до 1 секундыПользователь замечает задержку, но может работать с интерфейсом
• 10 секундПредел терпения
Источник: http://www.nngroup.com/articles/response-times-3-important-limits/
Индексы для коллекций ресурсов
Например github.com issues GET /issuesGET /user/issuesGET /orgs/:org/issuesGET /repos/:owner/:repo/issues
(и фильтры для milestone, state, assignee, creator, labels …)
Sync API• Дополняет, а не заменяет RESTful API
• Клиенты: толстые, локально хранят копию данных с сервера
• Сервер: туповат, просто предоставляет API для получения кусочков данных
• Примеры применения: • списки задач, заметок и т.д. • панели управления ресурсами • системы мониторинга, мгновенных уведомлений
Sync API в Todoist• Основной API для всех официальных клиентов c 2012 года
• Работает на Redis и MySQL
• Обслуживает 1’000’000 активных пользователей
• Синхронизирует задачи между устройствами за 5 секунд
• Поддерживается командой из трех разработчиков
Sync API. Реализация
id content … deleted seq_no
1 foo FALSE 56
2 null TRUE 83
Таблица с объектами
seq_no:<uid1> 85
seq_no:<uid2> 167
Счетчик в Redis для каждого пользователя
Sync API. INSERT/UPDATE/DELETEПолучить следующий Sequence Number INCR seq_no:<uid>
Манипулируя объектом, не забыть обновить seq_no INSERT INTO table (…, seq_no) VALUES (..., <seq_no>) UPDATE table SET … seq_no = <seq_no> UPDATE table SET … is_deleted = TRUE, seq_no = <seq_no>
Sync API. Первоначальная синхронизацияЗапрос GET /api/sync
Подготовка ответа MySQL: SELECT ... WHERE user_id=<uid> AND deleted=FALSE Redis: GET seq_no:<uid>
Ответ {"seq_no": <seq_no>: "objects": [...]}
Sync API. Частичная синхронизацияЗапрос GET /api/sync?seq_no=1234
Подготовка ответа MySQL: SELECT ... WHERE user_id=<uid> AND seq_no > 1234 Redis: GET seq_no:<uid>
Ответ {"seq_no": <seq_no>: "objects": [...]}
Sync API. Почему это хорошо
• Простая реализация
• Данные рядом с клиентом
• Один индекс в базе
• Push уведомления
Sync API. Что можно сделать лучше?
• Не хотим хранить удаленные объекты в базе!
• Не хотим B-tree индекс, который O(log n)
slave master клиентыsync
создаем буфер
готовим данные для отправки
Буфер
1 2 3 4
команды: A, B, C
A B C
возвращаем данные,
A, B, C, offset=3команды: D, E, F
DE F5 6
sync, offset=3
DEF, offset=6
Sync API v2. Redis backlogСчетчик. Храним seq_no самого последнего сообщения в очереди INCR seq_no:<uid>
Очередь. Добавляем id измененного объекта и подрезаем очередь RPUSH queue:<user_id> <object_id> LTRIM queue:<user_id> -1 -100
СерверКлиент Другие клиенты
счетчик буфер (redis list, max length: 4, хранит только ids)
создать объекты A, B, C
3
GET /api/sync
{seq_no: 3, objects: [A, B, C]}создать D, изменить А, B
A1
B2
C3
D4
A5
B6
6
GET /api/sync?seq_no=3
{seq_no: 6, objects: [D, A, B]}
...GET /api/sync?seq_no=1
Error: full sync required
Sync API v2. Redis backlog• Индексы только по id и user_id.
Время поиска и вставки O(1)
• Очередь фиксированной длины, и только для активных клиентов. Память О($), где $ — количество платящих клиентов, 1.5Kb на очередь из 200 сообщений 11 млн клиентов на 16Gb (m4.xlarge, 126$ в месяц)
• Клиент должен быть готов к "полной перезагрузке"
• Используется Evernote и Google Calendar?
Sync API. Ограничения localStorageUser Agent Размер (тыс
символов)Чтение из 10k (мс)
Чтение из 500k (мс)
Чтение из макс (мс)
Chrome 33 5,120 3 20 1,026
Chrome Mobile 32
5,120 28 164 1,066
Firefox 27 5,120 1 14 143
IE 11 4,883 15 32 872
Opera 19 5,120 7 36 313
Mobile Safari 7
2,560 16 37 104
Safari 7 2,560 11 44 177
Источник: https://www.stevesouders.com/blog/2014/02/11/measuring-localstorage-performance/
Ограничения localStorage. Что делать?
• Считывать данные в память при первой загрузкедля ускорения доступа
• Не хранить данные в JSONпреобразование списка объектов в CSV экономит до 50% места
• Сжимать данныеСм. http://pieroxy.net/blog/pages/lz-string/index.html, до 95%
• Использовать вытесняющий кеш