v3api.md 4.0 KB

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

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;
          },
    }
    …