Tendis 在银河麒麟 V10 SP3 + 鲲鹏 ARM64(QEMU 模拟)适配与验证记录

环境:Windows + Intel i5-13600K + QEMU 全系统模拟 ARM64
目标:验证 Tendis 是否能够在银河麒麟 V10 SP3 SP3 + 鲲鹏 ARM64 环境离线部署运行
结论:可以编译、可以运行、可以通信,但存在明显 ARM + RocksDB 性能特征差异,需要针对性调优


一、项目背景

最终部署目标环境:

  • 银河麒麟高级服务器操作系统 V10 SP3 2403
  • CPU:鲲鹏 ARM64

当前开发环境:

  • Windows 11
  • Intel i5-13600K
  • QEMU 全系统模拟 ARM64

由于缺少真实鲲鹏物理机,因此采用 QEMU 模拟整机环境进行前置验证,确保:

  • 编译链可用
  • 依赖可满足
  • 服务可启动
  • 基础功能可运行
  • 性能具备参考价值(非最终值)

二、技术验证方案

2.1 选型对比

方案 优点 缺点
Docker + QEMU 简单 与真实系统差异较大
QEMU 全系统 ARM64 最接近真实环境 性能偏差较大

最终选择:

QEMU 全系统 ARM64 + 银河麒麟 V10 SP3


2.2 QEMU 启动环境

关键启动参数:

qemu-system-aarch64.exe -M virt -cpu cortex-a72 -m 8192 -smp 8 -bios D:\Dev\Tools\qemu\share\edk2-aarch64-code.fd -drive if=virtio,file=D:\Dev\Env\kylin-arm64.qcow2,format=qcow2 -cdrom D:\Dev\Projects\ISO\Kylin-Server-V10-SP3-2403-Release-20240426-ARM64.iso -device virtio-gpu-pci -device qemu-xhci -device usb-kbd -device usb-mouse -nic user,model=virtio-net-pci,hostfwd=tcp::2222-:22 -nographic

三、系统安装与基础环境

3.1 系统信息

查看架构:

uname -m

输出:

aarch64

查看系统版本:

cat /etc/os-release

关键输出:

Kylin Linux Advanced Server V10 (Halberd)

3.2 网络问题修复

初始状态:

  • 网卡 disconnected
  • 无 IP

修复操作:

nmcli connection up emp0s1

恢复后 IP:

10.0.2.15

验证网络连通性:

ping -c 4 10.0.2.2

3.3 基础依赖安装

安装编译及工具链依赖:

yum install -y gcc gcc-c++ make cmake git wget curl tar unzip zip openssl-devel zlib-devel

四、第一个核心问题:GCC 版本过低

默认 GCC 版本:

gcc --version
gcc 7.3.0

问题:Tendis 依赖 C++17 特性,GCC 7.3 对 C++17 支持不完整,编译会报错。
解决方案:手动安装 GCC 8.4 到 /usr/local/gcc-8.4,并在 CMake 时显式指定编译器路径。

cmake -DCMAKE_C_COMPILER=/usr/local/gcc-8.4/bin/gcc -DCMAKE_CXX_COMPILER=/usr/local/gcc-8.4/bin/g++ ..

注:GCC 8.4 安装包需提前从可信源获取,或通过源码编译安装(离线环境可提前准备 RPM 包)。

五、源码编译问题修复记录

5.1 submodule 未拉取

源码中的第三方依赖(如 RocksDB)以 git submodule 形式管理,克隆时需一并拉取:

git submodule update --init --recursive

5.2 C_STANDARD=17 不兼容

错误信息:

C_STANDARD is set to invalid value '17'

原因:CMake 版本较低,不识别 C_STANDARD 17。
修复:将 CMakeLists.txt 中的标准改为 C++11(Tendis 实际可用 C++11 编译)。

set(CMAKE_C_STANDARD 11)

5.3 缺少

编译 ldb_tendis.cpp 时报错:

error: 'setw' is not a member of 'std'
error: 'setfill' is not a member of 'std'

修复:在该文件头部添加 #include 。

sed -i '1i #include <iomanip>' \
src/tendisplus/tools/ldb_tendis.cpp

5.4 ldb_tendis 链接失败

错误:

undefined reference: rocksdb::Iterator

该工具是辅助 CLI,不影响 Tendis 服务主程序。若仅需服务端,可单独编译 tendisplus 目标:

make tendisplus

5.5 RocksDB patch 未应用

编译时报错:

rocksdb/tendis_extension.h: No such file or directory

原因:Tendis 对 RocksDB 有定制补丁,需先打补丁才能生成扩展头文件。
修复步骤:

cd src/thirdparty/rocksdb/rocksdb
patch -p1 < ../../patch/0002-add-latency-statistic-log.patch

打补丁后重新编译 RocksDB 和 Tendis。

六、Tendis 服务启动验证

