COLLABORATIVE TEXT
EDITING
INTRODUCTION
Bartosz Sypytkowski
▪ @Horusiath
▪ b.sypytkowski@gmail.com
▪ bartoszsypytkowski.com
 What’s the problem?
 Opertional Transfromations
 Replicated Growable Arrays
 How do we replicate?
 How to optimize this thing?
 How to collect garbage?
AGENDA
PROBLEM
Alice Bob
CONTINOUS CONTINOUS
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINOUS
ins(8, ?)
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINUOUS
CONTINOUS
ins(8, ?)
CONTINOUS?
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINUOUS
CONTINOUS
ins(8, ?)
CONTINOUS?
ins(5, U)
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINUOUS
CONTINOUS
ins(8, ?)
CONTINOUS?
CONTINUOUS?
ins(5, U)
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINUOUS
CONTINOUS
ins(8, ?)
CONTINOUS?
ins(8, ?)
CONTINUOUS?
ins(5, U)
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINUOUS
CONTINOUS
ins(8, ?)
CONTINOUS?
CONTINUOU?S
ins(8, ?)
CONTINUOUS?
ins(5, U)
PROBLEM
Alice Bob
CONTINOUS
ins(5, U)
CONTINUOUS
CONTINOUS
ins(8, ?)
CONTINOUS?
CONTINUOU?S
ins(8, ?)
CONTINUOUS?
ins(5, U)
WHY NOT
JUST USE
CENTRAL
DATABASE
?
1. A single contributor can issue hundreds
of ops/min.
2. Lag cannot be visible for a naked eye.
3. We should accept periodic
disconnections, the longer the better.
4. … and maybe push the cost to the
edges?
OPERATIONAL
TRANSFORMATION
As seen in Google Docs, Apache Wave and Etherpad
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S C O N T I N O U S
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S
ins(6, U, A)
C O N T I N O U S
ins(9, ?, B)
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S
ins(6, U, A)
C O N T I N U O U S
+1 +1 +1 +1 +1
C O N T I N O U S
ins(9, ?, B)
C O N T I N O U S ?
+1 +1
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S
ins(6, U, A)
C O N T I N U O U S
+1 +1 +1 +1 +1
C O N T I N O U S
ins(9, ?, B)
C O N T I N O U S ?
+1 +1
ins(9, ?, B)
C O N T I N U O U S
+1 +1 +1 +1 +1
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S
ins(6, U, A)
C O N T I N U O U S
+1 +1 +1 +1 +1
C O N T I N O U S
ins(9, ?, B)
C O N T I N O U S ?
+1 +1
C O N T I N U O U S ?
ins(9, ?, B)
+1 +1 +1 +1 +1 +1
+1 +1
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S
ins(6, U, A)
C O N T I N U O U S
+1 +1 +1 +1 +1
C O N T I N O U S
ins(9, ?, B)
C O N T I N O U S ?
+1 +1
C O N T I N U O U S ?
ins(6, U, A)ins(9, ?, B)
+1 +1 +1 +1 +1 +1
+1 +1
C O N T I N O U S ?
+1 +1
OPERATIONAL
TRANSFORMATION
Alice Bob
C O N T I N O U S
ins(6, U, A)
C O N T I N U O U S
+1 +1 +1 +1 +1
C O N T I N O U S
ins(9, ?, B)
C O N T I N O U S ?
+1 +1
C O N T I N U O U S ? C O N T I N U O U S ?
ins(6, U, A)ins(9, ?, B)
+1 +1 +1 +1 +1 +1
+1 +1
+1 +1
+1 +1 +1 +1 +1 +1
“Unfortunately, implementing OT sucks”
PROBLEM WITH OPERATIONAL
TRANSFORMATION
- Joseph Gentle (Google Wave, ShareJS)
REPLICATED GROWABLE ARRAY
WE NEED IMMUTABLE INDEXES
1:AABSOLUTE INDEX ID UNIQUE REPLICA ID
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
ins(6A, U, 10A)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S
ins(9A, ?, 10B)
1A 2A 3A 4A 5A 6A 7A 8A 9A
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
ins(6A, U, 10A)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
ins(9A, ?, 10B)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S ?
1A 2A 3A 4A 5A 6A 7A 8A 9A 10B
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
ins(6A, U, 10A)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
ins(9A, ?, 10B)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S ?
1A 2A 3A 4A 5A 6A 7A 8A 9A 10B
ins(9A, ?, 10B)
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
ins(6A, U, 10A)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
ins(9A, ?, 10B)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S ?
1A 2A 3A 4A 5A 6A 7A 8A 9A 10B
C O N T I N U O U S ?
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A 10B
ins(9A, ?, 10B)
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
ins(6A, U, 10A)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
ins(9A, ?, 10B)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S ?
1A 2A 3A 4A 5A 6A 7A 8A 9A 10B
C O N T I N U O U S ?
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A 10B
ins(6A, U, 10A)ins(9A, ?, 10B)
REPLICATED
GROWABLE
ARRAY
Alice Bob
C O N T I N O U S
ins(6A, U, 10A)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
ins(9A, ?, 10B)
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S ?
1A 2A 3A 4A 5A 6A 7A 8A 9A 10B
C O N T I N U O U S ?
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A 10B
C O N T I N U O U S ?
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A 10B
ins(6A, U, 10A)ins(9A, ?, 10B)
HOW TO INSERT AT THE SAME POSITION?
HOW TO INSERT AT THE SAME POSITION?
6A < 6B
MAKE POSITIONS COMPARABLE
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B)
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B)
10B > 10A
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N N U O U S
1A 2A 3A 4A 5A 6A 10B 10A 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B)
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N N U O U S
1A 2A 3A 4A 5A 6A 10B 10A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B) ins(6A, U, 10A)
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N N U O U S
1A 2A 3A 4A 5A 6A 10B 10A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B) ins(6A, U, 10A)
10A < 10B
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N N U O U S
1A 2A 3A 4A 5A 6A 10B 10A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B) ins(6A, U, 10A)
10A > 7A
REPLICATED
GROWABLE
ARRAY
INSERT AT THE SAME
POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N N O U S
1A 2A 3A 4A 5A 6A 10B 7A 8A 9A
C O N T I N N U O U S
1A 2A 3A 4A 5A 6A 10B 10A 7A 8A 9A
C O N T I N N U O U S
1A 2A 3A 4A 5A 6A 10B 10A 7A 8A 9A
ins(6A, U, 10A) ins(6A, N, 10B)
ins(6A, N, 10B) ins(6A, U, 10A)
HOW TO INSERT AND DELETE AT THE
SAME POSITION?
HOW TO INSERT AND DELETE AT THE
SAME POSITION?
TOMBSTONES
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
ins(6A, U, 10A) del(6A)
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
ins(6A, U, 10A) del(6A)
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
ins(6A, U, 10A) del(6A)
del(6A)
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
ins(6A, U, 10A) del(6A)
del(6A)
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
ins(6A, U, 10A) del(6A)
ins(6A, U, 10A)del(6A)
REPLICATED
GROWABLE
ARRAY
INSERT AND DELETE AT
THE SAME POSITION
Alice Bob
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I N U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
C O N T I N O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I O U S
1A 2A 3A 4A 5A 6A 7A 8A 9A
C O N T I U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
ins(6A, U, 10A) del(6A)
ins(6A, U, 10A)del(6A)
C O N T I U O U S
1A 2A 3A 4A 5A 6A 10A 7A 8A 9A
REPLICATED GROWABLE
ARRAYS
HOW TO REPLICATE OPERATIONS?
• We need to ensure that every operation
was received by every node…
• … and at the same time we cannot wait
for confirmation before displaying it.
IS THERE ANY PROBLEM?
• We need to ensure that every operation
was received by every node…
• … and at the same time we cannot wait
for confirmation before displaying it.
IS THERE ANY PROBLEM?
EVENTSOURCING
Alice
(1, ins(1A, ‘H’, 2A))
(2, ins(2A, ‘e’, 3A))
(3, ins(3A, ‘l’, 4A))
(4, ins(4A, ‘l’, 5A))
(5, ins(5A, ‘o’, 6A))
PARTIALLY
ORDERED
LOG
Alice
. . .
ins(6A, ‘o’, 7A)
ins(7A, ‘u’, 8A)
ins(8A, ‘s’, 9A)
ins(6A, ‘u’, 10A)
ins(6A, ‘n’, 10B)
Bob
. . .
ins(6A, ‘o’, 7A)
ins(7A, ‘u’, 8A)
ins(8A, ‘s’, 9A)
ins(6A, ‘n’, 10B)
ins(6A, ‘u’, 10A)
Other “features”?
1. File format?PARTIALLY
ORDERED LOG
Other “features”?
1. File format?PARTIALLY
ORDERED LOG
Other “features”?
1. File format?
2. History (undo/redo)
PARTIALLY
ORDERED LOG
REPLICATED GROWABLE
ARRAYS
ANY PROBLEMS?
BLOCK-WISE REPLICATED
GROWABLE ARRAYS
… OR HOW TO ADD MORE THAN ONE CHAR AT THE TIME
METADATA OVERHEAD
H
1 A
2 A
ACTUAL PAYLOAD (SINGLE CHARACTER)
CURRENT POSITION
NEXT CHAR POSITION
ABSOLUTE POSITION + OFFSET
1A:0ABSOLUTE INDEX ID
+ REPLICA ID
BLOCK OFFSET
COMPAR
ING
VECTOR
CLOCKS
BLOCKWISE
REPLICATED
GROWABLE
ARRAY
I WAS EXPECTING IT
1A:0
COMPAR
ING
VECTOR
CLOCKS
BLOCKWISE
REPLICATED
GROWABLE
ARRAY
I WAS EXPECTING IT
1A:0
ins(1A:5, NOT, 2B)
COMPAR
ING
VECTOR
CLOCKS
BLOCKWISE
REPLICATED
GROWABLE
ARRAY
I WAS
1A:0
ins(1A:5, NOT, 2B)
EXPECTING IT
1A:5
link
COMPAR
ING
VECTOR
CLOCKS
BLOCKWISE
REPLICATED
GROWABLE
ARRAY
I WAS
1A:0
EXPECTING IT
1A:5
link
NOT
2B:0
BLOCKWISE REPLICATED
GROWABLE ARRAYS
DELETING BLOCK OF DATA
TOMBSTONING
I WAS
1A:0
EXPECTING IT
1A:5
link
NOT
2B:0
del(1A:12, 3)
BLOCKWISE
REPLICATED
GROWABLE
ARRAYS
I WAS
1A:0
EXPECT
1A:5
link
NOT
2B:0
del(1A:12, 3)
ITING
BLOCKWISE
REPLICATED
GROWABLE
ARRAYS
TOMBSTONING
I WAS
1A:0
EXPECT
1A:5
link
NOT
2B:0
del(1A:12, 3)
ITING
1A:12 1A:15
link link
BLOCKWISE
REPLICATED
GROWABLE
ARRAYS
TOMBSTONING
I WAS
1A:0
EXPECT
1A:5
link
NOT
2B:0
IT---
1A:12 1A:15
link link
BLOCKWISE
REPLICATED
GROWABLE
ARRAYS
TOMBSTONING
TOMBSTONES
HOW TO GET RID OF THEM?
WE CAN ONLY INSERT ELEMENTS AFTER BLOCKS WE SEE
(NOT TOMBSTONES)
I WAS
1A:0
EXPECTING IT
1A:5
link
t1
2B:0
del(1A:12, 3, t3)
TOMBSTONE
PRUNNING
I WAS
1A:0
EXPECT
1A:5
link
t1
2B:0
ITt3
1A:12 1A:15
link link
TOMBSTONE
PRUNNING
I WAS
1A:0
EXPECT
1A:5
link
t1
2B:0
ITt3
1A:12 1A:15
link link
TOMBSTONE
PRUNNING prune(t2)
I WAS
1A:0
EXPECT
1A:5
link
t1
2B:0
ITt3
1A:12 1A:15
link link
TOMBSTONE
PRUNNING
t1 < t2
I WAS
1A:0
EXPECT
1A:5
link
ITt3
1A:12 1A:15
link link
TOMBSTONE
PRUNNING
t3 > t2
I WAS
1A:0
EXPECT
1A:5
link
ITt3
1A:12 1A:15
link link
TOMBSTONE
PRUNNING
CAN WE USE WALLCLOCK TIME FOR TIMESTAMPING?
“In transactions, timekeeping is more
about order of operations than actual
time.”
SEQUENCERS
Set X = 1 ts = 1
Set Y = 2 ts = 2
Set X = 3 ts = 3
Delete Y ts = 4
Set Y = 1 ts = 5
Delete X ts = 6
Monotonically incrementing counter
timeline
Node A
DOTS
Set X = 1 A:1
Set X = 3 A:2
Set Y = 1 A:3
Delete X A:4
timeline
Node A
Set Y = 2 B:1
Delete Y B:2
timeline
Node B
VECTOR
CLOCKS
Set X = 1
Set X = 3
Set Y = 1
Delete X
Node A
Set Y = 2
Delete Y
Node B
A 1
A 1
B 1
A 2
B 1 A 2
B 2
A 3
B 2
A 4
B 2
COMPAR
ING
VECTOR
CLOCKS
PARTIAL
ORDERING
Equals Greater than
Less than Concurrent
A 2
B 3
C 1
A 2
B 3
C 1
A 2
B 3
C 2
A 2
B 3
C 1
A 2
B 2
C 1
A 2
B 3
C 1
A 2
B 3
C 1
A 2
B 2
C 2
=
=
=
=
=
>
=
<
=
=
>
<
COMPAR
ING
VECTOR
CLOCKS
RESOLVING
CONCURRENT
UPDATES
Node 1
Node 2
Bob Joe
t1
SET X = 2SET X = 1
t2
COMPAR
ING
VECTOR
CLOCKS
RESOLVING
CONCURRENT
UPDATES
Node 1
Node 2
Bob Joe
t1
SET X = 2SET X = 1
t2
max (t1, t2)
max (t1, t2)
LAST
WRITE
WINS
MAX (2018-09-15T15:53:00, 2019-01-12T17:47:13)
=
2019-01-12T17:47:13
VECTOR
CLOCK
MERGE
MAX ( , )
=
A 1
B 3
A 2
B 1
C 1
A 2
B 3
C 1
HOW TO DETERMINE “SEEN BY ALL”?
DOT VECTOR
CLOCK
???
MATRIX
CLOCKS
2 2 1
2 3 1
1 2 2
A
B
C
A B C
Observers
Observed
MATRIX
CLOCKS 2 2 1
2 3 1
1 2 2
A
B
C
A B C
SEEN-BY-ALL
MIN
MATRIX
CLOCKS 2 2 1
2 3 1
1 2 2
A
B
C
A B C
SEEN-BY-ALL
MIN
1 2 1
MATRIX
CLOCKS 2 2 1
2 3 1
1 2 2
A
B
C
A B C
SEEN-BY-ALL
MIN
1 2 1
Our pruning point
I WAS
1A:0
EXPECTING IT
1A:5
link
{A:2,
B:2}
2B:0
del(1A:12, 3, {A:4,B:2})
TOMBSTONE
PRUNNING
I WAS
1A:0
EXPECT
1A:5
link
{A:2,
B:2}
2B:0
IT{A:4,
B:2}
1A:12 1A:15
link link
TOMBSTONE
PRUNNING
I WAS
1A:0
EXPECT
1A:5
link
{A:2,
B:2}
2B:0
IT{A:4,
B:2}
1A:12 1A:15
link link
TOMBSTONE
PRUNNING prune({A:3,B:2})
I WAS
1A:0
EXPECT
1A:5
link
{A:2,
B:2}
2B:0
IT{A:4,
B:2}
1A:12 1A:15
link link
TOMBSTONE
PRUNNING {A:2,B:2} < {A:3,B:2}
I WAS
1A:0
EXPECT
1A:5
link
IT{A:4,
B:2}
1A:12 1A:15
link link
TOMBSTONE
PRUNNING {A:4,B:2} > {A:3,B:2}
I WAS
1A:0
EXPECT
1A:5
link
IT{A:4,
B:2}
1A:12 1A:15
link link
TOMBSTONE
PRUNNING
 Operational transformation discussion on HN: https://news.ycombinator.com/item?id=12311984
 JSON CRDT by Martin Kleppman: https://www.youtube.com/watch?v=B5NULPSiOGw
 Rope data structure: https://www.geeksforgeeks.org/ropes-data-structure-fast-string-concatenation/
 Blockwise Replicated Growable Arrays: https://pages.lip6.fr/Marc.Shapiro/papers/rgasplit-group2016-11.pdf
 Examples of CRDT implementations: https://github.com/Horusiath/crdt-examples/
REFERENCES
THANK YOU

Collaborative text editing