52
Распределенные системы в Одноклассниках Олег Анастасьев @m0nstermind [email protected]

Распределенные системы в Одноклассниках

Embed Size (px)

Citation preview

Распределенные системы в Одноклассниках

Олег Анастасьев @m0nstermind [email protected]

1. Абсолютно надежная сеть 2. Мизерная сетевая задержка 3. Практически безлимитная пропускная способность 4. Полностью однородна 5. Изменение топологии сети незаметны 6. Полностью защищена 7. Управляется одним администратором 8. Транспортировка данных почти ничего не стоит

2

В Одноклассниках

1. Абсолютно надежная сеть 2. Мизерная сетевая задержка 3. Практически безлимитная пропускная способность 4. Полностью однородна 5. Изменение топологии сети незаметны 6. Полностью защищена 7. Управляется одним администратором 8. Транспортировка данных почти ничего не стоит

3

Заблуждения разработчиков распределенных систем

https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing[Peter Deutsch, 1994; James Gosling 1997]

4

4ЦОД

150типов

сервисов

8000серверов

В Одноклассниках

5

инженеры

сетевики

админы

разработчики

6

Страница друзей

1. Получить список друзей

2. Применить фильтр

3. Подавить ЧС

4. Получить профили

5. Отсортировать

6. Получить наклейки

7. Посчитать счетчики

7

Простой способ

SELECT * FROM friendlist f, users uJOIN ON f.vertexId=u.userId WHERE u.userId=? AND f.kind=?

AND NOT EXISTS( SELECT * FROM blacklist …)…

• Дружбы

• 12 млрд. связей, 300GB

• 500 000 запросов в сек

8

Простой способ не работает

• Профили пользователей

• > 350 млн. штук,

• 3 500 000 запросов в сек, 50 Gbit

9

Работает так

web frontend API frontend

app server

one-graph user-cache black-list

(микро) сервисы

10

Анатомия (микро) сервиса

Ремотный интерфейс

Логика , Кеши

[ Локальное хранилище ]

1 JVM

11

Анатомия (микро) сервиса

Ремотный интерфейс

https://github.com/odnoklassniki/one-nio

interface GraphService extends RemoteService { @RemoteMethod long[] getFriendsByFilter(@Partition long vertexId, long relationMask);}

interface UserCache { @RemoteMethod User getUserById(long id);}

12

App Server code

https://github.com/odnoklassniki/one-nio

long []friendsIds = graphService.getFriendsByFilter(userId, mask); List<User> users = new ArrayList<>(friendsIds.length); for (long id : friendsIds) { if(blackList.isAllowed(userId,id)) {

users.add(userCache.getUserById(id)); }

}…

return users;

• По таким значениям партиционируем

• У сервиса есть стратегия

• long id -> int partitionId(id) -> node1,node2,…

• Стратегии разные

• Cassandra ring, Voldemort partitions

• или…

13

interface GraphService extends RemoteService { @RemoteMethod long[] getFriendsByFilter(@Partition long vertexId, long relationMask);}

14

Взвешенный квадрат

p = id % 16 p = 0

p = 15

p = 1

N01 N02 N03 . . . 019 020

W =

1

W =

100

N11

node = wrr(p)

SET

15

Проблема в коде

https://github.com/odnoklassniki/one-nio

long []friendsIds = graphService.getFriendsByFilter(userId, mask); List<User> users = new ArrayList<>(friendsIds.length); for (long id : friendsIds) { if(blackList.isAllowed(userId,id)) {

users.add(userCache.getUserById(id)); }

}…

return users;

16

Цена сетевого запроса

0.1-0.3 ms

0.7-1.0 ms

Другой ЦОД

* цена сильно зависит от конкретной инфраструктуры и фреймворков.

задержка = 1.0ms * 2 reqs * 200 друзей = 400 ms

10k друзей задержка = 20 seconds

17

Решение: пакетные запросы

public interface UserCache { @RemoteMethod( split = true ) Collection<User> getUsersByIds(long[] keys);}

long []friendsIds = graphService.getFriendsByFilter(userId, mask);friendsIds = blackList.filterAllowed(userId, friendsIds );List<User> users = userCache.getUsersByIds(friendsIds);

…return users;

18

split & merge

split ( ids by p ) -> ids0, ids1

p = 0

p = 1

N01 N02 N03 . . .

N11

ids0

ids1

users = merge (users0, users1)

19

1. Пропажа клиента

2. Пропажа сервера

3. Потеря исходящего сообщения

4. Потеря входящего сообщения

5. Таймаут сервера

6. Неправильный ответ

7. Произвольный отказ

Что может пойти не так ?

Отказы

Распределенные системы в Одноклассниках

• Отказы невозможно предотвратить, только скрыть

• Отказ произойдет обязательно.

• Ключ к скрытию отказов - избыточность:

• Информации (коды защиты от ошибок)

• Железа (резервирование, реплики, дублирующие схемы)

• Времени (транзакции, retries)

21

Что делать с отказами ?

22

Что сервер сделал ?

Сдаваться нельзя ,

повторить !

Сдаваться , нельзя

повторить !

? ?Добавить друга

• Со стороны клиента - неизвестно

• Что клиент может сделать ?

• Не давать никаких гарантий

• Никогда не повторять запрос. Максимум 1 раз. At Most Once.

• Всегда повторять запрос. По меньшей мере 1 раз. At Least Once.

23

Был ли друг добавлен ?

1. Транзакция в ACID хранилище

• есть мастер, успех однозначен (или проходит или нет)

• возможен атомарный откат

2. Обновление информации в кешах

• много реплик, мастера нет

• атомарного отката нет: возможны частичные отказы

24

Добавляем друга

• Операция применима повторно с тем же результатом

