随着知识图谱、GraphRAG 等 AI 技术的发展,图数据库也受到日益增多的关注。
今天,我们来“揭秘”一个开源图数据库项目 Nebula Graph,它的 GitHub 地址是:
https://github.com/vesoft-inc/nebula
在解析项目中,我们通常需要借助 AI 软件来解析,这次我用到的这款软件是 Eagle DevAgent(简称Eagle)
使用网址:https://eagle.capitalren.com/
Nebula Graph项目介绍
Nebula Graph 是一款开源的、分布式的、易扩展的原生图数据库,能够承载包含数千亿个点和数万亿条边的超大规模数据集,并且提供毫秒级查询。
关于图数据库
图数据库是专门存储庞大的图形网络并从中检索信息的数据库。它可以将图中的数据高效存储为点(Vertex)和边(Edge),还可以将属性(Property)附加到点和边上。
图数据库适合存储大多数从现实抽象出的数据类型。世界上几乎所有领域的事物都有内在联系,像关系型数据库这样的建模系统会提取实体之间的关系,并将关系单独存储到表和列中,而实体的类型和属性存储在其他列甚至其他表中,这使得数据管理费时费力。
Nebula Graph 作为一个典型的图数据库,可以将丰富的关系通过边及其类型和属性自然地呈现。
用 Eagle 解读 Nebula Graph
我们把 Nebula Graph 这个开源项目的 GitHub 网址发送给 Eagle。 Eagle 很清晰的把项目概况、主要特性、重要目录和文件、使用的模式或框架等初步的分析结果列了出来。
I 对项目整体解读
Q:解读一下这个项目:https://github.com/vesoft-inc/nebula
Eagle 对整个项目做了概述
I 对技术架构解读
Q:此项目的架构是什么?
结合图示,及文字说明把Nebula Graph的详细架构和交互流程做了罗列
I 对某技术点解读
通过上面的架构图,我们知道 Nebula Graph 在数据及元数据存储中都用到了Raft 算法。
Raft 算法是分布式系统中保证数据存储可靠性和一致性的重要算法,但不同的系统对 Raft 的具体实现迥异,这也是导致系统可用性和性能差别的关键所在,Nebula Graph 是如何实现 Raft 算法的呢?我们把这个问题抛给了 Eagle,下面就来看看TA的精彩回答吧:
Q:解释一下:https://github.com/vesoft-inc/nebula的Raft算法实现
在代码库中定位到关键技术点的实现
Eagle还会列出关键实现代码,例如领导者选举:
folly::Future<bool> RaftPart::leaderElection(bool isPreVote) {
using namespace folly;
bool expected = false;
if (!inElection_.compare_exchange_strong(expected, true)) {
return false;
}
cpp2::AskForVoteRequest voteReq;
decltype(hosts_) hosts;
if (!prepareElectionRequest(voteReq, hosts, isPreVote)) {
std::lock_guard<std::mutex> g(raftLock_);
role_ = Role::FOLLOWER;
leader_ = HostAddr("", 0);
inElection_ = false;
return false;
}
auto proposedTerm = voteReq.get_term();
auto resps = ElectionResponses();
stats::StatsManager::addValue(kNumStartElect);
if (hosts.empty()) {
auto ret = handleElectionResponses(resps, hosts, proposedTerm, isPreVote);
inElection_ = false;
return ret;
} else {
folly::Promise<bool> promise;
auto future = promise.getFuture();
auto eb = ioThreadPool_->getEventBase();
collectNSucceeded(
gen::from(hosts) |
gen::map([eb, self = shared_from_this(), voteReq](std::shared_ptr<Host> host) {
return via(eb, [voteReq, host, eb]() -> Future<cpp2::AskForVoteResponse> {
return host->askForVote(voteReq, eb);
});
}) |
gen::as<std::vector>(),
quorum_,
[hosts](size_t idx, cpp2::AskForVoteResponse& resp) {
return resp.get_error_code() == nebula::cpp2::ErrorCode::SUCCEEDED &&
!hosts[idx]->isLearner();
})
.via(executor_.get())
.then([self = shared_from_this(), pro = std::move(promise), hosts, proposedTerm, isPreVote](
auto&& t) mutable {
pro.setValue(
self->handleElectionResponses(t.value(), std::move(hosts), proposedTerm, isPreVote));
});
return future;
}
}
Eagle:“这个方法发起领导者选举。它首先准备选举请求,然后发送请求并等待响应。如果获得多数票,它将成为领导者。”
关键实现细节也以代码呈现的形式进行了解读
Q:Nebula Graph 的 Raft 算法实现中的领导者(leader),是集群中的某个节点吗?还是说对数据进行分片,每个分片会以多个副本存在几个节点上,每个节点都有可能成为不同数据分片的leader?
Eagle 对 Nebula Graph 中的数据分片机制及其与 Raft 算法的关系做了详细解释,回答了用户的疑问。
Eagle 还对要点进行了简明扼要的总结,让用户一目了然。
Eagle 按照用户提示,给出了关键代码。
小tips
Eagle 除了可以直接提交 GitHub 开源项目地址外,也可通过上传开源项目 Zip 压缩包的形式进行提问
有更多想要了解的也可以关注视频号:码力一哥。十一期间还有直播,可以和老师 1V1 交流 AI 大模型编程的相关问题,助力职场晋升!