ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

NebulaGraph 存储性能压测工具 storage-perf 实战指南:压测参数、方法选择与数据完整性校验

NebulaGraph 存储性能压测工具 storage-perf 实战指南:压测参数、方法选择与数据完整性校验 NebulaGraph 存储性能压测工具 storage-perf 实战指南压测参数、方法选择与数据完整性校验【免费下载链接】nebulaA distributed, fast open-source graph database featuring horizontal scalability and high availability项目地址: https://gitcode.com/gh_mirrors/nebul/nebulastorage-perf是 NebulaGraph 仓库中用于直接压测存储服务storage service的基准测试工具它绕过 Graph 层、以 RPC 方式向 Storage 服务灌入读写负载帮助开发者在部署真实业务前量化getNeighbors、addVertices、addEdges等核心接口的吞吐与延迟。本文以 src/tools/storage-perf/README.md 为骨架结合 StoragePerfTool.cpp 与 StorageIntegrityTool.cpp 的源码实现完整讲解工具的全部配置参数、压测方法与输出指标含义并介绍配套的数据完整性校验工具。读完本文你将能够独立搭建压测环境、正确配置参数、读懂压测日志并用环形链表方案验证存储数据在读写后的完整性。工具概览一个入口、两类能力按 src/tools/storage-perf/README.md 的说明_build/storage_perf是用于测试存储服务的性能工具。该目录下包含两个相互独立的可执行目标storage_perf性能压测工具源码为 StoragePerfTool.cpp支持多种 RPC 方法的混合/单一压测storage_integrity数据完整性校验工具源码为 StorageIntegrityTool.cpp其设计基于 HBase 的IntegrationTestBigLinkedList思路README 中明确说明 Integration test is based onIntegrationTestBigLinkedListof HBase。两个工具的共同点是都直接通过 StorageClient 与 meta 服务、storage 服务通信不经过 Graph 查询层因此测到的是存储引擎与 RPC 链路的真实能力。需要说明的是从当前仓库源码看src/tools/storage-perf/CMakeLists.txt 中两个可执行目标的nebula_add_executable与install规则均处于注释状态且 src/tools/CMakeLists.txt 仅在未启用 standalone 版本NOT ENABLE_STANDALONE_VERSION时才添加storage-perf子目录。因此在实际使用前需要根据你的构建环境按需启用该目标的编译README 中_build/storage_perf即为构建产物路径。测试前置条件空间、Tag 与 EdgeREADME 明确指出测试前需要先创建图空间graph space、Tag 和 Edge 类型。工具默认使用的名字分别为图空间testTagtest_tagEdgetest_edge这三个名字分别对应源码中的默认参数FLAGS_space_name、FLAGS_tag_name、FLAGS_edge_nameStoragePerfTool.cpp。从源码实现看工具的初始化流程会进一步印证这一前提StoragePerfTool.cpp解析meta_server_addrs得到 meta 服务地址列表通过NetworkUtils::toHosts无法解析则直接退出创建folly::IOThreadPoolExecutor线程数由io_threads控制与MetaClientskipConfig_ true并调用waitForMetadReady()等待 meta 服务就绪通过getSpaceIdByNameFromCache按名字解析 SpaceID——图空间必须已存在否则报Get SpaceID Failed并退出解析 Tag若test_tag不存在工具会自动创建一个仅含一个 STRING 类型属性col_1的 Tag schema然后等待heartbeat_interval_secs 1秒让 schema 同步生效若已存在则直接使用并读取其全部属性名用于构造请求Edge 的处理逻辑与 Tag 完全对称不存在则自动创建col_1属性存在则复用。这意味着图空间需要你预先通过 Graph 客户端如nebula-console创建而 Tag/Edge 可以由工具自动补齐但为保证压测数据的可预期性建议仍按 README 建议提前创建好三者。配置参数全解析README 给出了完整的参数参考表下表逐项继承并补充源码中的实际定义源码位于 StoragePerfTool.cpp属性名README 默认值源码默认值说明threads21压测总线程数每个线程独立循环发送请求qps10001000压测工具的总目标 QPStotalReqs1000010000压测期间的总请求数达到后停止io_threads1010客户端 IO 线程数folly IOThreadPoolExecutor 线程池大小methodgetNeighborsgetNeighbors被测方法getNeighbors、addVertices、addEdges、getVertices、getEdgesmeta_server_addrsmeta 服务地址如127.0.0.1:9559min_vertex_id11最小的顶点 ID工具内部会转换为字符串max_vertex_id1000010000最大的顶点 ID工具内部会转换为字符串size1000—见property_size每个请求的数据量space_nametesttest指定图空间名tag_nametest_tagtest_tag指定 Tag 名要求其属性全部为字符串类型edge_nametest_edgetest_edge指定 Edge 名要求其属性全部为字符串类型random_messagefalsetrue是否向存储服务写入随机消息源码中 README 未列出的补充参数对照源码可以发现README 参数表之外还有三个实际生效的 gflags这属于 README 与源码的差异使用时以源码为准属性名默认值说明property_size1000单个属性的字符串长度字节即 README 中size的实际实现载体concurrency50单次批量发出的并发请求数与令牌桶联动batch_num1每个请求批量包含的顶点/边数量此外还有两个值得注意的 README 与源码默认值差异threadsREADME 写 2源码默认 1与random_messageREADME 写 false源码默认 true。压测前应显式指定这些参数不要依赖默认值。参数的作用机制min_vertex_id/max_vertex_id决定随机顶点 ID 的取值区间。randomVertices()用folly::Random::rand32(max - min) min生成随机 IDStoragePerfTool.cpp因此区间大小直接影响数据分布范围。random_messageproperty_sizegenData()在random_messagetrue时为每个属性生成property_size长度的随机字符串字符集为数字 大小写字母见 StoragePerfTool.cpp为 false 时属性值为空字符串。写入数据的真实负载大小 属性个数 × 属性长度。meta_server_addrs格式与 conf/nebula-metad.conf.default 中的--meta_server_addrs127.0.0.1:9559保持一致多个地址用逗号分隔。支持的压测方法与其实现细节method参数支持五种方法README 列举了四种源码 StoragePerfTool.cpp 实际支持五种method 取值底层 StorageClient 调用实现要点getNeighborsgetNeighborsStorageClient.h查询随机顶点的邻居边方向固定为EdgeDirection::BOTH携带顶点属性与边属性请求addVerticesaddVerticesStorageClient.h以ifNotExiststrue, ignoreExistedIndexfalse写入批量顶点顶点 ID 从min_vertex_id起递增addEdgesaddEdgesStorageClient.h批量写入边每条边为vintId - vintId1、rank 为 0getVerticesgetPropsStorageClient.h以kVid作为输入列构造 DataSet返回随机顶点的 Tag 属性getEdgesgetProps以kSrc/kType/kRank/kDst四列构造 DataSet返回随机边的属性其中getVertices/getEdges在源码中通过统一的getProps接口实现只是传入的VertexProp/EdgeProp不同。压测数据生成上genVertices()与genEdges()都支持batch_num批量放大单请求负载StoragePerfTool.cpp边数据始终指向相邻递增的顶点保证数据在拓扑上的自洽性。压测执行流程与结果输出解读运行模型Perf::run()的主流程为StoragePerfTool.cpp初始化客户端 → 拉起threads个线程 → 每个线程在runInternal()中循环执行直到全局finishedRequests_达到totalReqs。runInternal()的循环体包含两个关键机制令牌桶限流每次通过tokenBucket_.consumeOrDrain(FLAGS_concurrency, FLAGS_qps, FLAGS_concurrency)从 folly 的DynamicTokenBucket申请令牌StoragePerfTool.cpp即单轮最多发concurrency个请求、总速率不超过qps进度与指标上报每处理 2000 个请求打印一次日志PLOG_EVERY_N(INFO, 2000)随后usleep(500)微休眠避免忙循环打满 CPU。日志输出解读压测过程中会周期性输出类似下面的进度日志Progress 42%, qps1032, latency(us) median 342, p90 891, p99 2134这些指标来自两个 folly 直方图对象latencies_与qps_StoragePerfTool.cppProgress已完成请求数占totalReqs的百分比qps当前吞吐qps_.rate(0)latency(us) median / p90 / p99最近一个时间窗口内请求延迟微秒的 50 分位、90 分位与 99 分位估计值。每个请求的延迟通过time::WallClock::fastNowInMicroSec()在发出前与回调返回后各取一次时间戳相减得到见各*Task()实现。压测全部结束后还会输出总耗时与总请求数Total time cost 12345ms, total requests 10000注意getNeighbors、addEdges等任务中若请求失败会在回调里打印Request failed及失败分片信息addVerticesTask会打印具体的 partition 与错误码这些信息同样是压测结论的重要输入。Storage Integrity Tool环形链表式数据完整性校验README 的最后一段说明集成测试基于 HBase 的IntegrationTestBigLinkedList。该思路在 StorageIntegrityTool.cpp 中有完整的源码实现其核心思想是构造一个环形链表状的数据矩阵然后沿链表遍历验证每条数据都能正确读写。参数与默认值属性名默认值说明meta_server_addrsmeta 服务地址io_threads10客户端 IO 线程数space_nametest_space目标图空间名注意与压测工具的默认test不同first_key1链表的起始 key最小 keywidth100矩阵宽度每行的节点数height1000矩阵高度行数校验原理IntegrityTest类StorageIntegrityTool.cpp把数据组织成一个width × height的矩阵每个 key 的 value 是下一个节点的 key所有 key-value 构成一条首尾相接的大链表。其数据排布可用源码注释中的示意图理解——首行、前驱行、当前行逐行串接最后一行经过旋转后与首行闭合从而形成一条可从任意节点出发、走width * height步回到起点的环形链表。具体流程为prepareData()先为第一行生成width个 key从first_key开始递增然后逐行调用insertRow()写入中间各行每个 key 指向上一行对应位置的 key最后将末行旋转一位再插入首行完成闭环StorageIntegrityTool.cpp写入通过client_-put(spaceId_, keyValues)批量完成每 10000 个 key-value 打印一次进度validate()从first_key出发循环width * height次每次用client_-get(spaceId_, {nextId})取回下一个 keyStorageIntegrityTool.cpp若中途取不到值或最终没有回到起点则校验失败并返回非零退出码。因此该工具不仅能验证写入后可读回还能验证整条数据链的连续性——任何一条数据丢失或错乱都会导致遍历中断或终点不闭合是检测存储层数据丢失、损坏等问题的有效手段。初始化时若width * height超过int32上限会直接报错退出。源码阅读指引如果希望深入理解这两个工具的实现建议按以下路径阅读压测主逻辑StoragePerfTool.cppPerf::run/runInternal/ 五个*Task方法完整性校验StorageIntegrityTool.cppprepareData/validate底层 RPC 客户端接口src/clients/storage/StorageClient.hCommonRequestParam结构与getNeighbors/addVertices/addEdges/getProps声明构建集成src/tools/CMakeLists.txt 与 src/tools/storage-perf/CMakeLists.txt服务端默认端口与 meta 地址配置conf/nebula-metad.conf.default。结合这些源码你可以在压测前准确预估每个参数对负载模型的影响例如concurrency决定瞬时并发、qps决定稳态速率、property_size决定单请求字节数从而设计出贴合真实业务场景的压测方案。【免费下载链接】nebulaA distributed, fast open-source graph database featuring horizontal scalability and high availability项目地址: https://gitcode.com/gh_mirrors/nebul/nebula创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进