KV 接口
接口示例
Nebula Graph storage 提供 key-value 接口,用户可以通过 StorageClient 进行 kv 的相关操作,请注意用户仍然需要通过 console 来创建 space。目前支持的接口有 Get 和 Put,接口如下。
folly::SemiFuture<StorageRpcResponse<storage::cpp2::ExecResponse>> put(
GraphSpaceID space,
std::vector<nebula::cpp2::Pair> values,
folly::EventBase* evb = nullptr);
folly::SemiFuture<StorageRpcResponse<storage::cpp2::GeneralResponse>> get(
GraphSpaceID space,
const std::vector<std::string>& keys,
folly::EventBase* evb = nullptr);
后续将提供 remove,removeRange 以及 scan 的方法。
下面结合示例说明 kv 接口的使用方法:
// Put 接口
std::vector<nebula::cpp2::Pair> pairs;
for (int32_t i = 0; i < 1000; i ++) {
auto key = std::to_string(folly::Random::rand32(1000000000));
auto value = std::to_string(folly::Random::rand32(1000000000));
pairs.emplace_back(apache::thrift::FragileConstructor::FRAGILE,
std::move(key), std::move(value));
}
// 通过 StorageClient 发送请求,相应的参数为 spaceId,以及写入的键值对
auto future = storageClient->put(spaceId, std::move(pairs));
// 获取结果
auto resp = std::move(future).get();
// Get 接口
std::vector<std::string> keys;
for (auto& pair : pairs) {
keys.emplace_back(pair.first);
}
// 通过 StorageClient 发送请求,相应的参数为 spaceId,以及要获取的 keys
auto future = storageClient->get(spaceId, std::move(keys));
// 获取结果
auto resp = std::move(future).get()
处理返回结果
用户可以通过检查 rpc 返回结果查看相应操作是否成功。此外由于每个 Nebula Graph storage 中都对数据进行了分片,因此如果对应的 Partition 失败了,也会返回每个失败的 Partition 的错误码。若任意一个 Partition 失败,则整个请求失败(resp.succeeded()为 false),但是其他成功的 Partition 仍然会成功写入或读取。
用户可以进行重试,直至所有请求都成功。目前 StorageClient 不支持自动重试,用户可以根据错误码决定是否进行重试。
// 判断调用是否成功
if (!resp.succeeded()) {
LOG(ERROR) << "Operation Failed";
return;
}
// 失败的 Partition 以及相应的错误码
if (!resp.failedParts().empty()) {
for (const auto& partEntry : resp.failedParts()) {
LOG(ERROR) << "Operation Failed in " << partEntry.first << ", Code: "
<< static_cast<int32_t>(partEntry.second);
}
return;
}
读取返回值
对于 Get 接口,用户需要一些操作来获取相应的返回值。Nebula storage 是基于 Raft 的多副本,所有读写操作只能发送给对应 partition 的 leader。当一个 rpc 请求包含了多个跨 partition 的 get 时,Storage Client 会给访问这些 key 所对应的 Partition leader。每个 rpc 返回都单独保存在一个 unordered_map 中,目前还需要用户在这些 unordered_map 中遍历查找 key 是否存在。示例如下:
// 查找 key 对应的 value 是否在返回结果中,如果存在,则保存在 value 中
bool found = false;
std::string value;
// resp.responses()中是多个 storage server 返回的结果
for (const auto& result : resp.responses()) {
// result.values 即为某个 storage server 返回的 key-value paris
auto iter = result.values.find(key);
if (iter != result.values.end()) {
value = iter->second;
found = true;
break;
}
}