使用默认配置文件启动:

$ ./build/bin/tendisplus tendisplus.conf

报错,因为目录不存在:

IO error: No such file or directory:
While mkdir if missing: ./home/db/catalog

说明:

dir="./home/db"
logDir="./home/log"
dumpdir="./home/dump"

但 ./home/db 这个父目录不存在,所以 RocksDB 创建 catalog 失败了。
直接执行:

mkdir -p ./home/db
mkdir -p ./home/dump
mkdir -p ./home/log

然后确认:

ls -ld ./home ./home/db ./home/dump ./home/log

重新启动:

./build/bin/tendisplus tendisplus.conf

然后立即执行:

ps -ef | grep tendisplus

启动成功。
6.3 端口监听确认

ss -lntp | grep 51002

输出示例:

LISTEN 0  128  127.0.0.1:51002  *:*  users:(("tendisplus",pid=1234,fd=10))

确认服务已成功监听在默认端口 51002。

七、Redis 协议兼容性验证

使用 Redis 客户端连接 Tendis 并执行 PING:

./src/redis-cli -h 127.0.0.1 -p 51002 ping

报错:

无法执行二进制文件: 可执行文件格式错误

基本只有一个原因:
❗ 这个 redis-cli 是 x86_64 编译的,你现在是 ARM64(鲲鹏)
确认 redis-cli 架构:

file ./bin/redis-cli

直接测协议(Redis RESP):

telnet 127.0.0.1 51002

然后输入:

ping

或者更标准 RESP:

*1
$4
PING

返回:

+PONG

编译ARM64 redis-cli:

cd /root
wget https://download.redis.io/releases/redis-7.2.4.tar.gz
tar -xvf redis-7.2.4.tar.gz
cd redis-7.2.4

只编 redis-cli(不用全量 Redis):

make redis-cli
make -j$(nproc) redis-cli MALLOC=libc

检查是否是 ARM64:

file src/redis-cli

输出:

ELF 64-bit LSB executable, aarch64

直接使用:

./src/redis-cli -h 127.0.0.1 -p 51002 ping

八、性能测试

确认 benchmark 工具

./src/redis-benchmark --help

如果有输出说明OK。
报错,因为刚才只编译了redis-cli,重新全量编译:

make -j$(nproc)
  • 测试指标QPS (Queries Per Second):这些测试会输出 Redis 每秒能处理多少请求,数值越高性能越好。通常单机 Redis 的 QPS 能达到 10 万左右。

基础压测(重点)

./src/redis-benchmark -h 127.0.0.1 -p 51002 -t set,get -n 100000 -c 50

用Redis/Tendis 自带的压测工具redis-benchmark,测试两种操作(读,写),总请求数20万次,50个客户端并发连接。

SET 性能:每秒处理 880 次写请求

指标 数值 含义
avg 56 ms 平均一次写 56ms
p95 111 ms 95%请求 < 111ms
p99 136 ms 99%请求 < 136ms
max 224 ms 最慢 224ms

GET 性能:每秒处理 1296 次读请求

指标 数值 含义
avg 37 ms 平均一次读 37ms
p95 79 ms 95%请求 < 79ms
p99 101 ms 99%请求 < 101ms
max 181 ms 最慢 181ms

模拟真实负载(更关键)

  • 小并发读写混合
./src/redis-benchmark -h 127.0.0.1 -p 51002 -t set,get,incr -n 200000 -c 100

用Redis/Tendis 自带的压测工具redis-benchmark,测试三种操作(读,写,原子自增),总请求数20万次,100个客户端并发连接。

指标 数值 含义
avg 136.177 ms 平均一次请求 136.177ms
p95 239.999 ms 95% 请求 < 239.999ms
p99 278.015 ms 95% 请求 < 278.015ms
max 422.143 ms 最慢 422.143ms
  • 高并发测试(看极限)
./src/redis-benchmark -h 127.0.0.1 -p 51002 -t set,get -n 500000 -c 200

用Redis/Tendis 自带的压测工具redis-benchmark,测试两种操作(读,写),总请求数50万次,200个客户端并发连接。

指标 数值 含义
avg 162.770 ms 平均一次写 162.770ms
p95 285.439 ms 95% 请求 < 285.439ms
p99 322.559 ms 99% 请求 < 322.559ms
max 436.479 ms 最慢 436.479ms

延迟测试

./src/redis-benchmark -h 127.0.0.1 -p 51002 -t set -n 100000 -c 10 -q

用Redis/Tendis 自带的压测工具redis-benchmark,测试一种操作(写),总请求数10万次,10个客户端并发连接,并以精简模式输出结果。

指标 数值 含义
吞吐量 737.75 req/s 每秒处理 737.75 次 SET 写请求
p50 9.631 msec 50% 的请求在 9.631ms 内完成(即中位数延迟)
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