Rustと非同期ライブラリーTokioで作成した簡易版Redisを紹介

メモリーセーフなRustと非同期処理ライブラリーTokioで作成した簡易版Redisのコードを紹介する。

松下 康之 - Yasuyuki Matsushita

2021年7月12日 6:00

メモリーセーフなプログラミング言語Rustは、その特性からシステムプログラミングに向いているとされている。Rustの非同期処理の実装はTokioというライブラリーによって行われている。今回は、AWSのイベントRe:InventからAWSのエンジニアによるRustとTokioに関するセッションを紹介する。

動画:AWS re:Invent 2020: Next-gen networking infrastructure with Rust and Tokio

セッションのタイトルは「Next-gen networking infrastructure with Rust and Tokio」というもので、AWSのエンジニアCarl Lerche氏とSean McArthur氏が登壇した。前半のRustに関する概略やメモリーセーフという特徴などの紹介をLerche氏が担当し、後半のキャッシュとして使われるRedisをmini-redisとしてRustで書き直すというチュートリアルは、McArthur氏が担当している。

あらためてRustについて解説

セッションの前半はLerche氏が担当

セッションの前半はLerche氏が担当

パブリッククラウドのトップであるAWSがRustを有望なプログラミング言語として見なしているのは、このセッションがRe:Inventで行われていることからも理解できる。AWSに限らずMicrosoftも積極的にRustを使っていこうという姿勢を見せているし、GoogleもRust Foundationに創立メンバーとして名前を連ねている。このことから、GoogleもGoに並んでRustを有望なシステムプログラミング言語として意識していることがわかる。ちなみにMicrosoftがRust Foundationに参加したことは、Microsoftの公式ブログでも紹介されている。

参考:Microsoft joins Rust Foundation

「性能を犠牲にせずに信頼できるネットワークアプリを構築する」のがRust

「性能を犠牲にせずに信頼できるネットワークアプリを構築する」のがRust

Lerche氏は、ネットワーク処理が必要なアプリケーションを開発する際に「信頼性と同時に高速に稼働する性能が必要である」としてJavaやGoなどを開発言語の候補として挙げたが、Rustをホビー用の開発言語として使ってみたところから、Rustを評価するようになったと解説した。

Java、Goなどを検討したがRustをメモリーセーフと高速性で評価

Java、Goなどを検討したがRustをメモリーセーフと高速性で評価

Rustの特徴を紹介するスライドでは、Rustのデータオーナーシップ(所有)にフォーカスして解説を行った。

Rustの特徴である所有権について解説するLerche氏

Rustの特徴である所有権について解説するLerche氏

変数によってデータが所有され、結果としてデータは明確に「誰(変数や関数)がそれを所有しているのか?」が常に確定されることで、メモリーアクセス違反が起こらない構造であることを強調した。

ソースコードを使ってデータの所有権について解説

ソースコードを使ってデータの所有権について解説

ここではtake_ownershipという関数を定義し、その引数としてfooを使うが、fooが関数内で利用された後は解放されるために、その後同じ関数内でfooを使おうとしても、すでに解放されているために使えないというエラーを、コンパイラーが返すということを解説している。関数が実行され、そのスコープが終了したと同時に変数は解放される仕様であるため、「データを誰がいつまで所有しているのか?」をRustのコンパイラーが厳密にチェックしているという例だ。

非同期ライブラリーであるTokioの紹介

非同期ライブラリーであるTokioの紹介

Lerche氏は、Tokioのコントリビューターの中では最も多くのコミットを行っているエンジニアである。元々はRustでデータベースを作ろうとしたが、Rustの機能には非同期処理を行うライブラリー//ランタイムがなかったため、いわゆるYak Shaving(「ヤクの毛を刈る」という言い回しはある目的を達成するために、その他の多くのことを先にやる必要がある状態を指す)として非同期通信機能であるTokioを開発したことを解説した。

この例ではループの中でプロセスがSpawnされ、非同期にテキストを書き出す処理を行っている。ソケットそのものを閉じる処理がなくても、関数の終了時にRustがデータを解放することでソケットを閉じる処理が行われることを示している。

Tokioの機能の概要

Tokioの機能の概要

TokioはTCP、UDP、UNIX Socketなど非同期通信を行うための必要な機能を提供していることを紹介。

さらにasync/awaitの解説として、hello_worldという関数のソースコードを使って解説。このシンプルなコードがTokioのライブラリーではどのような記述になるのか? を解説したのが次の2枚のスライドだ。

シンプルな非同期処理のコード

