Skip to content

RawKV Basic

Ping Yu edited this page Nov 17, 2022 · 5 revisions

Basic RawKV API

If you don't need transaction and multi-version support, you can consider using TiKV in the rawkv way, which usually has a faster response time.

Note: Currently a TiKV cluster can only choose one of the rawkv or txnkv APIs to use. Mixing them will cause unavailability issues due to inconsistent key encoding.

Creating Client

Information about a TiKV cluster can be found by the address of PD server. After starting a TiKV cluster successfully, we can use PD's address list to create a client to interact with it. The following code demonstrate the process of creating a rawkv client.

import (
    "github.com/tikv/client-go/v2/config"
    "github.com/tikv/client-go/v2/rawkv"
)

client, err := rawkv.NewClient(context.TODO(), []string{"127.0.0.1:2379"}, config.Security{})
if err != nil {
    // ... handle error ...
}

Create Client for TiKV API V2

Note: client-go >= v2.0.2 is required

import (
    "github.com/pingcap/kvproto/pkg/kvrpcpb"
    "github.com/tikv/client-go/v2/rawkv"
)

client, err := rawkv.NewClientWithOpts(context.TODO(), []string{"127.0.0.1:2379"},
    rawkv.WithAPIVersion(kvrpcpb.APIVersion_V2))
if err != nil {
    // ... handle error ...
}

Closing Client

When you are done with a client, you need to gracefully close the client to finish pending tasks and terminate all background jobs.

Example:

// ... create a client as described above ...
// ... do something with the client ...
if err := client.Close(); err != nil {
    // ... handle error ...
}

Single Key Read/Write

RawKV provides Get, Put and Delete methods to read and write a single key.

NOTE: please compare return value of Get with nil to check whether the key is found or not. len(value)==0 can not distinguish the key is not found, or the value is an empty byte slice.

Example:

v, err := client.Get(context.TODO(), []byte("key"))
if err != nil {
    // ... handle error ...
}
if v == nil {
    // ... handle not found ...
}
// ... handle value v ...

err = client.Put(context.TODO(), []byte("key"), []byte("value"))
if err != nil {
    // ... handle error ...
}

err = client.Delete(context.TODO(), []byte("key"))
if err != nil {
    // ... handle error ...
}

Iterations

Like txnkv, there are also Scan and ReverseScan methods to iterate over a range of keys. Start key and end key are arbitrary bytes. nil key stands for "" when used as start key, and stands for +inf when used as end key. Note in particular that ReverseScan from the last key (i.e. endKey=nil) is not currently supported.

keys, values, err := client.Scan(context.TODO(), []byte("begin"), []byte("end"), 10)
if err != nil {
    // ... handle error ...
}
// ... handle keys, values ...

keys, values, err := client.ReverseScan(context.TODO(), []byte("end"), []byte("begin"), 10)
if err != nil {
    // ... handle error ...
}
// ... handle keys, values ...

Batch Operations

To optimize performance, rawkv also supports batch operations using batch. Note that since rawkv is not transaction guaranteed, we do not guarantee that all writes will succeed or fail at the same time when these keys are distributed across multiple regions.

values, err := client.BatchGet(context.TODO(), [][]byte{[]byte("key1"), []byte("key2")})
if err != nil {
    // ... handle error ...
}
// ... handle values ...

err = client.BatchPut(context.TODO(), [][]byte{[]byte("key1"), []byte("key2")}, [][]byte{[]byte("value1"), []byte("value2")})
if err != nil {
    // ... handle error ...
}

err = client.BatchDelete(context.TODO(), [][]byte{[]byte("key1"), []byte("key2")})
if err != nil {
    // ... handle error ...
}