9月26日、Wafrisが「RedisからSQLiteへの再構築」と題したブログ記事を公開した。この記事では、Wafrisが提供するRailsクライアントのバージョン2におけるRedisからSQLiteへの移行について、その決定プロセスやパフォーマンスに関する考察、さらにアーキテクチャ変更の詳細が語られている。
以下に、その内容を紹介する。
移行の背景
Wafrisは、Railsアプリケーションに組み込むことで、HTTPリクエストに対するセキュリティルールのチェックを行うミドルウェアを提供している。Wafrisの初期バージョンであるv1は、ユーザーが自身のRedisデータストアを管理することを前提に設計されていた。この背景には、WafrisがHerokuエコシステムから誕生したことが関係しており、HerokuではRedisの導入が簡単に行える環境が整っていたためだ。さらに、Sidekiqのような成功したプロジェクトを参考に、Redisを使用することで信頼性が高くスケーラブルなソリューションを構築できると考えていた。
しかし、実際の運用においてRedisの管理は思った以上に困難で、特に分散環境や複雑なアプリケーションにおいて、多くのユーザーがデプロイやデバッグに苦労するという問題が発生した。Wafrisの目標である「ユーザーにとって簡単なセキュリティ管理」を実現するには、Redisのような高度なデータベース管理が不要な解決策が必要だと認識された。
SQLiteへの移行理由
Redisは高速で信頼性の高いデータベースであるが、それでもネットワーク遅延や接続管理など、扱う上での負担が多い。特にクラウド環境では、ネットワーク遅延が大きな課題となり、Wafrisのv1クライアントではリクエスト処理のパフォーマンスに影響が出てしまうことがあった。
これに対して、SQLiteはクライアントサーバー型のデータベースではなく、ファイルベースのデータベースであるため、ネットワークのラウンドトリップを完全に排除できる点が大きな魅力だった。SQLiteは、公式ドキュメントで「fopen()と競合する」と記述されているように、単にファイルを開く感覚で扱えるほどシンプルであり、これによりパフォーマンスの向上が期待できる。
Wafrisは、この利点を活かし、v2でRedisからSQLiteに移行することを決断した。
ベンチマーク結果
Wafrisは、RedisとSQLiteのパフォーマンスを独自に比較するベンチマークを行った。その結果、SQLiteはRedisに対して約3倍の速度向上を示した。これは、あくまでローカル環境での結果であり、さらにクラウド環境でのネットワーク遅延を考慮すると、SQLiteがさらに有利になると考えられる。
このベンチマークは、SQLiteとRedisの性能を単純に比較するものではなく、あくまでWafrisのユースケースにおける特定のクエリ処理における速度差に焦点を当てたものである。たとえば、IPアドレスをカテゴリーごとにマッピングする「ホットパス」と呼ばれるクエリタイプでは、Wafrisの運用環境において、SQLiteの圧倒的な優位性が確認された。
アーキテクチャの再設計
Wafrisは、ファイアウォールとしての機能を果たすために、リクエスト処理とその結果のレポート作成を行う。ここで重要なのは、リクエスト処理(「読み込み」部分)が即時に実行される必要があるのに対し、レポート作成(「書き込み」部分)は後回しにできるという点だ。このアプローチにより、リクエスト処理の高速化が最優先課題とされ、SQLiteの採用が決定された。
v1では、ルールの更新がRedisに直接反映される仕組みであったが、v2では定期的にSQLiteのデータベースをダウンロードする方式に変更された。これにより、ユーザーが自身でデータベースを管理する必要がなくなり、導入の簡便さが大幅に向上した。
分散アーキテクチャへの対応
Wafrisは、クラウド環境での分散アーキテクチャにも対応するため、SQLiteを活用している。例えば、アプリケーションの負荷が急増し、複数のインスタンスが起動した場合でも、各インスタンスにローカルなSQLiteデータベースを同期することで、データベース接続のボトルネックを回避できる。
この仕組みにより、Redisのように集中管理されたデータベースが引き起こすスケーリングの問題を解決し、より柔軟でスケーラブルなアーキテクチャを実現している。
まとめ
SQLiteを採用したことで、Wafrisのv2クライアントは多くのユーザーにとって簡単に導入可能なソリューションとなった。ベンチマーク結果やユーザーからのフィードバックを基に、Wafrisは引き続きセキュリティとパフォーマンスの向上に注力している。
詳細は[Rearchitecting: Redis to SQLite]]を参照していただきたい。