• напр: чтение, Set.add(), Math.max(x,y)

• Упорядоченное Атомарное изменение с контролем дубликата

25

Идемпотентность

Только для Идемпотентных операцийможно применять стратегию“всегда повторять попытку”

https://ru.wikipedia.org/wiki/Идемпотентность

26

Идемпотентность в ACID хранилище

Подружиться

ждем; timeout

Подружиться

Подружились!

Уже друзья ?

Нет, делаем изменения!

Уже друзья ?

Да, ничего не делаем !

27

Идемпотентность через секвенсинг

Подружиться (ОпИД)

Подружились!

УжеДелали (ОпИд) ?

Нет, делаем изменения!

Выписать ОпИД

Примеры ОпИД:

• OpId+=1

• OpId=currentTimeMillis()

• OpId=TimeUUIDhttp://johannburkard.de/software/uuid/

1. Транзакция в ACID хранилище

• есть мастер, успех однозначен (или проходит или нет)

• возможен атомарный откат

2. Обновление информации в кешах

• много реплик, мастера нет

• атомарного отката нет: возможны частичные отказы

28

Добавляем друга

29

Нотификация реплик кешей

add(Friend)

p = 0 N01 N02 N03 . . .

Но без повтора данные реплики рассинхронизируются

Повторять бессмысленно

• Процесс синхронизации данных

• Непрерывно читает изменения из транзакционного хранилищаSELECT * FROM users WHERE modified > ?

• Применяет их в память кеша

• Загружает изменения при старте ноды

• Повтор - ненужен.

30

Синхронизируем кеш через БД

31

Смерть через таймаут

STW GC

Подружиться

ждем; timeout

конец пула потоков

1. Клиенты перестают обращаться к серверу

После Х непрерывных отказов за последнюю секунду

2. Клиенты мониторят доступность сервера

В фоне, раз в минуту

3. И возвращают его в ротацию

32

Вывод из ротации

33

Смерть через торможение

Avg = 1.5msMax = 1.5c24 cpu coresCap = 24,000 ops

Cтавить таймаут = 2.4ms ?

Выводить из ротации если среднее > 2.4ms ?

Avg = 24msMax = 1.5c24 cpu coresCap = 1,000 ops

10,000 ops

34

Спекулятивный повтор

Идемпотентная Оп

wait; timeout

Повторный запрос

Результат операции

• Применим не всегда

• Идемпотентные операциидополнительная нагрузка, трафик

• Балансируем спекуляцию: всегда, >99p, >avg

35

Спекулятивный повтор

• Лучше

• Задержки 99p, средние

• Стабильность системы

Классы, задержка 99p, наносекунды.без спекулятивного повтора (желтый)

и с ним (красный)

^^^ пики до 1 сек ^^^

Больше отказов !

Распределенные системы в Одноклассниках

• Чрезмерная нагрузка

• Чрезмерная паранойя

• Баги

• Люди

• Масштабные аварии

37

Отказ всех реплик сервиса

38

Использовать другие источники,деградация консистентности

Использовать неполные данные, частичная деградация функции

Отключать функцию полностью

Деградировать!

39

Код

interface UserCache { @RemoteMethod Distributed<Collection<User>> getUsersByIds(long[] keys);}

interface Distributed<D>{

boolean isInconsistency(); D getData();}

class UserCacheStub implements UserCache { Distributed<Collection<User>> getUsersByIds(long[] keys) {

return Distributed.inconsistent(); }

}

Тестирование отказов

Распределенные системы в Одноклассниках

41

Свой продукт

“Стандартные” продукты - особенно !

“Админские” маневры

Что тестировать ?

• Что делает:

• Определяет соединения с фронта на сервис

• Отрубает соединения (iptables drop)

• Запускает авто тесты

• Что проверяем

• Что ничего не валится, показываются красивые заглушки

• Сервер стартует

42

Свой продукт: “Горилла”

• Тестовый стенд с синтетический нагрузкой ?

- Топология сети не неизменна

- Сложно воспроизвести профиль нагрузки.

• На продакшене!

• Но чтобы никто не заметил

• Проверяем сценарии отказов и восстановления

43

Как тестировать стандартные решения ?

44

Зеркало

UserCacheProxy

UserCacheImpl UserCacheNew

primary mirror

1. Вызываем primary

2. В отдельном тред пуле mirror. Сравниваем.

3. На основании конфигурации отключаем, переключаем

one-conf

Диагностика

Распределенные системы в Одноклассниках

• Быстрое определение существования аварии

• Локализация проблемы

• Своевременное предупреждение аварий

46

Зачем

• Zabbix

• Cacti

• Операционные метрики

• Имена вызванных операций, напр. “Graph.getFriendsByFilter”

• Количество вызовов, успешность

• Длительность вызовов

47

Авария есть или будет ?

• Оперативную статистику и тренды

• Агрегированное число вызовов и ошибок

• Агрегации задержек

• Среднее, Макс

• Перцентили 50,75,98,99,99.9

48

Что показывают графики

49

Интересные графики

50

Авто поиск аномалий

• Возможностей отказов в распределенных системах безграничны

• Отказы маскируются за счет информации, времени, железа

• При немаскируемых отказах - деградируем !

• Отказы надо тестировать наравне с функционалом

• Отказы нужно диагностировать и предупреждать на проде

51

Краткое содержание предыдущих слайдов

52 Распределенные системы в Одноклассниках, JBreak 2016

slideshare.net/m0nstermind

https://v.ok.ru/publishing.html

http://www.cs.yale.edu/homes/aspnes/classes/465/notes.pdf

Notes on Theory of Distributed Systems CS 465/565: Spring 2014James Aspnes

Тут можно узнать больше: