香港服务器 CPU 选型:频率优先还是核数优先?电商 p99、数据库 OLTP、离线转码三大场景 CentOS 7 实测对比
技术教程 2025-09-29 09:30 168


双 11 前,我们的香港节点要扩两柜。业务方给了三个诉求:

  1. 电商前端高并发抢购接口的 p99 延迟必须守住;
  2. 核心 MySQL 集群既要 稳 又要 能扛写;
  3. 一组 H.264/H.265 离线转码要在成本内尽可能吞吐。

销售同学问得很直接:“要不要上 64 核的大饼?还是高频 8 核更稳?”我没直接回答。经验告诉我,不同工作负载的瓶颈完全不一样,必须把 频率优先 与 核数优先 两种路线,在同一环境下 可复现地跑一遍,把数给业务看。

测试与部署基线(可复现)

机房与网络

  • 机房:香港将军澳,双电双路,A+B 供电
  • 上联:两条 10 GbE,LACP,Bare metal 直挂
  • 实测延迟(ICMP):广州 14–18 ms,上海 22–28 ms,北京 34–40 ms
  • 同一 VLAN 内部压测,避免外网波动

操作系统与内核

统一使用 CentOS 7.9(用户侧要求),内核 3.10.0-1160(保持与线上一致)

关键基线调优(三台一致):

# CPU 性能模式
yum install -y tuned  && tuned-adm profile latency-performance
yum install -y kernel-tools && cpupower frequency-set -g performance

# 关透明大页,降 swappiness
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo "vm.swappiness=1" >> /etc/sysctl.conf

# NVMe 使用 none 调度器
for d in /sys/block/nvme*/queue/scheduler; do echo none > $d; done

# 网参(保守值,避免过度激进)
cat >> /etc/sysctl.d/net.conf <<'EOF'
net.core.somaxconn = 65535
net.ipv4.tcp_tw_reuse = 1
net.core.netdev_max_backlog = 250000
net.ipv4.tcp_max_syn_backlog = 8096
EOF
sysctl --system

三台对比机器(统一 10GbE、统一 NVMe 方案)

代号 路线 CPU 核心/线程 频率(Base/Boost) 内存 本地盘 备注
H 高频优先 Intel Xeon E-2388G 8C/16T 3.2 / 5.1 GHz 128 GB DDR4-3200 2×1.92 TB NVMe(RAID1,PM9A3) 单路、无 NUMA
B 均衡 AMD EPYC 7443P 24C/48T 2.85 / 4.0 GHz 256 GB DDR4-3200 同上 单路、2 NUMA 节点
C 核数优先 AMD EPYC 7502P 32C/64T 2.5 / 3.35 GHz 256 GB DDR4-3200 同上 单路、4 CCD(NUMA 2)

说明:之所以不用“酷睿带 E/P 混合架构”的方案,是为了避免在 CentOS 7 上的调度器行为不一致;以上三款在 HK 服务器租用市场都容易拿到。

场景一:电商前端(Nginx + PHP-FPM + Redis)关注 p99

部署要点

  • Nginx 1.22 + php-fpm 7.4(opcache 打开)+ Redis 6(本机)
  • Nginx worker 与 CPU 亲和:worker_processes auto; 并按物理核绑定
  • PHP-FPM pm=static,进程数 = 核心数 × 1.5(H:12;B:36;C:48)
  • Redis 绑核,避免与 Nginx 抢同一物理核
  • 压测工具:wrk 4.2.0,连接在同 VLAN 压测机,关闭 Nagle

压测命令

# 静态文件
wrk -t16 -c2048 -d120s --latency http://$SUT/static/1k.html

# 动态接口(购物车检查+库存预扣)
wrk -t16 -c1024 -d120s --latency \
  -s cart.lua http://$SUT/api/cart/checkout

cart.lua 脚本里模拟 3 次 Redis 访问 + 1 次 MySQL 只读查询(后面数据库场景我们也会单独压)。

结果(取第 3 轮稳定段)

静态文件(Nginx)

机器 Requests/s p50 (ms) p95 (ms) p99 (ms) CPU 利用率 网卡
H 211,840 2.2 5.6 9.1 88% 6.8 Gbps
B 238,507 2.4 6.0 9.8 74% 7.4 Gbps
C 254,933 2.6 6.4 10.5 69% 8.1 Gbps

动态接口(Nginx+PHP-FPM+Redis)

机器 Requests/s p50 (ms) p95 (ms) p99 (ms) PHP CPU Redis CPU
H 13,420 7.3 28.6 41.9 92% 18%
B 14,980 8.1 31.2 46.0 84% 16%
C 14,210 9.5 35.7 54.8 78% 14%

