25 ポイント 投稿者 GN⁺ 2025-12-01 | 1件のコメント | WhatsAppで共有
  • CRDT(Conflict-free Replicated Data Type, 競合のない複製データ型) は、ネットワーク分断や同時更新の状況でも 調停なしに一貫したデータマージ を可能にする分散データ構造である
  • データマージが 交換法則・結合法則・冪等性 を満たせば、すべてのレプリカは最終的に同一の状態へ収束する
  • 代表的なものとして G-Counter, PN-Counter, G-Set, 2P-Set, OR-Set, LWW-Register, MV-Register, RGA, WOOT, Logoot などがあり、それぞれ異なる 追加・削除・再追加・順序維持 の要件を扱う
  • Delta CRDT は全体状態の代わりに変更分だけを送ることで効率を高め、Garbage Collection はメタデータ蓄積の問題を解決するための重要課題である
  • CRDTは万能な解決策ではないが、可用性が即時一貫性より重要なシステム において強力な選択肢と評価されている

CRDTの基本概念

  • CRDTは 分散環境で同時更新が発生しても、調停なしにマージ可能なデータ構造
    • マージ演算が 可換(commutative)結合的(associative)冪等(idempotent) であれば、すべてのレプリカが同一状態へ収束する
  • Lattice(束) の概念に基づき、状態が常に「上方向」にのみ進むよう設計される
    • 例: G-Counterは各レプリカのカウントを max でマージし、損失のない合算を保証する
  • CRDTには State-based(CvRDT)Operation-based(CmRDT) の2つのアプローチがある
    • CvRDTは全体状態をマージし、CmRDTは操作を伝播する

主なCRDTの種類

  • G-Counter: 増加のみ可能なカウンタ、各レプリカの値を合算
  • PN-Counter: 増加用・減少用のG-Counterを組み合わせ、双方向カウントをサポート
  • G-Set: 追加のみ可能な集合
  • 2P-Set: 追加・削除は可能だが再追加は不可
  • LWW-Element-Set: タイムスタンプに基づき、最新の操作が勝つ
  • OR-Set: 一意タグを用いて 同時追加時もデータ損失なくマージ し、add-winsで動作
  • LWW-Register / MV-Register: 単一値保存用で、LWWは単一の勝者、MVは同時値をすべて保持
  • OR-Map: キーごとにOR-Setを組み合わせたマップ構造
  • RGA / WOOT / Logoot / LSEQ: 順序付きシーケンスデータ向けのCRDT
    • RGAはツリーベース、WOOTは双方向参照ベース、Logoot/LSEQは位置識別子ベース

高度なCRDTの概念

  • Causal CRDTs: バージョンベクタを使って因果関係を追跡し、より正確な競合検出が可能
  • Delta CRDTs: 全体状態の代わりに変更分(デルタ)だけを送信し、ネットワーク効率を向上
  • Tree CRDTs: 階層構造データ(ファイルシステムなど)の複製をサポートし、親子関係の維持が必要
  • Observed-Remove Shopping Cart: OR-SetとPN-Counterを組み合わせたEC向けショッピングカートの例

Garbage Collectionの問題

  • CRDTは収束のためにメタデータを継続的に蓄積するため、無限成長の問題 が発生する
    • 例: OR-Setのタグ、RGAのtombstone
  • 時間ベースの期限切れ, 合意ベースの削除, バージョンベクタベースの因果追跡, メタデータ上限の設定, チェックポイント/リベース など多様な戦略がある
  • 各方式は 安全性(ゾンビ復元防止)空間効率性 の間でトレードオフが必要

性能と選定ガイド

  • CRDTの種類ごとの空間・時間計算量は、レプリカ数、要素数、タグ数などに応じて変わる
    • G/PN-Counterはレプリカ数に比例し、OR-Setはタグ数に比例、RGAはtombstoneが蓄積する
  • Delta CRDT はマージ性能を大きく改善する
  • 選定基準:
    • 追加のみ必要 → G-Counter, G-Set
    • 削除が必要、再追加は不要 → 2P-Set
    • LWWを許容 → LWW-Set/Register
    • 同時更新の保持 → OR-Set, MV-Register
    • 順序維持が必要 → RGA, Logoot
    • ネスト構造 → OR-Map

結論

  • CRDTは 調停なしの収束 を保証するが、メタデータ増加と複雑性 が欠点である
  • 可用性優先のシステム で有用であり、各CRDTは特定の問題タイプに最適化されている
  • 実務では従来型データベースと併用され、ガベージコレクション戦略 が必須
  • 「完璧なCRDT」は存在せず、アプリケーション要件に合った選択 が重要である

