Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
自作オブジェクトストレージをRustで
Search
noharu36
December 01, 2025
Programming
75
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
自作オブジェクトストレージをRustで
noharu36
December 01, 2025
More Decks by noharu36
See All by noharu36
皆さんはHaskellをご存知です_しかし皆さんはHaskellが読めません_.pdf
noharu36
0
44
検証!会津は本当に地盤が硬いのか?
noharu36
0
34
ファミコンに思いを馳せる〜エミュレータ自作を添えて〜
noharu36
0
37
shell自作した話
noharu36
0
34
Rustを布教したい
noharu36
0
39
neofetchよ、永遠に
noharu36
0
37
ISSの軌道計算をRustで
noharu36
0
32
Other Decks in Programming
See All in Programming
Cloudflare is Agents
chimame
0
180
Claude CodeとAgentCore Gatewayを繋ぐ際の認証認可 / Authentication and authorization when connecting Claude Code with AgentCore Gateway
har1101
2
350
FastAPI の並行処理モデルを完全に理解する
hoto17296
8
2.5k
Dockerfile CMD for Node.js
grazie1999
0
110
使いながら育てる Claude Code — 開発フローの1コマンド化 × 繰り返し指摘の自動仕組み化
shiki_kakaku
0
1.9k
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
12
19k
リアルな遅延を測る仕様
kota_yata
1
120
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
360
What's New in Android 2026
veronikapj
0
270
源内ハンズオン概要編
hideg
0
210
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
960
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
680
Featured
See All Featured
Crafting Experiences
bethany
1
260
Docker and Python
trallard
47
4.1k
A Modern Web Designer's Workflow
chriscoyier
698
190k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
250
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
810
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
470
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.8k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
RailsConf 2023
tenderlove
30
1.5k
Balancing Empowerment & Direction
lara
6
1.2k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
550
Un-Boring Meetings
codingconduct
0
390
Transcript
自作オブジェクトストレージを Rustで 休学中 harukun
自己紹介 { name: 能島明希 handle: harukun origin: 広島->岡山->大阪->東京->会津 tech: {
front-end: React+TS backend: Rust, Go etc: Rust, Haskell Rust: Rust } favorites: Tobacco, BoyScout, Rust, Neovim, NixOS Twitter(x): https://twitter.com/pieceofharuki Blog: https://zenn.dev/haru_blog }
オブジェクトストレージとは • データをオブジェクト単位で扱う • ディレクトリのような階層構造は持たず、データは巨大な記憶領域の中にフラットに格納される • 保存できるオブジェクト数に(理論上)制限がない • 一般的に分散ストレージで構成されており、スケールアウトしやすい •
他のストレージシステムと比べて低速であり、更新頻度が高く高速な読み書きを要求するデータの管理に は向いてない
オブジェクトストレージ自作してみた
注意 このLTは、オブジェクトストレージを使ったことがない人間が、オブジェクトストレージって多分こんなもんじゃね?(鼻ホ ジ)と言いながら作った制作物を発表するLTです。 開発にあたって、dwango様とmirrativ様の技術ブログを参考にしました https://dwango.github.io/articles/frugalos/ https://tech.mirrativ.stream/entry/2023/10/20/115202
Why Rustでものづくりしたかった(いつも通り) ↓ DBよくわかんない、理解するために自作するか、 NoSQLならSQLパーサーなくて楽そうやな ... ↓ さくしょーがオブジェクトストレージ作れって言った ↓ まあオブジェクトストレージも全くわかんないからちょうどいいし作るか
...
技術スタック
外部クレート [dependencies] reed-solomon-erasure = "6.0.0" bytes = "1.10.1" tokio =
{ version = "1.44.2", features = ["full"] } anyhow = "1.0.98" axum={ version = "0.8.3", features = ["multipart"] } serde = { version = "1.0.219", features = ["derive"] } serde_json = "1.0.140" futures = "0.3.31" tokio-util = { version = "0.7.14", features = ["io"] } mime_guess = "2.0.5" tower-http = { version = "0.6.2", features = ["limit"] } rayon = "1.10.0" tracing = "0.1.41" tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] } sqlx = { version = "0.8", features = [ "runtime-tokio", "sqlite" ] } chrono = "0.4.41" dotenvy = "0.15.7" [dependencies.uuid] version = "1.16.0" features = ["v4"]
軽く説明 • reed_solomon_erasure: イレイジャーコーディングの部分をよしなにやってくれる • tokio, tower_http, axum: Rustの非同期ランタイムとかWebフレームワークとか。
サーバーをたてる上で使う部分 • tracing: ログをいい感じに出してくれるやつ • sqlx: DB接続ライブラリ。ORMではない。マクロを使うとコンパイル時チェックが優秀 • anyhow: エラー管理ライブラリ。エラーの型を脳死で統合できるので良くも悪くも楽できる
構成 • benches/ : ベンチマークを計測するためのコードを置く • migrations/ : マイグレーションファイル •
src/handler/ : REST APIに対応する関数とか • src/db.rs : DBにアクセスするやつ • src/encode.rs , src/decode.rs : データのエンコード・デコー ド、ストレージへの格納・ロードの処理 • src/server.rs : サーバーの設定とか
ルーティングの例 #[instrument] fn object_routes() -> Router<MetadataStore> { Router::new() .route( "/bucket/{:bucket_name}/{:object_id}",
post(post_object).get(get_object).delete(delete_object), ) .layer(DefaultBodyLimit::disable()) .layer(RequestBodyLimitLayer::new(3 * 1024 * 1024 * 1024)) } /bucket/{bucket_name}/{object_id}に POST、GET、DELETEのメソッドをはやしている Bodyのサイズを3GBまでに制限している
POSTの処理 sample.mp4 (100mb) post_object( Path((bucket_name, object_id)), State(store), mut multipart )
save_shards(shards,object_id) store_data(bytes, id) encode_file(content) /bucket/{bucket_name}/{object_id}に POSTリクエストを送る multipart形式でデータを受け取る。 bucketが存在しているかをチェックし、メタデータを作成 してDBに登録する。 データをBytesに変換してメモリに読み込み、 store_data 関数の引数にする bytesをbytesmutに変換し、 encode_file関数の引数にする reed-solomon符号を用いてデータを分割し、 Result<Vec<BytesMut>を返す ベクタのインデックスと object_idを組み合わせてハッシュ化し、 その値を用いて(おそらくなるべくなんとなく)データが均一に分 散されるようストレージに保存する
IntoResponse post, deleteの関数の返り値は特定の型ではなく Impl IntoResponseとしている src/handler/api.rsで共通のレスポンスの型を定義し ている #[derive(Debug, Serialize)] struct
ApiResponse<T> { status: String, data: T, } #[derive(Debug, Serialize)] struct ApiError { status: String, message: String, } pub enum ApiResult<T> { Success(StatusCode, T), Error(StatusCode, String), } impl<T: Serialize> IntoResponse for ApiResult<T> { fn into_response(self) -> axum::response::Response { match self { ApiResult::Success(status, data) => ( status, Json(ApiResponse { status: "success".to_string(), data, }), ) .into_response(), ApiResult::Error(status, message) => ( status, Json(ApiError { status: "error".to_string(), message, }), ) .into_response(), } } }
できたもの https://github.com/noharu36/t3
今後 • メタデータをもっと豊富に(あと多分メタデータの管理方法間違ってる) • 認証・認可 • 格納先をちゃんとストレージにする(ロードバランサーとかも必要かも) • S3互換のAPIの実装
まとめ • 今までやってこなかったサーバー周りを Rustでかけてよかった • DB(SQL)、オブジェクトストレージへの理解度がほんの少し上がった • 次はNoSQL DB自作しようかな (俺が作ったのは本当にオブジェクトストレージなのか
...???)
THE YODAN 今年もセキュキャンに申し込みました。 年齢的に今回がラストチャンスなので死ぬ気で課題書きます ... 乞うご期待!