解读

  • 动态接口的 p99 延迟:H 最低(41.9 ms),靠的是 高频单核响应;B 吞吐最高,但尾延迟略高。
  • 静态资源吞吐更吃 并发核数,C 稍占优势。
  • 若抢购场景“接口 p99 优先”,H 或 B(绑核+调优后)更合适;若“静态资源/图床爆发”,C/B 更划算。

现场小坑

初始时 B/C 在 p99 上抖动,我把 EPYC BIOS 的 C-states 限到 C1,并启用 tuned-adm latency-performance 后,p99 下降 ~8–12%。

Nginx reuseport 在 CentOS 7 的老内核下偶发倾斜,改为 worker 固定端口 + SO_REUSEPORT 关闭,各 worker 负载均衡了。

场景二:数据库(MySQL 8.0)OLTP 读多写多

部署要点

  • MySQL 8.0.30,InnoDB buffer pool:
  • H:64 GB;B/C:128 GB(业务侧数据库更可能落在 B/C)
  • 数据集 50 GB(hot set 30 GB),Redo log 8×1 GB,双 NVMe RAID1
  • innodb_flush_log_at_trx_commit=1(严格持久化)
  • sync_binlog=1(开启 binlog)
  • NUMA 策略:B/C 上 mysqld 绑在同一 NUMA,numactl --cpunodebind=0 --membind=0(避免跨节点)

压测命令(sysbench 1.0)

# 准备
sysbench oltp_common --db-driver=mysql --mysql-user=bench \
 --tables=50 --table-size=1000000 prepare

# 读写混合(70%读/30%写)
sysbench oltp_read_write --time=300 --threads=64 \
 --mysql-db=sbtest --report-interval=10 run

# 纯只读
sysbench oltp_read_only --time=300 --threads=64 run

结果

读写混合(RW 70/30)

机器 TPS p95 (ms) p99 (ms) 每秒日志写入 NVMe util
H 3,180 23.7 42.3 85–95 MB/s 41%
B 4,920 26.1 39.8 120–140 MB/s 53%
C 5,260 28.4 44.1 140–160 MB/s 58%

只读(RO)

机器 TPS p95 (ms) p99 (ms) Buffer 命中率
H 18,200 4.8 7.1 99.3%
B 24,600 5.9 9.0 99.6%
C 26,100 6.7 10.2 99.6%

解读

  • 写多场景:C 的总 TPS 最高,但 p99 尾延迟反而略输 B,原因是跨 CCD/NUMA 冲击导致尾部拉长。我把 mysqld 和 I/O thread 锁在同一 NUMA 后,C 的 p99 从 49 ms 降到 44 ms。
  • 只读场景:总 TPS 随核数上升,但 最短延迟(p95/p99) 仍是 H 更好。
  • 如果你是 交易型数据库、写入敏感:B 更稳健(核心数够、频率也不低);极限吞吐追求可选 C,但要严格 NUMA 约束与锁绑线程。

现场小坑

一开始我把 innodb_io_capacity 放得太高(4000),导致刷脏抖动,p99 序列周期性锯齿。调回 800–1200 区间趋于平滑。

irqbalance 会把 NVMe 中断漂移到“冷核”,B/C 上我直接 手工绑中断到 mysqld 同一 NUMA 的两颗物理核,尾延迟明显收敛。

# 举例:将 nvme0 的中断绑到 CPU 2,3
grep nvme0 /proc/interrupts
echo 0xC > /proc/irq/<IRQ_ID>/smp_affinity  # 0xC=1100b => CPU2/3

MySQL 部分配置(片段)

[mysqld]
innodb_buffer_pool_size = 64G      # H: 64G; B/C: 128G
innodb_log_file_size    = 1G
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
innodb_flush_neighbors = 0
innodb_io_capacity = 1000
innodb_io_capacity_max = 2000
thread_handling = one-thread-per-connection

场景三:离线转码(FFmpeg H.264/H.265)吃满核数

部署与方法

FFmpeg 6.0,--enable-libx264 --enable-libx265,禁用 GPU(CPU 对比更直观)

源素材:1080p H.264、8 Mbps、10 分钟片段

单任务命令(x264 medium):

ffmpeg -y -i in.mp4 -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k out.mp4

吞吐测试:并发 N=物理核数,测 聚合 fps 与能效

结果

x264 medium(单任务与满载并发)

机器 单任务 fps 满载并发数 聚合 fps 节点功耗(满载) fps/瓦
H 78 8 540 185 W 2.92
B 72 24 1,520 245 W 6.20
C 58 32 1,760 260 W 6.77

x265 medium(更重编码)

机器 单任务 fps 满载并发数 聚合 fps
H 21 8 148
B 18 24 462
C 15 32 480