1件のコメント

 
GN⁺ 2025-12-01
Hacker Newsの意見
  • CRDTの興味深い点の1つは、単に複数の低レベルCRDTを組み合わせたライブラリではないということ たとえばAutomergeはそれ自体で完全なCRDTであり、数学的証明によって並行実行下でも一貫性を保証する AutomergeチームはIsabelleのような定理証明ツールで設計を検証し、データベース分野の最新の性能手法を適用して、高速かつ正確な実装を目指している リアルタイム協業が必要なSaaS(例: Notion、Figma)を作るなら、複雑な理論を知らなくても協調型データ構造をすぐに適用できる バックエンドはシンプルなkey-valueストレージで十分で、フロントエンドはライブラリ1つで済む

    • AutomergeはRustだけでなくJavascriptやCでも優れたAPIを提供している 私もRedisベースのautomergeライブラリを作ってみたが、pub/subを使って完全な永続同期サーバーを実装できた Webdisのwebsocket機能を活用して、複数ブラウザ間でのドキュメント同期デモもすばやく完成させた
    • Automergeは素晴らしいが、依然として学術的アプローチが強い印象がある より良いDXとCRDTベースのフルスタックDBを求めるなら、Triplit.devを勧める。開発速度はやや遅くなったが、機能は十分完成している
    • Automergeが完全なCRDTだというのは驚くことではない 個人的にはLoroも好きだが、依然としてドキュメントベースの構造なのでクエリエンジンが不足している。欲しいデータを得るには特定のネスト項目を直接指定しなければならない
    • Automergeがセルフホスティングをサポートしていない点は、多くのアプリケーションで致命的な制約だ
  • CRDTの基本から高度な概念までよく整理された記事だった ちなみにRiakは今でもOpenRiakとして維持されている

    • OpenRiakを初めて知ったが、昔の同僚たちが参加しているのを見ると嬉しい。Bashoは本当に優れたエンジニア集団だった
  • この2年間、直接CRDTを開発してきたが、あまりに多くのトレードオフがあると気づき、最終的にIDベースのOTフレームワークへ移行した 今週火曜日にDocnode.devをローンチする予定だ。フィードバックを聞きたい 今後はP2Pが必要な状況に備えて、CRDTモードも追加する計画だ

    • どんなトレードオフが特に問題だったのか気になる
  • CRDTやOTは人々が同じ段落を同時に編集するときの問題を解決しようとする仕組みだが、実際にはそういう状況はほとんど発生しない

    • しかし、こうした機能がないシステムでは、カーソルが同じ文に重なってコンテンツの消失や時間の無駄が生じることがよくある
  • この記事でいうOR-Setは、昔Monotoneが2005年から使っていたマージ方式と似ている 関連資料はMarkMerge文書で見られる

  • CRDTは依然として自分で実装しなければならない領域だ 私も2か月前、diamond typesに着想を得てシーケンスベースのCRDTエンジンを作った AIに助けを求めたが、こうした論理中心の問題にはまったく役に立たなかった LLMが新しいロジックを理解できるか検証するブラックボックステストが必要だと感じる

    • Loroのようなものをそのまま使うのはどうなのか気になる
  • 記事は素晴らしかったが、用語集には**索引(index)**がぜひ必要だと思う

  • CRDTは結局、マージ競合をDBからアプリケーションロジックへ押し出しているだけなのではないかという気がする

    • CRDTはDB内部に設計することもできる。Riakではまさにそれを目指していた 正しく書かれていれば、どの層にあっても自動マージ解決が可能だ
    • 私もPostgreSQLでCRDT手法を適用したグラフDBを構想している 最大の問題はUNIQUE/PRIMARY KEY競合の処理だった 各サーバーにID名前空間を割り当て、最初の作成を勝ちとし、競合時には名前を変更または削除する形で解決できる EAVスキーマを使えば、SQLで再帰CTEによりグラフ探索を簡単に実装できる ただしPostgreSQLにはANY型がないため、属性が多様なオブジェクトを表現しにくく、FOREIGN KEY機能も自分で実装しなければならない それでもEAV構造は継承のようなメタスキーマ設計に向いている PostgreSQLでCRDT型を直接定義できれば理想的だが、現状ではmonoid演算の制限ができない 結局、非キー列向けのCRDTはアプリケーション層で処理する必要がある 要するに、CRDTはRDBMS内部にも実装できるが、ビジネスロジックをどこに置くかによってアプローチは変わる