请问下 TiDB 会使用到 mvcc/txn 接口的场景是什么?

从tikv的rpc接口看有两套接口:
一套是支持 mvcc/txn,
一套是RawKV commands

这两套接口的使用场景分别是什么呢?
是不是只要是支持ACID的事务操作就用mvcc/txn这套接口?

2赞

一套是 SQL 入口,
另外一套是 标准的 KV 入口

你可以按照你的场景需要,来判断用那种

2赞

@xfworld
按你的意思, mvcc/txn是SQL的入口?RawKV是标准的KV入口了
如果用RawKV,是不是不支持mvcc?
但我理解下面几个基本的mvcc/txn接口,也应该是可以做为单独KV入口吧?
rpc KvPrewrite
rpc KvCommit
rpc KvGet
rpc KvScan

2赞

我说的是这里提供的tikv的rpc接口
https://github.com/pingcap/kvproto/blob/5cb23649b361013f929e0d46a166ae24848fbcbb/proto/tikvpb.proto#L57

2赞

txn 接口走的 tidb
RawKV 直接就是 tikv

大概能理解么?

然后rawkv 有 client api,论坛里头有标准答案,你可以搜一下

1赞

我大概明白了。是这样子吧?
1,使用txn的接口,是要从txn的begin执行,再到txn的commit处理,这部分
是要走tidb的部分流程,然后再执行到tidb-client的prewrite和commit的处理发
给tikv;
2,直接使用rawkv的接口,就是直接send给tikv了(中间从pd获取下tikv的信息)

1赞

TiKV 支持 TxnKV 和 RawKV 两种接口。大部分应用(比如 TiDB / juicefs)都是走 TxnKV 接口。

2赞

可以参考一下 TiKV API v2 的 RFC,里面也 cover 了一些目前 API 的情况 https://github.com/tikv/rfcs/pull/69

1赞

TiKV 提供了 RawKV 和 TxnKV 两套接口,TiDB 使用的是 TxnKV 的接口,对外提供 SI 的事务隔离级别以及确保事务的 ACID 属性。

其他客户端如果不需要事务,不需要 MVCC,希望每个 Key 有 TTL,可以使用 RawKV 接口,性能会好一些。

client-go 中有一些事务和非事务 API 的使用例子,可以参考下:https://github.com/tikv/client-go/tree/master/examples

3赞

嗯,接口这部分我是清楚了。多谢各位!

另外我想到一个问题,假如我就用了RawKV的put接口写了很多数据,数据分布在3个tikv集群中,那么获取一个范围的数据,是会根据pd(或者缓存信息)获取每个tikv的信息,分别在tikv获取查询信息回来汇总结果吗?

另外我想到一个问题,假如我就用了 RawKV 的 put 接口写了很多数据,数据分布在 3 个 tikv 集群中,那么获取一个范围的数据,是会根据 pd (或者缓存信息)获取每个 tikv 的信息,分别在tikv获取查询信息回来汇总结果吗?

是的。请问您目前是打算在某个业务场景中使用 TiKV 吗?

嗯,主要想把一些时序数据转到kv存储。
另外,github上rawkv例子好像比较旧了,直接用编译不过。
我包含了"github.com/tikv/client-go/v2/tikv",使用tikv.NewRawKVClient,再调整下几个函数的参数才能编译过~

client-go/rawkv.go at master · tikv/client-go (github.com)

OK,可以提个 PR 帮忙修改下这个例子吗?

这个…PR 还不知道怎么弄~
另外,我在测试BatchPut后发现会各写多一对kv,是这样设计的?如:
key1 := []byte(“t_Company_1”)
val1 := []byte(“v_Company_1”)
key2 := []byte(“t_Company_2”)
val2 := []byte(“v_Company_2”)
var key = [][]byte{key1, key2}
var val = [][]byte{val1, val2}
err = cli.BatchPut(key, val)
key11, val11, err := cli.Scan([]byte(“t_Company_”), []byte(“t_Company_3”), 10)

这里,scan出来的结果是:(多了_ok的key和value对)
[t_Company_1 t_Company_1_ok t_Company_2 t_Company_2_ok]
[v_Company_1 v_Company_1_ok v_Company_2 v_Company_2_ok]
期望的结果是:
[t_Company_1 t_Company_2 ]
[v_Company_1 v_Company_2 ]

请问您用的是哪个语言的客户端?什么版本?能否提供一下复现的代码?

环境是:一个PD和3个tikv的集群,pd和tikv都是5.1.0
我将那两个多余的kv对删掉后,重新改成之前的代码,问题又不出现了。。。

之前的代码就是这样,也没什么特别的:
import (
“fmt”
github.com/tikv/client-go/v2/config
github.com/tikv/client-go/v2/tikv
)
func main() {
cli, err := tikv.NewRawKVClient([]string{“10.x.x.x:2379”}, config.DefaultConfig().Security)
if err != nil {
panic(err)
}
defer cli.Close()
fmt.Printf(“cluster ID: %d\n”, cli.ClusterID())
key1 := []byte(“t_Company_1”)
val1 := []byte(“v_Company_1”)
key2 := []byte(“t_Company_2”)
val2 := []byte(“v_Company_2”)

var key = [][]byte{key1, key2}
var val = [][]byte{val1, val2}

err = cli.BatchPut(key, val)
if err != nil {
    panic(err)
}
fmt.Printf("Successfully put %s:%s to tikv\n", key, val)

key11, val11, err := cli.Scan([]byte("t_Company_"), []byte("t_Company_3"), 10)
if err != nil {
    panic(err)
}
fmt.Printf("found val: %s for key: %s\n", val11, key11)

err = cli.Delete(key1)
if err != nil {
    panic(err)
}
fmt.Printf("key: %s deleted\n", key1)

err = cli.Delete(key2)
if err != nil {
    panic(err)
}
fmt.Printf("key: %s deleted\n", key2)

// get key again from tikv
val1, err = cli.Get(key1)
if err != nil {
    fmt.Printf("not found val: %s for key: %s\n", val1, key1)
    panic(err)
}
fmt.Printf("found val: %s for key: %s\n", val1, key1)

}

可能集群里面原来就有数据,如果后续能复现问题,麻烦再跟我们说一下复现的办法

嗯,好的。
之前应该是没这个数据的。因为我之前是在测试put的接口,也就是连续put这两组数据,
当时也是做过一样的scan,没scan出异常数据。只是batchput验证间隔了一个晚上,但
期间应该没人会去写这样的数据。

我确定了, 这数据是另外一个人写的。这里没问题^_^

1赞