用 Automerge 處理 CRDT 問題

上個月看到 Automerge 出了 2.0 版的消息:「Automerge 2.0」,Automerge 這個套件可以幫你處理複雜的 CRDT 結構 (Conflict-free replicated data type)。

可以看到 Automerge 在 2.0 之後的效能改善不少,可以跟 yjs 比較了:

所以練了一下手測界面怎麼用,另外也看一下 conflict 時的處理方式。

這邊先產生 hello, world.,然後做了三個操作,第一個是把開頭的 h 改成 H;第二個是把 world 改成 test;第三個是把 world 改成 example

(() => {
  const Automerge = require('@automerge/automerge');

  let doc1 = Automerge.init();

  doc1 = Automerge.change(doc1, 'Init', doc => {
    doc.text = new Automerge.Text();
    doc.text.insertAt(0, 'h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '.');
  });
  
  let doc2 = Automerge.clone(doc1);
  let doc3 = Automerge.clone(doc1);

  doc1 = Automerge.change(doc1, 'Capitalize', doc => {
    doc.text.deleteAt(0);
    doc.text.insertAt(0, 'H');
  });
  doc2 = Automerge.change(doc2, 'world => test', doc => {
    delete doc.text.deleteAt(7, 5);
    doc.text.insertAt(7, 'test');
  });
  doc3 = Automerge.change(doc3, 'world => example', doc => {
    delete doc.text.deleteAt(7, 5);
    doc.text.insertAt(7, 'example');
  });

  let finalDoc = Automerge.merge(doc1, doc2);
  finalDoc = Automerge.merge(finalDoc, doc3);
  console.log(finalDoc);
})();

這樣最後會產生出 Hello, testexample.

{
  text: Text {
    elems: [
      'H', 'e', 'l', 'l', 'o',
      ',', ' ', 't', 'e', 's',
      't', 'e', 'x', 'a', 'm',
      'p', 'l', 'e', '.'
    ]
  }
}

這結果看起來還行。

只能說以前要是有這些 library 就好了,當初在 KKBOX 做雲端歌單自己搞半天...

ScyllaDB 1.7 要支援 Cassandra 的 Counter 了

Counter 是 Cassandra 裡一個特別的資料型態,總算是要 porting 進 ScyllaDB 了:「Scylla 1.7 introduces experimental support for counters」。

由於資料結構的特殊性,在文章裡有提到想像得到的限制:

  • once deleted, counter column value cannot be used again—this is a consequence of the fact that counters can only be incremented or decremented, they cannot be set to any specific value
  • a table cannot contain both counter and regular columns—without this limitation it wouldn’t be possible to provide proper atomicity and isolation guarantees for updates that modify both counters and regular columns in a single row
  • counter columns cannot be members of primary key
  • updates are not idempotent – in case of a write failure the client cannot safely retry the request
    counter columns cannot have time-to-live set

跟 Cassandra 一樣是透過 CRDT 實做的,行為上會是 eventually consistency:

Scylla implements counters using state-based conflict-free replicated data types (CRDT), which allow atomic operations, like increment or decrement, to be performed locally without the need for synchronization between nodes.

在「Scylla Status and Roadmap」這邊可以看到其他會在 1.7 出現的功能。