MariaDBからRedisへ一部の機能を移行したこと

記録しておかないとなんで移行したのか忘れてしまいそうだから書いておく。

MySQL5.6からMariaDBへ移行

だいたい毎月100万PVほどあるWEBサイトのデータベースをMySQL5.6からMariaDBへの移行と同時に見直して、一部の機能をRedisへ移行した。

MySQL5.7の5.6からの変更がうちには合わないし、もうMySQLは見限って良さそうだし、MariaDBへ移行することにした。やってみると、インストールと設定の移行はいろいろ細かい調整は必要だったけれど特に問題なく移行できた。

ただ、MariaDBへの移行で同時に解消しないかなあと思っていた問題も引きずってしまった。

DB接続の断続的な切断問題

問題というのは、高負荷になるとDBアクセスが断続的に切れてしまってアプリケーションでの接続し直しが頻発して結果的にWEBサイトのレスポンスが悪くなってしまうこと。MySQL Server goneとかなんとか。

当該サイトは11月ごろからアクセスが増えて12月から1月がピークを迎える。10月中にはなんとかしたかった。

どのSQLで接続が切れるかは特定できない。同じSQLでも切れることもあれば切れないこともある。SQLのログをとりつつどこで起きているのかをリストアップするとだいたい傾向がわかってきた。あれじゃないかなあと予想はしてたところだった。

テーブル定義: CREATE TABLE kvs(k int NOT NULL PRIMARY KEY, v text)

切断が起きる前後のSQLで80%程度をしめていたのが、このテーブルへのこういうSQL: SELECT v FROM kvs WHERE k in (1, 2, … 256)

SQLで柔軟に検索して集めてきたkvsテーブルのキーの値(kvs.v)を最終的にドンと持ってくる部分。inで指定されるキーの数は10個未満が90%だけどたまに256個とかもある。最大512個までに制限しているけど本当は8192個ぐらいはいけるようにしたい。

こういう感じのkvsテーブルへのクエリーが60クエリー/秒程度を超えてくると結構きつく切断と再接続が頻発する。inで指定されるキーの個数は関係あるような気がするけどないような気もする(ちゃんと調べてない)。

アプリケーションではローカルディスクでのキャッシュもしているし、MySQLのクエリーキャッシュも設定しているけど、WHERE句のバリエーションの方が多くてあまりキャッシュにヒットしない。

マシンの性能アップでも解消する部分はあると思うけれど、売り上げを考えるとこれ以上のメモリー増設やCPUアップグレードもやりにくい。RDB的な使い方でもないしなんだかなあと思ってはいたので、いよいよKVSを試してみることにした。

Redisで解決

キーの値をまとめてもってくるkvsテーブルへのアクセス部分だけをRedisに移行することにした。この部分はシンプルだし、アプリケーションの手直しも容易(容易ならなぜ早くやらなかった)。

SELECT v FROM kvs WHERE k in (1, 2, … 256)的なSQL発行をRedisのMGET 1 2 … 256に置き換えるだけでMariaDBの負荷は半分以下になるし、100クエリー/秒を発行してみたけれどRedisはなんでもない。RedisとMariaDBの合計で使うメモリー量はほぼ変わらないか、MariaDBへの接続数が減ったのでその分トータルのメモリ使用量は減っているように見える。いいことばかり。

適材適所ってこと。おわり。