シンプルな非同期処理のコード

非同期処理の中身を解説

非同期処理の中身を解説

Tokioのランタイムの構造について解説したスライドでは、複数のWorkerがタスクを非同期に処理することを紹介。先ほどの例で言えば、SpawnされたタスクがこのWorkerの中で処理されているということになるのだろう。

Tokioの構造を解説

Tokioの構造を解説

またデータベース処理に必要なデータをタスク間で共有する処理についても、Spawnされたタスクからデータをmoveする処理ではRustのコンパイラーがエラーを返すという例を使って解説。ここでもRustが持つ厳密なデータ所有権の機能が効果を発揮していると言える。

Rustのコンパイラーのエラーメッセージはわかりやすい

Rustのコンパイラーのエラーメッセージはわかりやすい

Rustのエコシステムの中ではCargoというビルドツールが非常に使いやすいことは知られているが、Rustのコンパイラーもデベロッパーフレンドリーであることは特記すべきポイントだろう。

そしてこの部分のまとめとしてRustは安全で高速、コンパイル時にメモリー関連のチェックが行われるという特性を解説して、後半であるmini-redisを作るというパートを担当するMcArthur氏に交替した。

Rustのまとめ

Rustのまとめ

Redisの簡易版mini-redisをRustで作る

後半を担当するMcArthur氏も、Tokioのコントリビューターとして活動しているAWSのエンジニアだ。ここでは非同期処理の例としてRedisを挙げて、そのコアの機能をRustとTokioで書くとどういうコードになるのか? を検証し、それを教育として使うためのプロジェクトとしてmini-redisを開発したという。

参考:tokio-rs/mini-redis: Incomplete Redis client and server implementation using Tokio

mini-redisを解説するMcArthur氏

mini-redisを解説するMcArthur氏

最初に、インメモリーのキーバリューストアデータベースであるRedisの特性を解説した。キャッシュとして使われることの多いRedisだが、C言語で書かれていること、多くのプロセスから非同期並列に接続され、データの書き込み、検索、読み込みなどの機能を満たしていることを説明した。

mini-redisの解説。Redisのサブセットの機能をRustとTokioで実装

mini-redisの解説。Redisのサブセットの機能をRustとTokioで実装

その上で今回のプロジェクト、mini-redisの概要を紹介した。mini-redisはRedisを置き換えるものではなく、あくまでもRustによる非同期通信をデベロッパーに理解してもらうための教育が目的であると解説した。

実際のコードは、上記のGitHubのリポジトリーを参照してほしい。前半のLerche氏によるデータを複数のプロセスで共有するために必要な処理について、クライアントからのコネクションを処理するサーバー側のコードを使って紹介した。

インメモリーデータベース作成するコードの例

インメモリーデータベース作成するコードの例

データベースを構造体として定義する際にMutexを追加して排他制御の実装が必要であることを解説。他にも、Arcというスマートポインターを使ってデータを共有する仕組みを使っている。

db構造体にMutexを指定

db構造体にMutexを指定

RustにおけるArcについては以下のQiitaの記事が参考になるだろう。

参考:Rustの `Arc` を読む(1): Arc/Rcの基本

次のスライドでは標準のMutexについて解説を行っている。

Mutexについて解説

Mutexについて解説

ここからインメモリーデータベースへのデータ書き込み、読み込みのソースコードを解説し、Rustであれば簡潔に記述できることを説明した。

GETの例

GETの例

SETの例

SETの例

最後にRedisとmini-redisでSET、GETのベンチマークを実施し、C言語で書かれたRedisとほぼ同様の性能を出していることを解説した。ここではメモリーセーフでありながら高速に実行できるRustとTokioの組み合わせが、安全性と高速性を両立したソフトウェアを開発できるという例として強調された形になった。

Redisとmini-redisの性能比較。ほぼ同等と言える

Redisとmini-redisの性能比較。ほぼ同等と言える

McArthur氏は、RustとTokioの組み合わせによって安全で高速なソフトウェアが実現できることを再度紹介して、セッションを終えた。GitHubのmini-redisのリポジトリーのソースコードを見れば、多くのコメント行によって初めてコードを見るデベロッパーへの教育という目的を目指していることがわかる。

mini-redisのようなコードがあれば、RustとTokioによるリアルなアプリケーション開発に初めて取り組むエンジニアにとっても参考になるだろう。

安全で高速なソフトウェアを実現できるRustとTokio

安全で高速なソフトウェアを実現できるRustとTokio

この記事のキーワード :

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30