Skip to content

Commit

Permalink
tikv: update the usage example for Txn KV API (#487)
Browse files Browse the repository at this point in the history
* tikv: update the usage example for Txn KV API

* tikv: update the code fencing

* tikv: address comments
  • Loading branch information
lilin90 authored Jun 14, 2018
1 parent 40ebc4f commit 3e42d44
Showing 1 changed file with 122 additions and 79 deletions.
201 changes: 122 additions & 79 deletions tikv/go-client-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ To use the Raw Key-Value API in applications developed by golang, take the follo

2. Import the dependency packages.

```bash
```go
import (
"fmt"
"github.com/pingcap/tidb/config"
Expand All @@ -31,7 +31,7 @@ To use the Raw Key-Value API in applications developed by golang, take the follo

3. Create a Raw Key-Value client.

```bash
```go
cli, err := tikv.NewRawKVClient([]string{"192.168.199.113:2379"}, config.Security{})
```

Expand All @@ -42,7 +42,7 @@ To use the Raw Key-Value API in applications developed by golang, take the follo

4. Call the Raw Key-Value client methods to access the data on TiKV. The Raw Key-Value API contains the following methods, and you can also find them at [GoDoc](https://godoc.org/github.com/pingcap/tidb/store/tikv#RawKVClient).

```bash
```go
type RawKVClient struct
func (c *RawKVClient) Close() error
func (c *RawKVClient) ClusterID() uint64
Expand All @@ -54,7 +54,7 @@ To use the Raw Key-Value API in applications developed by golang, take the follo

### Usage example of the Raw Key-Value API

```bash
```go
package main
import (
Expand Down Expand Up @@ -142,23 +142,32 @@ To use the Transactional Key-Value API in applications developed by golang, take
1. Install the necessary packages.
```bash
go get -v -u github.com/juju/errors
go get -v -u github.com/pingcap/tidb/kv
go get -v -u github.com/pingcap/tidb/store/tikv
go get -v -u golang.org/x/net/context
```
2. Import the dependency packages.
```bash
```go
import (
"flag"
"fmt"
"os"
"github.com/juju/errors"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/store/tikv"
"fmt"
"github.com/pingcap/tidb/terror"
goctx "golang.org/x/net/context"
)
```
3. Create Storage using a URL scheme.
```bash
```go
driver := tikv.Driver{}
storage, err := driver.Open("tikv://192.168.199.113:2379")
```
Expand All @@ -169,7 +178,7 @@ To use the Transactional Key-Value API in applications developed by golang, take
5. Call the Transactional Key-Value API's methods to access the data on TiKV. The Transactional Key-Value API contains the following methods:
```bash
```go
Begin() -> Txn
Txn.Get(key []byte) -> (value []byte)
Txn.Set(key []byte, value []byte)
Expand All @@ -180,116 +189,150 @@ To use the Transactional Key-Value API in applications developed by golang, take
### Usage example of the Transactional Key-Value API
```bash
```go
package main
import (
"context"
"flag"
"fmt"
"strconv"
"os"
"github.com/juju/errors"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/store/tikv"
"github.com/pingcap/tidb/terror"
goctx "golang.org/x/net/context"
)
// if key not found, set value to zero
// else increase the value
func increase(storage kv.Storage, key []byte) error {
txn, err := storage.Begin()
type KV struct {
K, V []byte
}
func (kv KV) String() string {
return fmt.Sprintf("%s => %s (%v)", kv.K, kv.V, kv.V)
}
var (
store kv.Storage
pdAddr = flag.String("pd", "192.168.199.113:2379", "pd address:192.168.199.113:2379")
)
// Init initializes information.
func initStore() {
driver := tikv.Driver{}
var err error
store, err = driver.Open(fmt.Sprintf("tikv://%s", *pdAddr))
terror.MustNil(err)
}
// key1 val1 key2 val2 ...
func puts(args ...[]byte) error {
tx, err := store.Begin()
if err != nil {
return err
return errors.Trace(err)
}
defer txn.Rollback()
var oldValue int
val, err := txn.Get(key)
if err != nil {
if !kv.ErrNotExist.Equal(err) {
return err
}
} else {
oldValue, err = strconv.Atoi(string(val))
for i := 0; i < len(args); i += 2 {
key, val := args[i], args[i+1]
err := tx.Set(key, val)
if err != nil {
return err
return errors.Trace(err)
}
}
err = txn.Set(key, []byte(strconv.Itoa(oldValue+1)))
err = tx.Commit(goctx.Background())
if err != nil {
return err
return errors.Trace(err)
}
err = txn.Commit(context.Background())
return nil
}
// lookup value for key
func lookup(storage kv.Storage, key []byte) (int, error) {
var value int
txn, err := storage.Begin()
func get(k []byte) (KV, error) {
tx, err := store.Begin()
if err != nil {
return value, err
return KV{}, errors.Trace(err)
}
defer txn.Rollback()
val, err := txn.Get(key)
v, err := tx.Get(k)
if err != nil {
return value, err
return KV{}, errors.Trace(err)
}
value, err = strconv.Atoi(string(val))
if err != nil {
return value, err
}
return value, nil
return KV{K: k, V: v}, nil
}
func main() {
driver := tikv.Driver{}
storage, err := driver.Open("tikv://192.168.199.113:2379")
func dels(keys ...[]byte) error {
tx, err := store.Begin()
if err != nil {
panic(err)
return errors.Trace(err)
}
defer storage.Close()
key := []byte("Account")
// lookup account
account, err := lookup(storage, key)
for _, key := range keys {
err := tx.Delete(key)
if err != nil {
return errors.Trace(err)
}
}
err = tx.Commit(goctx.Background())
if err != nil {
fmt.Printf("failed to lookup key %s: %v\n", key, err)
} else {
fmt.Printf("Account is %d\n", account)
return errors.Trace(err)
}
return nil
}
// increase account
err = increase(storage, key)
func scan(keyPrefix []byte, limit int) ([]KV, error) {
tx, err := store.Begin()
if err != nil {
panic(err)
return nil, errors.Trace(err)
}
// lookup account again
account, err = lookup(storage, key)
it, err := tx.Seek(keyPrefix)
if err != nil {
fmt.Printf("failed to lookup key %s: %v\n", key, err)
} else {
fmt.Printf("Account increased to %d\n", account)
return nil, errors.Trace(err)
}
defer it.Close()
var ret []KV
for it.Valid() && limit > 0 {
ret = append(ret, KV{K: it.Key()[:], V: it.Value()[:]})
limit--
it.Next()
}
return ret, nil
}
func main() {
pdAddr := os.Getenv("PD_ADDR")
if pdAddr != "" {
os.Args = append(os.Args, "-pd", pdAddr)
}
flag.Parse()
initStore()
// set
err := puts([]byte("key1"), []byte("value1"), []byte("key2"), []byte("value2"))
terror.MustNil(err)
// get
kv, err := get([]byte("key1"))
terror.MustNil(err)
fmt.Println(kv)
// scan
ret, err := scan([]byte("key"), 10)
for _, kv := range ret {
fmt.Println(kv)
}
// delete
err = dels([]byte("key1"), []byte("key2"))
terror.MustNil(err)
}
```
The result is like:
```bash
INFO[0000] [pd] create pd client with endpoints [192.168.199.113:2379]
INFO[0000] [pd] leader switches to: http://127.0.0.1:2379, previous:
INFO[0000] [pd] init cluster id 6554145799874853483
INFO[0000] [kv] Rollback txn 400197262324006914
failed to lookup key Account: [kv:2]Error: key not exist
INFO[0000] [kv] Rollback txn 400197262324006917
Account increased to 1
# run the program again
INFO[0000] [pd] create pd client with endpoints [192.168.199.113:2379]
INFO[0000] [pd] leader switches to: http://127.0.0.1:2379, previous:
INFO[0000] [pd] init cluster id 6554145799874853483
INFO[0000] [kv] Rollback txn 400198364324954114
Account is 1
INFO[0000] [kv] Rollback txn 400198364324954117
Account increased to 2
INFO[0000] [pd] leader switches to: http://192.168.199.113:2379, previous:
INFO[0000] [pd] init cluster id 6563858376412119197
key1 => value1 ([118 97 108 117 101 49])
key1 => value1 ([118 97 108 117 101 49])
key2 => value2 ([118 97 108 117 101 50])
```

0 comments on commit 3e42d44

Please sign in to comment.