サーバーレスで作る共同編集サービス

やまたつ @devio_day1
2023-04-11

  • 山本達也(やまたつ)
  • クラスメソッド株式会社
  • CX事業本部 デリバリー部
  • Twitter: @yamatatsu193
  • GitHub: @yamatatsu
  • コミュニティ活動:
    • JAWS-UG CDK支部
  • OSSコントリビューション:
    • aws-cdk

もくじ

  1. イントロ
  2. デモ
  3. 構成および技術紹介
  4. サーバーレス化の課題と解決
  5. Yjsの永続化

イントロ

ある日の社内slack

😎「miro作るのって難しいの?」

😤 「それはそうですよ!
websocketで状態共有して競合解決して
undo/redoと無限平面とあとあと」

😇 (でも本当はよくわからん。。。)

🤔(なんかむずかしそう。。。)

🤔 何が難しそう?

  • 無限平面(WebGL)
  • 共同編集 ← 今日話すのはここ

デモ

構成紹介

Yjs紹介

Yjsとは共同編集におけるデータコンフリクトを解決するためのライブラリです。
Yjsとは共同編集におけるデータコンフリクトを解決するためのライブラリです。CRDT(Conflict-free Replicated Data Type)というデータ構造を用いて、データの整合性を保証します。
Yjsとは共同編集におけるデータコンフリクトを解決するためのライブラリです。CRDT(Conflict-free Replicated Data Type)というデータ構造を用いて、データの整合性を保証します。CRDTはGoogle Docsなどで使われているOT(Operational Transformation)という手法と比較されることが多いです。OTは編集操作を順番に適用していくことで、データの整合性を保証します。そのため順序を保証する中央サーバーが必要になります。一方CRDTは編集操作を順番に適用することなく、結果整合的にデータの整合性を保証します。そのため順序を保証する中央サーバーが不要で、分散システムに適した手法です。
Yjsとは共同編集におけるデータコンフリクトを解決するためのライブラリです。CRDT(Conflict-free Replicated Data Type)というデータ構造を用いて、データの整合性を保証します。CRDTはGoogle Docsなどで使われているOT(Operational Transformation)という手法と比較されることが多いです。OTは編集操作を順番に適用していくことで、データの整合性を保証します。そのため順序を保証する中央サーバーが必要になります。一方CRDTは編集操作を順番に適用することなく、結果整合的にデータの整合性を保証します。そのため順序を保証する中央サーバーが不要で、分散システムに適した手法です。またOTに比べて複雑なデータ構造を管理することに向いていると言われています。YjsはJavaScriptで実装されたCRDTライブラリで、ブラウザ上で動作する共同編集サービスを構築するためのライブラリです。各ユーザーの編集操作をYjsのデータ構造に適用することで、update(更新)と呼ばれるバイナリデータが発行されます。このバイナリデータを各ユーザーが受け取ることで、たとえ同時に編集されたとしても、データの整合性を保証することができます。updateの適用は可換であり冪等なので通信上で輻輳があってもデータが破損することはありません。
Yjsとは共同編集におけるデータコンフリクトを解決するためのライブラリです。CRDT(Conflict-free Replicated Data Type)というデータ構造を用いて、データの整合性を保証します。CRDTはGoogle Docsなどで使われているOT(Operational Transformation)という手法と比較されることが多いです。OTは編集操作を順番に適用していくことで、データの整合性を保証します。そのため順序を保証する中央サーバーが必要になります。一方CRDTは編集操作を順番に適用することなく、結果整合的にデータの整合性を保証します。そのため順序を保証する中央サーバーが不要で、分散システムに適した手法です。またOTに比べて複雑なデータ構造を管理することに向いていると言われています。YjsはJavaScriptで実装されたCRDTライブラリで、ブラウザ上で動作する共同編集サービスを構築するためのライブラリです。各ユーザーの編集操作をYjsのデータ構造に適用することで、update(更新)と呼ばれるバイナリデータが発行されます。このバイナリデータを各ユーザーが受け取ることで、たとえ同時に編集されたとしても、データの整合性を保証することができます。updateの適用は可換であり冪等なので通信上で輻輳があってもデータが破損することはありません。共同編集で必須なundo/redo機能もサポートされており、加えてWebRTC, WebSocketなどのプロトコル、IndexedDB, LevelDBなどのストレージ、React, Vueなどのフレームワーク、monaco, CodeMirrorなどのエディターなど、さまざまな技術との組み合わせに対応しています。

Yjsとは

  • 共同編集のライブラリ
  • update(更新)を送り合うことで同期する
  • 結果整合的で分散システムに向いてる
    • 冪等で可換
  • JavaScriptで実装されている
  • undo/redoをサポート

サーバーレス化の課題と解決

課題.1

既存のy-websocket serverは
サーバーの状態に依存している

課題.2

Amazon API Gateway WebSocket API は
path parameterをサポートしていない

課題.3

既存のy-websocket clientは
subprotocolをサポートしていない

課題.4

既存のy-dynamodbは
sdk v2しかサポートしてないし、遅いし、整合性の課題があるし、メンテが止まっている

課題を解決したコードがこちら

https://github.com/yamatatsu/yjs-lab/

y-dynamodb-for-sdkv3

  • sdk v3対応
  • 書き込み速度が100倍向上
  • flush操作の整合性が向上

Yjsの永続化

何がいけなかったのか?

  • 整合性の解決をDBではなくComputeが担っている
  • DynamoDBは悲観ロックやロック待ち書き込みをサポートしていない
  • 楽観ロックはできる。なので成功するまで何度も読み出して書き込むことはできる。

じゃあどうする?🤔

整合してようがしてなかろうが書き込んでしまえばいい💡

読み込んでから整合させればいい💡💡

updateを全部保存してしまえばいい💡💡💡

データ、無限に増えていいの?🤔

flushという操作があります💡

flush

  • データ読み出し時に行う
  • すべてのupdateを取り出し、Y.Docに書き込む
  • 完成したY.Docのスナップショットを他の更新と同じように保存する
  • 最後にflushされたupdateたちを削除する

これによりYjsは分散コンピューティング上での永続化の課題を解決できました🎉

Yjsで楽して共同編集機能を作りましょう!

rust実装のYrsもあるよ!

ご清聴ありがとうございました 🙏

サーバーレスで構築された共同編集サービスのデモを用いて、構成例や利用したOSSなどを紹介します。 特に、共同編集データをDynamoDBに保存するOSSを実装、公開した知見をもとに、共同編集データ永続化の設計観点を、分散システム、冪等性、結果整合性、富豪的解決法などをキーワードに説明します。