-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2675 from xiang90/v3rfc
doc: v3api rfc
- Loading branch information
Showing
2 changed files
with
463 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
## Design | ||
|
||
1. Flatten binary key-value space | ||
|
||
2. Keep the event history until compaction | ||
- access to old version of keys | ||
- user controlled history compaction | ||
|
||
3. Support range query | ||
- Pagination support with limit argument | ||
- Support consistency guarantee across multiple range queries | ||
|
||
4. Replace TTL key with Lease | ||
- more efficient/ low cost keep alive | ||
- a logical group of TTL keys | ||
|
||
5. Replace CAS/CAD with multi-object Tnx | ||
- MUCH MORE powerful and flexible | ||
|
||
6. Support efficient watching with multiple ranges | ||
|
||
7. RPC API supports the completed set of APIs. | ||
- more efficient than JSON/HTTP | ||
- additional tnx/lease support | ||
|
||
8. HTTP API supports a subset of APIs. | ||
- easy for people to try out etcd | ||
- easy for people to write simple etcd application | ||
|
||
|
||
## Protobuf Defined API | ||
|
||
[protobuf](./v3api.proto) | ||
|
||
### Examples | ||
|
||
#### Put a key (foo=bar) | ||
``` | ||
// A put is always successful | ||
Put( PutRequest { key = foo, value = bar } ) | ||
PutResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 1, | ||
raft_term = 0x1, | ||
} | ||
``` | ||
|
||
#### Get a key (assume we have foo=bar) | ||
``` | ||
Get ( RangeRequest { key = foo } ) | ||
RangeResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 1, | ||
raft_term = 0x1, | ||
kvs = { | ||
{ | ||
key = foo, | ||
value = bar, | ||
create_index = 1, | ||
mod_index = 1, | ||
version = 1; | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
#### Range over a key space (assume we have foo0=bar0… foo100=bar100) | ||
``` | ||
Range ( RangeRequest { key = foo, end_key = foo80, limit = 30 } ) | ||
RangeResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 100, | ||
raft_term = 0x1, | ||
kvs = { | ||
{ | ||
key = foo0, | ||
value = bar0, | ||
create_index = 1, | ||
mod_index = 1, | ||
version = 1; | ||
}, | ||
..., | ||
{ | ||
key = foo30, | ||
value = bar30, | ||
create_index = 30, | ||
mod_index = 30, | ||
version = 1; | ||
}, | ||
}, | ||
} | ||
``` | ||
|
||
#### Finish a tnx (assume we have foo0=bar0, foo1=bar1) | ||
``` | ||
Tnx(TnxRequest { | ||
// mod_index of foo0 is equal to 1, mod_index of foo1 is greater than 1 | ||
compare = { | ||
{compareType = equal, key = foo0, mod_index = 1}, | ||
{compareType = greater, key = foo1, mod_index = 1}} | ||
}, | ||
// if the comparison succeeds, put foo2 = bar2 | ||
success = {PutRequest { key = foo2, value = success }}, | ||
// if the comparison fails, put foo2=fail | ||
failure = {PutRequest { key = foo2, value = failure }}, | ||
) | ||
TnxResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 3, | ||
raft_term = 0x1, | ||
succeeded = true, | ||
responses = { | ||
// response of PUT foo2=success | ||
{ | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 3, | ||
raft_term = 0x1, | ||
} | ||
} | ||
} | ||
``` | ||
|
||
#### Watch on a key/range | ||
|
||
``` | ||
Watch( WatchRequest{ | ||
key = foo, | ||
end_key = fop, // prefix foo | ||
start_index = 20, | ||
end_index = 10000, | ||
// server decided notification frequency | ||
progress_notification = true, | ||
} | ||
… // this can be a watch request stream | ||
) | ||
// put (foo0=bar0) event at 3 | ||
WatchResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 3, | ||
raft_term = 0x1, | ||
event_type = put, | ||
kv = { | ||
key = foo0, | ||
value = bar0, | ||
create_index = 1, | ||
mod_index = 1, | ||
version = 1; | ||
}, | ||
} | ||
… | ||
// a notification at 2000 | ||
WatchResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 2000, | ||
raft_term = 0x1, | ||
// nil event as notification | ||
} | ||
… | ||
// put (foo0=bar3000) event at 3000 | ||
WatchResponse { | ||
cluster_id = 0x1000, | ||
member_id = 0x1, | ||
index = 3000, | ||
raft_term = 0x1, | ||
event_type = put, | ||
kv = { | ||
key = foo0, | ||
value = bar3000, | ||
create_index = 1, | ||
mod_index = 3000, | ||
version = 2; | ||
}, | ||
} | ||
… | ||
``` |
Oops, something went wrong.