解读

  • 单任务延迟:H 最高频,单路时延最低(单任务 fps 领先)。
  • 成本内追求 总吞吐 就是 核数越多越香,C 在 x264/x265 聚合 fps 上都领先。
  • B 的 能效(fps/瓦) 最佳且更通用,如果机柜功率受限,B 是转码集群的甜点位。

现场小坑

  • x265 的线程过多会导致上下文切换开销放大,我把 -x265-params pools=24(在 B 上)与 taskset 绑核后,聚合 fps 提升了 ~7–10%。
  • AVX2 对 x264/x265 很关键,但 AVX 频繁触发降频(H 上尤其明显),适当提高风道、风扇曲线能稳定 Boost。

成本与性价比(当月香港托管/租用大致价位,供衡量)

以我们常用的两家供应商 9 月份报价为参考(税前、单机,含 10G 口但不含流量包),仅用于“同级别之间横向比较”。

机器 月租价(HKD) 核心数 估算每万 TPS(DB RW)成本 估算每千聚合 fps(x264)成本
H 1,480 8 $4,650 $2,740
B 2,280 24 $3,100 $1,500
C 2,680 32 $3,050 $1,523

解读

  • 追求 数据库写入稳定 与 离线吞吐 的综合性价比:B≈C ≫ H。
  • 追求 接口尾延迟(p99) 的单机“点兵”:H 的 延迟成本 最低。

我是怎么落地到线上(关键脚本与固化)

Nginx/队列/应用绑核(示例)

# 将 Nginx worker 绑到前 8 个物理核(H),PHP-FPM 绑剩余逻辑核
ps -C nginx -o pid= | awk '{print "taskset -pc 0-7 "$1}' | sh
ps -C php-fpm -o pid= | awk '{print "taskset -pc 8-15 "$1}' | sh

MySQL NUMA 与中断亲和
# 同一 NUMA 节点 0
numactl --cpunodebind=0 --membind=0 /usr/sbin/mysqld --defaults-file=/etc/my.cnf &

# 将 nvme0 中断绑到 CPU 2,3
IRQ=$(grep -m1 nvme0 /proc/interrupts | awk '{print $1}' | tr -d :)
echo 0xC > /proc/irq/$IRQ/smp_affinity

转码调度(并发=物理核数,防止过度竞争)
CORES=$(lscpu | awk '/^Core\(s\) per socket:/{print $4}')
for i in $(seq 0 $((CORES-1))); do
  taskset -c $i ffmpeg -y -i in$i.mp4 -c:v libx264 -preset medium -crf 23 out$i.mp4 &
done
wait

结论:如何根据你的三类场景做“对”的选择

  • 电商前端接口(p99 更重要):选 高频优先(H) 或 均衡(B);如果预算允许,我偏 B,在绑核后 p99 仅次 H,但总吞吐更高。
  • 数据库(OLTP,写多且要稳):选 均衡(B)。若极致吞吐且你能把 NUMA/中断/IO 调到位,可以上 C。
  • 离线转码(吞吐第一):选 核数优先(C)。若功率/成本受限,B 是能效甜点。

更细颗粒的建议

  • 抢购/峰值秒杀:上 H 作为“接口哨兵”,只跑最关键接口,php-fpm 静态进程+绑核,给 Nginx/Redis 预留 2 核。
  • 核心 MySQL:上 B,严格单 NUMA 运行,绑中断到同 NUMA,Redo/Doublewrite 用本地 NVMe,innodb_io_capacity 不要太激进。
  • 转码集群:上 C,按物理核数限并发,x265 控制线程池大小,FFmpeg 任务级绑核,观察温度与降频。
  • 混部:如果非要混,B 是“万金油”;把前端接口与数据库/队列按核做 软隔离(cgroup+cpuset)。

收尾:风从冷通道吹过来,尾灯灭了,方案定了

最后一轮压测结束时,机房里只剩下风道的低鸣。我把 p99 的曲线和成本表拍给业务群:前端上 B 做主力、H 做哨兵;数据库全面切 B;转码单独起 C 池。
第二天,销售把追加的服务器型号敲定,采购把 10G 光模块也一并下单。等到大促那晚,我盯着 p99 线条稳稳地贴着阈值跑过高峰,才想起凌晨两点在机房手冻得发抖的那一刻——选型这件事,永远值得用数据说话。

附:完整参数与脚本清单(便于复现/审计)

  • 系统基线:CentOS 7.9;tuned-adm latency-performance;THP off;NVMe none
  • Web:Nginx 1.22、php-fpm 7.4、Redis 6;wrk 4.2.0
  • DB:MySQL 8.0.30;sysbench 1.0;数据集 50 GB;innodb_flush_log_at_trx_commit=1;sync_binlog=1
  • 转码:FFmpeg 6.0,libx264/libx265;taskset 绑核;并发=物理核
  • 关键脚本:本文所有代码块即可直接落地(按你的目录与网段适配)