「Redash遅くね？」と言われた時に確認すること

本記事は、 [Redash Advent Calendar 2018](https://adventar.org/calendars/3299) の22日目の記事です！
[去年も書いた](https://qiita.com/katsuhisa__/items/32030e052583b4d51d9e)ので、今年も書けて嬉しいです。

## はじめに
本記事では、Redash遅くね？と言われた時に確認することをまとめます。後述しますが、**小規模チームでの運用**を想定して書いています。

不足点や、こうすると良いよ、というご提案あれば、[@katsuhisa__](https://twitter.com/katsuhisa__) まで教えていただけると嬉しいです。追記します。

## 環境
* [AWS AMI 版のRedash](https://redash.io/help/open-source/setup#aws)
* Redash バージョン `5.0.2`
* Ubuntu 16.04

## 状況的な意味での環境
* 小規模チームでの運用（queries <100, users <20）
* 最大同時利用者数 <5

大規模チームで運用していると、本記事で扱う内容と別問題が起こるかと思いますので、あまり参考にならないかもしれません。

## 確認する流れ
1. 前提として意識しておくこと
2. Redash Web UI から、Queries Queueを見てみる
3. 詳細を調べて対処する

順を追って説明します。

### 1. 前提として意識しておくこと
まず、第一に知るべきは、 **Redashがどのようなミドルウェアで構成されているか** です。

* Nginx: Webアプリのリバースプロキシ
* Gunicorn: Webアプリサーバ（RedashのWebアプリを動かす）
* PostgreSQL: DB(各種情報の保持)
* Celery: 分散タスクキュー（クエリを非同期実行する）
* Redis: （Cerelyのメッセージブローカー）
* Supervisor（プロセス管理ツール）

また、上記に加えて、　**クエリ実行の流れ** もおさえておくとよいです。

@ariarijp さんのスライドをどうぞ。

https://speakerdeck.com/ariarijp/bu-ta-miip-mu-redash?slide=15

このあたりが頭に入っていると捗ります。

また、上記とあわせて、「Redash遅くね？」の原因となりうる箇所も理解しておくとよいでしょう。

https://speakerdeck.com/ariarijp/bu-ta-miip-mu-redash?slide=16

・・・と、いろいろ書きましたが、小規模チームでの運用で問題になりやすいのは、**「クエリを投げたら詰まってしまう」**事象です。
そして、「詰まる」の詳細は、**「Celery のワーカーが（様々な要因で）反応しなくなってしまう」**というのが、私が過去経験したケースの大半です。

ここまでお読みいただき、「あ、うちはこれとは違うな」と感じた方は、以降を読み進めても、あまり得るものはないかもしれません。

### 2. Redash Web UI から、Queries Queueを見てみる
さて、まず「Redash遅くね？」と言われた時に、最初に見ると良いなーと私が思っているのは、Queries Queueです。

#### Queries Queueとは
実行しているクエリの状態を見ることが出来ます。
例えば、クエリが実行中であれば、 `executing_query` というStateでクエリが表示がされます。
まずは、Queries Queueをながめ、どういう実行状態か？を確認します。

#### Queries Queueはどこから見るの？
Adminグループに所属するユーザーでログインし、`/admin/queries/tasks`を見る。
Web UI からたどるのであれば、以下をご参照ください。

* Adminグループに所属するユーザーでログインし、「System Status」を選択

<img width="219" alt="スクリーンショット 2018-12-13 20.19.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/137214/24f331ff-97e2-0877-4ba0-f3c38aedd99b.png">

* Queries Queueのタブを選択

<img width="1264" alt="スクリーンショット 2018-12-13 20.21.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/137214/220c9c08-b01e-a46f-ae0b-8b4ce174db62.png">


### 3. 詳細を調べて対処する
Queries Queue に`executing_query`があった場合、処理が正しく進行している状態かどうかを確認したいです。もし、クエリが正しく進行しているのであれば、それは「Redashが遅い」でもなんでもなく、単に実行したSQLに時間がかかっているだけだと判断することができるからです。


#### CeleryがCPUを食いつぶしていないか
その判断をするために私がまず確認をするのは、`top`コマンドでCPU使用率をCeleryが食いつぶしていないかを確認します。もし、そうなっている場合、Celeryのワーカープロセスが異常であると判断し、当該のプロセスをリスタートすればよいでしょう。
もしくは、単にCeleryのワーカーをkillしても構いません。（Supervisorがプロセスを新しく立ち上げてくれます。）

```
kill -9 <プロセスID>
```

この事象は、ある程度長くRedashを運用している方は、一度は遭遇したことがあるのではないでしょうか。

#### Celeryのゾンビプロセスを掃除する
次に、Celeryのプロセスが残り続けている事象もよく起こる問題です。
まず、`/etc/supervisor/conf.d/redash.conf` の中を覗き、celeryのワーカーがいくつ起動しているのが正常な状態かを確認しておきましょう。

例えば、以下のようになっている場合、`-c2`なので同時実行ワーカープロセスは2つ、それに加え、beatのプロセスとメインプロセスで合計4つになります。

<adhocクエリ起動例>
`command=/opt/redash/current/bin/run celery worker --app=redash.worker --beat -c2 -Qqueries,celery --maxtasksperchild=10 -Ofair` 


また、Redashに詳しい方はご存知だと思いますが、Redashは、adhocなクエリとは別に、scheduledなクエリを処理するためのCeleryのプロセスを起動しています。

<scheduledクエリ起動例>
`command=/opt/redash/current/bin/run celery worker --app=redash.worker -c2 -Qscheduled_queries --maxtasksperchild=10 -Ofair`

ですので、上記のクエリ起動例であれば、4プロセス*2 で合計8プロセス起動しているのが正常な状態・・・といった感じです。

そのため、 `ps` コマンドでCeleryプロセスを眺め、明らかなゾンビプロセスを見つけた場合は、それもkillしましょう。1プロセスだけ起動タイミングがはるか昔になっていることがあります。
これもRedash運用が長い人にとってはお馴染みかもしれません。

####  プロセスをkillした場合、Redisもきれいにしておく
さて、前述したような対応をした場合、最後にRedisの中身も掃除しておく必要があります。
なぜなら、いちばんはじめに前提知識で記載した通り、Redashは、CerelyのメッセージブローカーとしてRedisを使用しており、Celeryのプロセスを`kill`した場合、メッセージブローカー側にゴミが残ってしまう可能性があるからです。

掃除の仕方は、以下をご参考ください。

<例>

```
$ redis-cli
> zrange query_task_trackers:in_progress 0 -1
> zrem query_task_trackers:in_progress query_task_tracker:<query_hash>
```

in_progress のステータスのクエリのハッシュを取得し、削除しています。

以上です！

Redash運用ユーザーのお役に立てれば幸いです！

Celeryのコードに深く潜って、CPU100%にはりつく事象の詳細やゾンビプロセスが生じる要因は、今後調べてみたいと思っています。