Skip to content

Commit 85b6c05

Browse files
author
Udalov Igor
committed
continue
1 parent e4db2d6 commit 85b6c05

File tree

7 files changed

+93
-13
lines changed

7 files changed

+93
-13
lines changed

case-study.md

Lines changed: 93 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
## Что за проект
44

5-
Команда `Unity` в `Rambler&Co`. Мы занимаемся разработкой продуктов, обеспечивающих работу редакций интернет-изданий - таких как [ferra.ru](https://www.ferra.ru/), [secretmag.ru](https://secretmag.ru/) и др.
5+
Команда `Unity` в `Rambler&Co`.
66

7-
Сайты разрабатываются отдельно группой фронтенда. На бэкенде есть набор сервисов, ключевые это:
7+
Мы занимаемся разработкой продуктов, обеспечивающих работу редакций интернет-изданий - таких как [ferra.ru](https://www.ferra.ru/), [secretmag.ru](https://secretmag.ru/) и др.
8+
9+
Сайты разрабатываются отдельно группой фронтенда. На бэкенде есть набор приложений и сервисов, ключевые это:
810

911
### krang
1012

11-
`CMS` на postgres, админка в которой работают редакции.
13+
`CMS` на `postgres`, админка в которой работают редакции (фронт разрабатывается отдельной командой).
1214

1315
### bebop
1416

15-
`mongoDB`, апишка, отдающая данные сайтам.
17+
Апишка на `mongoDB`, отдающая данные сайтам.
1618

1719
## Как долго уже разрабатывается
1820

@@ -22,32 +24,110 @@
2224

2325
### krang
2426

25-
Некоторые операции, такие как создание топика и др. могут занимать существенное время. Наверное, в рамках ДЗ мы попытаемся сконцентрировться на этом приложении.
27+
Некоторые операции, такие как создание топика и др., могут занимать существенное время.
28+
29+
В рамках ДЗ мы попытаемся сконцентрировться на этом приложении.
2630

2731
### bebop
2832

29-
Думаю, часть апи практически никогда не играет роль боттлнека по времени. Как обсуждалось на лекциях, СМИ редко бывают образцом перформанса, но именно за счет того, что сайты как правило тяжеловесны - на их фоне выдача подготовленных данных из `mongoDB` не играет существенной роли.
33+
Думаю, часть апи практически никогда не играет роль боттлнека по времени. Как обсуждалось на лекциях, сайты СМИ как правило тяжеловесны, и на их фоне выдача подготовленных данных из `mongoDB` не будет играть существенной роли.
3034

3135
## Есть ли мониторинг
3236

33-
`New Relic`, `Kibana` с дашбордами и наверное, что-то еще чего пока не видел.
37+
- `New Relic` (подключен `krang`, `bebop` - планируется);
38+
- `Kibana` с дашбордами;
39+
- что-то еще, чего пока не видел.
3440

3541
## Можете ли вы навскидку предположить где в проекте есть что оптимизировать
3642

37-
Когда получил доступ в `NewRelic` заметил на распухающее время `Redis zscan` за последнее 3 месяца - абсолютный лидер в числе тяжеловесных операций в данный момент, задача в работе.
43+
Когда получил доступ в `NewRelic` обратил внимание на распухающее время `Redis zscan`, за последнее 3 месяца - это абсолютный лидер среди тяжеловесных операций. Задача в работе.
3844

3945
## Какова ваша роль в проекте, как давно работаете, чем занимаетесь
4046

41-
Инженер-разработчик группы бэкенд, в компании 1.5 года. Занимаюсь разработкой приложений/сервисов на `Ruby`, вкл. написание тестов, исправление багов и пр.
47+
Инженер-разработчик `Ruby` группы бэкенд, в компании 1.5 года. Занимаюсь разработкой приложений/сервисов на `Ruby`, вкл. написание тестов, исправление багов и пр.
4248

4349
# Оптимизация Redis zscan
4450

45-
`New relic` подсказал, что на первое место самых затратных операций в `krang` занимает `Sidekiq/Social::CountUpdaterJob`.
51+
В последнее время стали наблюдаться проблемы с `redis` и `sidekiq`, возросло кол-во занятых воркеров / ноду.
4652

47-
Top 25 db operations:
53+
Анализ начался с отчетов `New relic`.
54+
55+
Если рассматривать операции по бд, то `redis zscan` в абсолютных лидерах:
4856

4957
<img src="/screenshots/top_20_db_operations_before.png" width="200" />
5058

51-
Обратившись к деталям замечаем отчета, видим, что за последние 3 месяца возрасло время обработки операции `redis zscan`.
59+
Абсолютно большая часть нагрузки приходится на джобу `Sidekiq/Social::CountUpdaterJob`:
60+
61+
<img src="/screenshots/redis_zscan_time_consumption_by_caller.png" width="200" />
62+
63+
Время ответа `redis zscan` в рамках `CountUpdaterJob` за последние 3 месяца увеличилось примерно в 2 раза (1160ms → 2050ms):
64+
65+
<img src="/screenshots/job_breakdown.png" width="200" />
66+
67+
Задача данной джобы заключается в сборе данных о репостах из социальных сетей (в нашем случае `vk` и до недавнего времени - `facebook`).
68+
69+
Наличие `redis zscan` в джобе обусловлено тем, что при постановке джобы мы ищем дубликаты по объектам - с целью минимизации общего кол-ва запросов: требование связано с действующим на текущий момент ограничением `не более 1 запроса в 20 секунд`.
70+
71+
В связи с подключением новых проектов, база за последние 3 месяца выросла - пропорциональным образом (`O(N)`) возросло и время ответа `redis zscan`.
72+
73+
Главной целью стал поиск путей отказа от проверки дублирования и как следствие - использования `redis zscan`.
74+
75+
Первая мысль была в том, чтобы найти ручку `vk`, которая собирает данные по многим топикам сразу, пакетно: возможно, с момента нашего последнего обновления такая возможность появилась, но такая ручка не нашлась.
76+
77+
Потом обратил внимание на то, что требование в установленном на нашей стороне ограничении было актуально для `facebook`, по которому мы в настоящий момент статистику не собираем. Вариант, который я предложил, заключается в отключении `mutex` и исключении проверок на дубликаты - выполнять запросы без ограничений (т.к. со стороны апи `vk` его и нет) - таким образом, мы увеличим кол-во запросов, но это позволит нам решить найденную проблему с `redis zscan`.
78+
79+
До тех пор мы тестируем решение, которое связано с уменьшением таймаута `mutex`. То есть нечто среднее между полным отключением проверки и текущим вариантом.
80+
81+
# Результаты
82+
83+
Уже сейчас мы вернулись к показателям 3-месячной давности, и в джобе:
84+
85+
<img src="/screenshots/job_after.png" width="200" />
86+
87+
И по `redis zscan` в целом:
88+
89+
<img src="/screenshots/redis_zscan_after_2.png" width="200" />
90+
91+
Это сказалось на времени обработки и других важных операциях в системе - например, `topics#create`:
92+
93+
<img src="/screenshots/topics_create.png" width="200" />
94+
95+
Что важно, нагрузка на `redis` в целом также существенно спала:
96+
97+
<img src="/screenshots/redis.png" width="200" />
98+
99+
Мы планируем еще понаблюдать за ситуацией, и после финализации решения установим защитный алерт для защиты метрики.
100+
101+
# Профит
102+
103+
Ориентировочный срок окупаемости - 3 месяца.
104+
105+
```ruby
106+
# стоимость разработчика
107+
dev_cost_rub_month = 4_000 * 100
108+
=> 400000 # (руб/месяц)
109+
dev_cost_rub_day = dev_cost_rub_month / 20
110+
=> 20000 # (руб/день)
111+
112+
# стоимоть требуемого увеличения мощностей (руб)
113+
# NOTE. сейчас redis работает на двух инстансах,
114+
# таким образом, для увеличения мощностей пропорционально возросшей нагрузки,
115+
# нам нужно 2 дополнительных сервера
116+
server_cost_rub_month = 3_000
117+
=> 3000
118+
redis_cost_rub_month = server_cost_rub_month * 2
119+
=> 6000
120+
121+
# стоимость оптимизации (руб)
122+
task_cost_rub = dev_cost_rub_day * 1
123+
=> 20000
124+
125+
# срок окупаемости (месяц)
126+
time_to_profit_month = task_cost_rub / redis_cost_rub_month
127+
=> 3
128+
```
52129

53-
Задача данной джобы заключается в сборе из социальных сетей данных о `shares` (репостов) по статьям. Наличие `redis zscan`
130+
Без учета того, что:
131+
- общая нагрузка на `redis`, по сравнению с показателями 3-месячной давности, спала примерно в 2.5 раза;
132+
- ввод дополнительного сервера не защитил бы нас от возможного возвращения проблемы в будущем;
133+
- не только `CountUpdaterJob`, но и другие операции, использующие `redis`, стали выполняться быстрее.

screenshots/job_after.png

219 KB
Loading

screenshots/job_breakdown.png

370 KB
Loading

screenshots/redis.png

176 KB
Loading
112 KB
Loading
168 KB
Loading

screenshots/topics_create.png

359 KB
Loading

0 commit comments

Comments
 (0)