こんにちは、サイオステクノロジー技術部 武井です。新年一発目の記事になります。
※本記事の英語版はこちら(Click here to read in English)
昨今、クラウドネイティブなアプリケーションが隆盛を迎えております。巷でもよく耳にすると思います。アプリ開発するときに、Virtual Machine使ったら負けとか聞いたこともあります。クラウドネイティブでつくるとモテるとも聞いたこともあります。切ないし、ハードル高いです(´・ω・`)
「クラウドネイティブなアプリケーション」というと、その定義は様々ですが、ここでは、Azureで言えばAzure Functions、AWSで言えばLambdaのようなFaaS(Function as a Service)を使ったアプリケーションであるとします。
そして、ここでよく問題になるのは、これらのFaaSで利用するデータベースは何を使うべきかということです。
一般的には、AzureのCosmosDB、AWSのDynamoDBのような、コネクションレスなデータベースがよいとされています。というのは、FaaSはステートレスです。一つの関数の実行が終わってしまうと、まるで3歩歩いたニワトリみたいに全てのことをキレイさっぱり忘れてしまいます。つまり、ある関数で取得したデータを、別で呼び出された関数で使うということが出来ません(><)(AzureにはDurable Functionsというステキな機能があり、これを使うとステートフルな関数の実行が実現可能ですが、ここでは割愛いたします)。
つまり、ステートレスということは、コネクションのプーリングが出来ないということになります。よって、MySQLやPostgreSQLのようなコネクションが必要なデータベースは、SQLを発行するたびにコネクションが必要になります。しかし、この接続コストが高いと言われてますので、これらのRDBとコネクションプーリングは、まるでトンカツと付け合せのキャベツのように、ともに使われることが非常に多いです。というか、昨今のWebアプリケーションでコネクションプーリングしてないのは、見たことないくらいです。FaaSとRDBの組み合わせは、アンチパターンとも聞いたこともあります。
また、FaaSはリクエストに応じて、どんどんスケールしていくので、RDBのようにSQL発行するたびに接続すると、RDBの方が最大接続数を超えて、限界に達してしまうという問題があります(´・ω・`)
でも、私は、やっぱりRDB使いたい(T_T)と思います。
CosmosDBやDynamoDBは、素晴らしいデータベースと思います。ただし、私の所感では、これらのデータベースはカタログ情報やログなどの、スキーマの変更の可能性が高く、単純な構造の情報を格納するにはモッテコイですが、テーブル間の結合が必要な複雑な業務においては、まだRDBの方が優勢と思っております。
ということで、調査をしてみました。
MySQL(バージョンは5.7)に対して、「select 1」という単純なSQLを発行する処理を、以下の2つのケースにおいて、10000回実行しました。
- SQLを発行するたびに毎回データベースに接続するパターン
- コネクションプーリングをするパターン
SQLを発行するたびに毎回データベースに接続するパティーンのソースコードは以下のとおりです。
コネクションプーリングするパターンのソースコードは以下のとおりです。
結果は以下の通りでした。
- SQLを発行するたびに毎回データベースに接続するパターン:22,497ミリ秒
- コネクションプーリングをするパターン:2,380ミリ秒
こう見てみると、差は大きいのですが、1接続あたりにかかるコストは2msです。
もし、小中規模のシステムであれば、RDBでも十分問題ないのではないかと思っております。
また、FaaSはリクエストに応じて、どんどんスケールしていくので、RDBのようにSQL発行するたびに接続すると、RDBの方が最大接続数を超えて、限界に達してしまうという問題があると申しましたが、Azure Functionsの場合は、batchSizeとSingletonAttirbuteというのを使えば、実行数に制限ができそうです。
https://github.com/Azure/azure-webjobs-sdk/wiki/Singleton
ス(´・ω・`)ゴ(´ε`;)イ( ;∀;)
ということで、ちょっとした検証と考察でした。