0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MySQLのreplicationをcustom mackerel-plugin で監視する

Last updated at Posted at 2020-10-17

managed じゃないRDBで replicationするのは、できれば避けて過ごしたい人生ですが、https://qiita.com/masudakz/items/1afafcca1c01d8b9c276 のようなシステム構成もありうるのです。そして replicationを組んでいると、「同期できなくなって障害」というのにいつかは出くわすので、早期警戒体制が欲しくなります。

Mackerel公式の mackerel-plugin-mysql にはmysql.seconds_behind_master.Seconds_Behind_Master があってよさげな感じです。

スレーブ SQL スレッドとスレーブ I/O スレッドの間の時間差 (秒単位)スレーブ SQL スレッドとスレーブ I/O スレッドの間の時間差 (秒単位)

この plugin を入れて Monitors でAlert設定入れて検証してみると、検出できない障害パターンもありました。Master側がAWS RDS でSecurityGroupで、Slaveからの接続を遮断したパターンです。Master側のbinlogが見えないので、遅延を計測できない感じです。MySQLの show slave status にも異常所見が見えない(少なくともAlert出したい時間感覚の中では)。

SecurityGroupの誤設定とか、Master側でのGRANTの誤設定とか、Replication用ユーザを間違って無効化するとか、遅延以外のオペレーションミスでの通信途絶リスクがあるので、これではちょっと足りない。足りないなら自作すればいいのです。

手動の同期トラブルシューティング

すでに開発環境で2度の同期事故経験があるので、どこを見てどう判断したかを思い出してみます。

  1. show slave statusLast_Error
  2. いつ止まったか、高頻度INSERTのTABLEの最終レコードを見る
    SELECT id, ts_created FROM ... ORDER BY id DESC LIMIT 1;
  3. replication用userで Slave - Master の疎通テスト

plugin概要

show slave statusLast Error はどんなパターンが出るか事前には網羅できないし、通信途絶だとそもそも Error 認識できないので custom plugin のスコープからは外します。

高頻度INSERTのTABLEの最終レコードを Slaveからlocalhost と Master(remote)で比較すれば、疎通テストにもなります。疎通失敗で比較不可能だったらその時点でAlert出るようにすればいいでしょう。

plugin骨格

SELECT MAX(${keycolumn}) FROM ${table};

Primary Keyの MAX() で瞬時レスポンスで毎分実行しても負荷にはならない想定です。

sqloption="--silent --skip-column-names --connect-timeout=2"
mysql -h ${host1} -u ${user1} -D ${database} -e "${sql}" ${sqloption}

SQL出力は --silent --skip-column-names で最もシンプルな数値だけにします。
通信障害のときにはさっさと(2秒で)あきらめてほしいので --connect-timeout=2 です。

plugin metric

Alert目的なので SELECT MAX... の結果の差分 max1 - max2 が必須です。
0 が正常、WARN, CRITICAL は1でも10でも1000でもINSERT頻度に応じて。

でもこれだけだと平常時はずっと 0 が続くので、 custom pluginがちゃんと動いているかどうかが不安になります。元の max1, max2 も出力します。ただし、必須の diff とは値域も重要度も違うので、namespace を分割して別グラフにします。

echo replica.key.max1 ${max1}  ${EPOCH}
echo replica.key.max2 ${max2}  ${EPOCH}
echo replica.diff.diff ${keydiff}  ${EPOCH}

replica.key の方を Mackrelで差分グラフにすると Insert数/min のグラフになります。Insert密度があがっていくとどこかでSlaveが追いつけなくなって diff が非0になるでしょう。それが障害か、利用頻度上昇によるものか、判断の一助になることを期待しています。

pluginコード

...
sql="SELECT MAX(${keycolumn}) FROM ${table};"
sqloption="--silent --skip-column-names --connect-timeout=2"

EPOCH=$(date +'%s')
max2=`mysql -h ${host2} -u ${user2} -D ${database} -e "${sql}" ${sqloption}`
max1=`mysql -h ${host1} -u ${user1} -D ${database} -e "${sql}" ${sqloption}`
if [ $? != 0 ]; then
  keydiff=1000
else
  keydiff=`expr $max1 - $max2`
fi
echo replica.key.max1 ${max1}  ${EPOCH}
echo replica.key.max2 ${max2}  ${EPOCH}
echo replica.diff.diff ${keydiff}  ${EPOCH}

全容は https://github.com/masudakz/mackerel-plugin-replica で開示しています。

余談

2018年06月のMy first mackerel pluginの記事が「自助」になりました。面白みの薄い pluginだなあと思いながら当時書いたものですが、自分が読むには自分の記事が一番読みやすい。2つ目を作るのに大いに助けになってくれました。
https://qiita.com/masudakz/items/654d65041a7507e59ee3

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?