KV 接口

接口示例

Nebula Graph storage 提供 key-value 接口,用户可以通过 StorageClient 进行 kv 的相关操作,请注意用户仍然需要通过 console 来创建 space。目前支持的接口有 Get 和 Put,接口如下。

  1. folly::SemiFuture<StorageRpcResponse<storage::cpp2::ExecResponse>> put(
  2. GraphSpaceID space,
  3. std::vector<nebula::cpp2::Pair> values,
  4. folly::EventBase* evb = nullptr);
  5. folly::SemiFuture<StorageRpcResponse<storage::cpp2::GeneralResponse>> get(
  6. GraphSpaceID space,
  7. const std::vector<std::string>& keys,
  8. folly::EventBase* evb = nullptr);

后续将提供 remove,removeRange 以及 scan 的方法。

下面结合示例说明 kv 接口的使用方法:

  1. // Put 接口
  2. std::vector<nebula::cpp2::Pair> pairs;
  3. for (int32_t i = 0; i < 1000; i ++) {
  4. auto key = std::to_string(folly::Random::rand32(1000000000));
  5. auto value = std::to_string(folly::Random::rand32(1000000000));
  6. pairs.emplace_back(apache::thrift::FragileConstructor::FRAGILE,
  7. std::move(key), std::move(value));
  8. }
  9. // 通过 StorageClient 发送请求,相应的参数为 spaceId,以及写入的键值对
  10. auto future = storageClient->put(spaceId, std::move(pairs));
  11. // 获取结果
  12. auto resp = std::move(future).get();
  1. // Get 接口
  2. std::vector<std::string> keys;
  3. for (auto& pair : pairs) {
  4. keys.emplace_back(pair.first);
  5. }
  6. // 通过 StorageClient 发送请求,相应的参数为 spaceId,以及要获取的 keys
  7. auto future = storageClient->get(spaceId, std::move(keys));
  8. // 获取结果
  9. auto resp = std::move(future).get()

处理返回结果

用户可以通过检查 rpc 返回结果查看相应操作是否成功。此外由于每个 Nebula Graph storage 中都对数据进行了分片,因此如果对应的 Partition 失败了,也会返回每个失败的 Partition 的错误码。若任意一个 Partition 失败,则整个请求失败(resp.succeeded()为 false),但是其他成功的 Partition 仍然会成功写入或读取。

用户可以进行重试,直至所有请求都成功。目前 StorageClient 不支持自动重试,用户可以根据错误码决定是否进行重试。

  1. // 判断调用是否成功
  2. if (!resp.succeeded()) {
  3. LOG(ERROR) << "Operation Failed";
  4. return;
  5. }
  6. // 失败的 Partition 以及相应的错误码
  7. if (!resp.failedParts().empty()) {
  8. for (const auto& partEntry : resp.failedParts()) {
  9. LOG(ERROR) << "Operation Failed in " << partEntry.first << ", Code: "
  10. << static_cast<int32_t>(partEntry.second);
  11. }
  12. return;
  13. }

读取返回值

对于 Get 接口,用户需要一些操作来获取相应的返回值。Nebula storage 是基于 Raft 的多副本,所有读写操作只能发送给对应 partition 的 leader。当一个 rpc 请求包含了多个跨 partition 的 get 时,Storage Client 会给访问这些 key 所对应的 Partition leader。每个 rpc 返回都单独保存在一个 unordered_map 中,目前还需要用户在这些 unordered_map 中遍历查找 key 是否存在。示例如下:

  1. // 查找 key 对应的 value 是否在返回结果中,如果存在,则保存在 value 中
  2. bool found = false;
  3. std::string value;
  4. // resp.responses()中是多个 storage server 返回的结果
  5. for (const auto& result : resp.responses()) {
  6. // result.values 即为某个 storage server 返回的 key-value paris
  7. auto iter = result.values.find(key);
  8. if (iter != result.values.end()) {
  9. value = iter->second;
  10. found = true;
  11. break;
  12. }
  13. }