You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: vac/raw/sds.md
+92-45Lines changed: 92 additions & 45 deletions
Original file line number
Diff line number
Diff line change
@@ -9,26 +9,30 @@ contributors:
9
9
10
10
## Abstract
11
11
12
-
This specification introduces the Scalable Data Sync (SDS) protocol to achieve end-to-end reliability
12
+
This specification introduces the Scalable Data Sync (SDS) protocol
13
+
to achieve end-to-end reliability
13
14
when consolidating distributed logs in a decentralized manner.
14
15
The protocol is designed for a peer-to-peer (p2p) topology
15
16
where an append-only log is maintained by each member of a group of nodes
16
17
who may individually append new entries to their local log at any time and
17
18
is interested in merging new entries from other nodes in real-time or close to real-time
18
19
while maintaining a consistent order.
19
20
The outcome of the log consolidation procedure is
20
-
that all nodes in the group eventually reflect in their own logs the same entries in the same order.
21
+
that all nodes in the group eventually reflect in their own logs
22
+
the same entries in the same order.
21
23
The protocol aims to scale to very large groups.
22
24
23
25
## Motivation
24
26
25
27
A common application that fits this model is a p2p group chat (or group communication),
26
28
where the participants act as log nodes
27
-
and the group conversation is modelled as the consolidated logs maintained on each node.
29
+
and the group conversation is modelled as the consolidated logs
30
+
maintained on each node.
28
31
The problem of end-to-end reliability can then be stated as
29
32
ensuring that all participants eventually see the same sequence of messages
30
33
in the same causal order,
31
-
despite the challenges of network latency, message loss, and scalability present in any communications transport layer.
34
+
despite the challenges of network latency, message loss,
35
+
and scalability present in any communications transport layer.
32
36
The rest of this document will assume the terminology of a group communication:
33
37
log nodes being the _participants_ in the group chat
34
38
and the logged entries being the _messages_ exchanged between participants.
@@ -39,20 +43,25 @@ We make the following simplifying assumptions for a proposed reliability protoco
39
43
40
44
***Broadcast routing:**
41
45
Messages are broadcast disseminated by the underlying transport.
42
-
The selected transport takes care of routing messages to all participants of the communication.
46
+
The selected transport takes care of routing messages
47
+
to all participants of the communication.
43
48
***Store nodes:**
44
-
There are high-availability caches (a.k.a. Store nodes) from which missed messages can be retrieved.
49
+
There are high-availability caches (a.k.a. Store nodes)
50
+
from which missed messages can be retrieved.
45
51
These caches maintain the full history of all messages that have been broadcast.
46
52
This is an optional element in the protocol design,
47
53
but improves scalability by reducing direct interactions between participants.
48
54
***Message ID:**
49
55
Each message has a globally unique, immutable ID (or hash).
50
-
Messages can be requested from the high-availability caches or other participants using the corresponding message ID.
56
+
Messages can be requested from the high-availability caches or
57
+
other participants using the corresponding message ID.
51
58
52
59
## Wire protocol
53
-
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
60
+
61
+
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”,
54
62
“SHOULD NOT”, “RECOMMENDED”, “MAY”, and
55
63
“OPTIONAL” in this document are to be interpreted as described in [2119](https://www.ietf.org/rfc/rfc2119.txt).
64
+
56
65
### Message
57
66
58
67
Messages MUST adhere to the following meta structure:
@@ -71,33 +80,45 @@ message Message {
71
80
}
72
81
```
73
82
74
-
Each message MUST include its globally unique identifier in the `message_id` field, likely based on a message hash.
75
-
The `channel_id` field MUST be set to the identifier of the channel of group communication that is being synchronized.
83
+
Each message MUST include its globally unique identifier in the `message_id` field,
84
+
likely based on a message hash.
85
+
The `channel_id` field MUST be set to the identifier of the channel of group communication
86
+
that is being synchronized.
76
87
For simple group communications without individual channels,
77
88
the `channel_id` SHOULD be set to `0`.
78
-
The `lamport_timestamp`, `causal_history` and `bloom_filter` fields MUST be set according to the [protocol steps](#protocol-steps) set out below.
89
+
The `lamport_timestamp`, `causal_history` and
90
+
`bloom_filter` fields MUST be set according to the [protocol steps](#protocol-steps)
91
+
set out below.
79
92
These fields MAY be left unset in the case of [ephemeral messages](#ephemeral-messages).
80
93
The message `content` MAY be left empty for [periodic sync messages](#periodic-sync-message),
81
94
otherwise it MUST contain the application-level content
82
95
83
96
### Participant state
84
97
85
98
Each participant MUST maintain:
86
-
- A Lamport timestamp for each channel of communication,
99
+
100
+
* A Lamport timestamp for each channel of communication,
87
101
initialized to current epoch time in nanosecond resolution.
88
-
- A bloom filter for received message IDs per channel.
89
-
The bloom filter SHOULD be rolled over and recomputed once it reaches a predefined capacity of message IDs.
90
-
Furthermore, it SHOULD be designed to minimize false positives through an optimal selection of size and hash functions.
91
-
- A buffer for unacknowledged outgoing messages
92
-
- A buffer for incoming messages with unmet causal dependencies
93
-
- A local log (or history) for each channel,
102
+
* A bloom filter for received message IDs per channel.
103
+
The bloom filter SHOULD be rolled over and
104
+
recomputed once it reaches a predefined capacity of message IDs.
105
+
Furthermore,
106
+
it SHOULD be designed to minimize false positives through an optimal selection of
107
+
size and hash functions.
108
+
* A buffer for unacknowledged outgoing messages
109
+
* A buffer for incoming messages with unmet causal dependencies
110
+
* A local log (or history) for each channel,
94
111
containing all message IDs in the communication channel,
95
112
ordered by Lamport timestamp.
96
113
97
114
Messages in the unacknowledged outgoing buffer can be in one of three states:
98
-
1.**Unacknowledged** - there has been no acknowledgement of message receipt by any participant in the channel
99
-
2.**Possibly acknowledged** - there has been ambiguous indication that the message has been _possibly_ received by at least one participant in the channel
100
-
3.**Acknowledged** - there has been sufficient indication that the message has been received by at least some of the participants in the channel.
115
+
116
+
1.**Unacknowledged** - there has been no acknowledgement of message receipt
117
+
by any participant in the channel
118
+
2.**Possibly acknowledged** - there has been ambiguous indication that the message
119
+
has been _possibly_ received by at least one participant in the channel
120
+
3.**Acknowledged** - there has been sufficient indication that the message
121
+
has been received by at least some of the participants in the channel.
101
122
This state will also remove the message from the outgoing buffer.
102
123
103
124
### Protocol Steps
@@ -109,34 +130,45 @@ the `lamport_timestamp`, `causal_history` and `bloom_filter` fields.
109
130
#### Send Message
110
131
111
132
Before broadcasting a message:
112
-
- the participant MUST increase its local Lamport timestamp by `1` and include this in the `lamport_timestamp` field.
113
-
- the participant MUST determine the preceding few message IDs in the local history and include these in an ordered list in the `causal_history` field.
133
+
134
+
* the participant MUST increase its local Lamport timestamp by `1` and
135
+
include this in the `lamport_timestamp` field.
136
+
* the participant MUST determine the preceding few message IDs in the local history
137
+
and include these in an ordered list in the `causal_history` field.
114
138
The number of message IDs to include in the `causal_history` depends on the application.
115
139
We recommend a causal history of two message IDs.
116
-
- the participant MUST include the current `bloom_filter` state in the broadcast message.
140
+
* the participant MUST include the current `bloom_filter`
141
+
state in the broadcast message.
117
142
118
-
After broadcasting a message, the message MUST be added to the participant’s buffer of unacknowledged outgoing messages.
143
+
After broadcasting a message,
144
+
the message MUST be added to the participant’s buffer
145
+
of unacknowledged outgoing messages.
119
146
120
147
#### Receive Message
121
148
122
149
Upon receiving a message,
123
-
- the participant MUST [review the ACK status](#review-ack-status) of messages in its unacknowledged outgoing buffer
150
+
151
+
* the participant MUST [review the ACK status](#review-ack-status) of messages
152
+
in its unacknowledged outgoing buffer
124
153
using the received message's causal history and bloom filter.
125
-
- the participant MUST include the received message ID in its local bloom filter.
126
-
- the participant MUST verify that all causal dependencies are met for the received message.
154
+
* the participant MUST include the received message ID in its local bloom filter.
155
+
* the participant MUST verify that all causal dependencies are met
156
+
for the received message.
127
157
Dependencies are met if the message IDs in the `causal_history` of the received message
128
158
appear in the local history of the receiving participant.
129
159
130
160
If all dependencies are met,
131
161
the participant MUST [deliver the message](#deliver-message).
132
162
If dependencies are unmet,
133
-
the participant MUST add the message to the incoming buffer of messages with unmet causal dependencies.
163
+
the participant MUST add the message to the incoming buffer of messages
164
+
with unmet causal dependencies.
134
165
135
166
#### Deliver Message
136
167
137
168
Triggered by the [Receive Message](#receive-message) procedure.
138
169
139
-
If the received message’s Lamport timestamp is greater than the participant's local Lamport timestamp,
170
+
If the received message’s Lamport timestamp is greater than the participant's
171
+
local Lamport timestamp,
140
172
the participant MUST update its local Lamport timestamp to match the received message.
141
173
The participant MUST insert the message ID into its local log,
142
174
based on Lamport timestamp.
@@ -147,7 +179,8 @@ the participant MUST follow the [Resolve Conflicts](#resolve-conflicts) procedur
147
179
148
180
Triggered by the [Deliver Message](#deliver-message) procedure.
149
181
150
-
The participant MUST order messages with the same Lamport timestamp in ascending order of message ID.
182
+
The participant MUST order messages with the same Lamport timestamp
183
+
in ascending order of message ID.
151
184
If the message ID is implemented as a hash of the message,
152
185
this means the message with the lowest hash would precede
153
186
other messages with the same Lamport timestamp in the local log.
@@ -158,27 +191,35 @@ Triggered by the [Receive Message](#receive-message) procedure.
158
191
159
192
For each message in the unacknowledged outgoing buffer,
160
193
based on the received `bloom_filter` and `causal_history`:
161
-
- the participant MUST mark all messages in the received `causal_history` as **acknowledged**.
162
-
- the participant MUST mark all messages included in the `bloom_filter` as **possibly acknowledged**.
194
+
195
+
* the participant MUST mark all messages in the received `causal_history` as **acknowledged**.
196
+
* the participant MUST mark all messages included in the `bloom_filter`
197
+
as **possibly acknowledged**.
163
198
If a message appears as **possibly acknowledged** in multiple received bloom filters,
164
199
the participant MAY mark it as acknowledged based on probabilistic grounds,
165
200
taking into account the bloom filter size and hash number.
166
201
167
202
#### Periodic Incoming Buffer Sweep
168
203
169
-
The participant MUST periodically check causal dependencies for each message in the incoming buffer.
204
+
The participant MUST periodically check causal dependencies for each message
205
+
in the incoming buffer.
170
206
For each message in the incoming buffer:
171
-
- the participant MAY attempt to retrieve missing dependencies from the Store node (high-availability cache) or other peers.
172
-
- if all dependencies of a message are met,
207
+
208
+
* the participant MAY attempt to retrieve missing dependencies from the Store node
209
+
(high-availability cache) or other peers.
210
+
* if all dependencies of a message are met,
173
211
the participant MUST proceed to [deliver the message](#deliver-message).
174
212
175
-
If a message's causal dependencies have failed to be met after a predetermined amount of time,
213
+
If a message's causal dependencies have failed to be met
214
+
after a predetermined amount of time,
176
215
the participant MAY mark them as **irretrievably lost**.
177
216
178
217
#### Periodic Outgoing Buffer Sweep
179
218
180
-
The participant MUST rebroadcast **unacknowledged** outgoing messages after a set period.
181
-
The participant SHOULD use distinct resend periods for **unacknowledged** and **possibly acknowledged** messages,
219
+
The participant MUST rebroadcast **unacknowledged** outgoing messages
220
+
after a set period.
221
+
The participant SHOULD use distinct resend periods for **unacknowledged** and
222
+
**possibly acknowledged** messages,
182
223
prioritizing **unacknowledged** messages.
183
224
184
225
#### Periodic Sync Message
@@ -187,19 +228,25 @@ For each channel of communication,
187
228
participants SHOULD periodically send an empty-content message to maintain sync state,
188
229
without incrementing the Lamport timestamp.
189
230
To avoid network activity bursts in large groups,
190
-
a participant MAY choose to only send periodic sync messages if no other messages have been broadcast in the channel after a random backoff period.
231
+
a participant MAY choose to only send periodic sync messages
232
+
if no other messages have been broadcast in the channel after a random backoff period.
191
233
192
-
Participants MUST process these sync messages following the same steps as regular messages.
234
+
Participants MUST process these sync messages
235
+
following the same steps as regular messages.
193
236
194
237
#### Ephemeral Messages
195
238
196
-
Participants MAY choose to send short-lived messages for which no synchronization or reliability is required.
239
+
Participants MAY choose to send short-lived messages for which no synchronization
240
+
or reliability is required.
197
241
These messages are termed _ephemeral_.
198
242
199
-
Ephemeral messages SHOULD be sent with `lamport_timestamp`, `causal_history`, and `bloom_filter` unset.
200
-
Ephemeral messages SHOULD NOT be added to the unacknowledged outgoing buffer after broadcast.
243
+
Ephemeral messages SHOULD be sent with `lamport_timestamp`, `causal_history`, and
244
+
`bloom_filter` unset.
245
+
Ephemeral messages SHOULD NOT be added to the unacknowledged outgoing buffer
246
+
after broadcast.
201
247
Upon reception,
202
-
ephemeral messages SHOULD be delivered immediately without buffering for causal dependencies or including in the local log.
248
+
ephemeral messages SHOULD be delivered immediately without buffering for causal dependencies
0 commit comments