Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
自作オブジェクトストレージをRustで
Search
noharu36
December 01, 2025
Programming
89
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
54
検証!会津は本当に地盤が硬いのか?
noharu36
0
42
ファミコンに思いを馳せる〜エミュレータ自作を添えて〜
noharu36
0
45
shell自作した話
noharu36
0
41
Rustを布教したい
noharu36
0
58
neofetchよ、永遠に
noharu36
0
43
ISSの軌道計算をRustで
noharu36
0
44
Other Decks in Programming
See All in Programming
Next.js: The final boss of Web Performance
guaca
0
250
AmebaブログはKMPから卒業します
kmars0605
0
190
The Rails Doctrine Decade
koic
2
590
見えないものを探る要求要件定義に必要な基本的思考 / invisible-requirement-thinking
minodriven
15
8.5k
S3 TablesのIcebergデータに、AIエージェントからアクセスしてみた / 20261016developersio2026joetsu-accessing-iceberg-in-s3tables-via-agent
kasacchiful
PRO
0
150
AI時代のコードレビューは人に向けるな、仕組みに向けろ
texmeijin
5
3.7k
作れる、でも消せるか?──安全に「枯らして消す」機能削除術 / Drain, Then Delete
chobishiba
2
640
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
1k
設計次第でAIコードの読む量は減らせる / designing-for-code-reading
minodriven
35
17k
AWSに止められる覚悟してますか?
morizo_1984
2
530
[Rails World 2026] Durable orchestration on Rails: from continuation to workflow
palkan
1
750
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
160
Featured
See All Featured
Between Models and Reality
mayunak
4
500
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
2
2k
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.5k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
490
Joys of Absence: A Defence of Solitary Play
codingconduct
1
550
Writing Fast Ruby
sferik
630
63k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
570
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
600
For a Future-Friendly Web
brad_frost
184
10k
Designing for Performance
lara
612
70k
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 今年もセキュキャンに申し込みました。 年齢的に今回がラストチャンスなので死ぬ気で課題書きます ... 乞うご期待!