2026-05-01から1ヶ月間の記事一覧
はじめに 決済APIにリクエストを投げた。3秒待っても応答がない。タイムアウト。 クライアントがリトライした。結果、数十件の二重課金が起きた。 発覚したのは、翌朝のカスタマーサポートへの問い合わせラッシュだった。 ネットワークタイムアウトの曖昧さ …
はじめに コンシューマを再起動した翌朝、ダッシュボードの数値が跳ね上がっていた。 バグを疑った。半日追ってから、processing time集計がバックログの再処理で壊れただけだとわかった。 event timeとprocessing time。同じ時刻ではない。 2つの時刻 スト…
はじめに 個々のバックエンドのp99は10msで安定していた。 APIゲートウェイのp99だけが、それを大きく超えていた。 計測はできていた。fan-outの確率的増幅が原因だと気づくまでに、数週間かかった。 「p99が10msだから大丈夫」という誤解 レイテンシの議論…
はじめに ノードAとBのログを、タイムスタンプでソートした。 因果関係が、平然と逆転していた。 50msのNTPずれで、秒間数千リクエストのシステムでは数百のイベントが入れ替わる。物理時計は嘘をつく。 物理時計は嘘をつく ここでいう「時計」は、腕時計や…
はじめに 「このロック、リースが切れたらどうなるんですか?」 デザインレビューで聞いた。分散ロックを取った後、リモートAPIを叩いてからリソースに書き込むジョブスケジューラの設計だった。 設計者と自分は、その先の答えを持っていなかった。 死んでい…
はじめに シェルスクリプト2行で、データベースが書ける。書き込みはO(1)、これ以上速くならない。 10億行になった瞬間、読み取りが破綻する。grepが全行を舐めて死ぬ。 RocksDBのソースには、Memtable、SSTable、Compactionが並ぶ。読むより、書いて確かめ…
はじめに PostgreSQLのREPEATABLE READは、Snapshot Isolationだ。 MySQLのREPEATABLE READは、それと違う何かだ。同じ言葉が、異なる挙動を指す。 ドキュメントを読むのをやめた。自分でMVCCストアを書き、各異常を手で再現することにした。 www.cockroachl…
はじめに マルチリーダーで、同じキーに同時書き込みが起きた。どちらの値が「正しい」のか。 「コンフリクトが起き得ないデータ構造」という言葉を、最初に読んだとき魔法に聞こえた。 実装した。魔法ではなく、数学だった。そしてそれには代償があった。 e…
はじめに キャッシュクラスタへノードを足すたびにヒット率が壊滅する。最初にこの問題へ出会ったのは、memcachedクラスタのスケーリングを調べていたときだった。hash(key) % Nの何が悪いのか、当時は正直よくわからなかった。実装して計測してみると、問題…
はじめに 書き終えた要件は、書き終えた瞬間から古び始める。 古びた要件と新しい要件を、AIは同列に扱う。「置き換え済み」と書いた印は、AIにとってはただの文字列でしかない。 要件を言葉にする話を第1部で、要件を動くものに散らす話を第2部で書いてきま…
はじめに RocksDBのソースを読んでいて、SSTableごとにBloom filterが挟まっている箇所に出くわした。概念は知っていたが、パラメータの導出を自分で追ったことはなかった。数式を眺めるだけでは全然理解できない悲しい子なので、Rustでゼロから書いて理論値…
はじめに 「Rust はコンパイルが遅いから」。技術選定の議論で、私はこの一言で打ち切られたことが何度かある。性能でも安全性でもなく、開発時のフィードバックループの遅さだ。コードを書いて保存したら画面に反映される、というサイクルが Rust にはない…
はじめに 長年、動いた DB を覗くと、たいていこういうレコードが眠っています。 { "order_id": 12345, "is_paid": true, "payment_id": null } is_paid = true なのに payment_id は null。 ドメイン上、 同時に成立してはいけない組み合わせ が静かに残り…
はじめに エディタで .unwrap() を書いた瞬間、 clippy が黄色い波線を引きます。match で variant が漏れた瞬間、コンパイラが赤い波線を引きます。これは魔法ではなく、 rust-analyzer が rowan で構文木を作り、その上をルールが歩いている というしくみ…
はじめに ※この筋肉はイメージであり現実の肉体とは乖離がある場合があります。 ある誕生日の朝、通知が、なかった。 母親からだけ、メッセージが来ていた気がする。 俺の人生はLINEの量で決まるかと嘯きながら、LINEの誕生日表示を非公開にした。20代の、ど…
はじめに Builder パターンで「url を設定する前に build() を呼んでしまった」事故を、 コンパイルエラーで止める 書き方があります。type-state pattern と呼ばれています。PhantomData を使って builder の進捗状態を型に乗せる、 Rust 固有の idiom です…
はじめに 「String に独自メソッドを追加したい」「外部クレートの型に1メソッドだけ生やしたい」場面があります。Rust の orphan rule のせいで、外部クレートの型に外部クレートのトレイトを直接実装するのは無理です。代わりに 自分のトレイトを定義して…
はじめに Rust で「グローバル変数を遅延初期化したい」となったとき、長らく lazy_static! クレートが定番でした。今 (2026年) はもう不要です。標準ライブラリの LazyLock (1.80+) と OnceLock (1.70+) で全部書けます。マクロや外部依存も要りません。 た…
はじめに 入力をそのまま返すか、一部書き換えてから返すか、関数の中で判定する場面があります。素直に書くと「変更しない場合も無駄に String::clone() してしまう」、または「&str を返したいが、変更があった時は所有データを返したい」というジレンマに…
はじめに UserId と OrderId を取り違えてバグを生み出す経験は、String で識別子を扱っていれば誰しもあります。Rust では newtype で別の型に分けるだけで、コンパイラに止めてもらえます。さらに PhantomData を組み合わせれば、「JPY と USD を足し算す…
はじめに ドキュメントは、書いた瞬間から腐っていく。 読まれない。検証されない。更新されない。それでも、要件と呼ばれ続けている。 第1部では、要件を言葉にする規律について書きました。引き出し、観察し、ジョブを見極めながら、業務領域の言葉で書く…
はじめに ゼロ割り、ゼロサイズ確保、ゼロインデックス。「ゼロでない数値」を期待する場面はあちこちにあります。これを runtime チェックではなく 型 で保証できる仕組みが NonZero<T> です。 Rust 2024 edition で書き味がさらに素直になりました。これまで</t>…
はじめに Rust で「ライブラリのエラー型をどう設計するか」は永遠のテーマです。素朴な答えは2つあります。 アプリケーションなら anyhow で済ませる ライブラリなら thiserror で型付きエラーを返す これは2026年でも変わりません。この記事は「ライブラリ…
はじめに Rust 1.88 (2025年) で if let chain が安定化されました。2024 edition のコードでは積極的に使えます。 && で if let 条件を連結できるようになり、ネストした if let を平らに書ける構文です。短い変更ですが、効果は大きく出ます。 何を解決す…
はじめに Rust の let-else 構文は、Rust 1.65 (2022年) で安定化された機能です。古くからある機能ですが、2024 edition のクリーンなコードベースでは多用されます。clippy の manual_let_else ルールも 2024 では使うことが推奨されます。 「Option が No…
はじめに Rust で Option や Result から値を取り出すとき、つい .unwrap() を書いてしまう場面があります。動くし短い。だから書く。だけどそのコードは、エラー時にスタックトレースなしで panic します。本番で踏むと 「どこで何の理由で死んだのか」 が…