ScyllaDB 单节点百万OPS:shard-per-core 架构如何重塑 NoSQL 性能
2026/9/17 8:54:29 网站建设 项目流程

简介:面向NoSQL数据库选型与性能调优场景,这份PDF资料系统梳理了ScyllaDB的架构特性和应用加速实践。内容围绕shard-per-core线性扩展、自研缓存机制、自动调优与动态调度等核心设计展开,并与传统Cassandra在多核利用、延迟表现、配置复杂度等方面进行对比,适合需要处理大规模实时数据、对低延迟有严格要求的架构师、DBA及运维人员阅读。资源包共1个文件,为PDF电子文档,整体大小约1.24MB,便于下载后离线学习。目前已有95人学习,资料价值已初步获得认可。全篇源自ScyllaDB官方技术分享,包含基准测试结论与Outbrain案例,读者可以快速掌握其性能优势、适用场景以及与Spark、Presto、Kafka等生态组件的集成方式,为实际选型或架构优化提供参考。

1. 单节点百万 OPS 的 NoSQL 加速是怎么实现的

先摆一个结论:ScyllaDB 在单节点上能做到 100 万 OPS 以上,99% 延迟压在 1 毫秒内。这不是调参调出来的,是换了一套执行模型换出来的。Session 里那句话说得直白:Cassandra 受限于 Java 和 JVM 的 GC,Scylla 用 C++ 重写,从 Java 那个坑里跳出来了。很多人以为 Scylla 只是换了个语言重写 Cassandra,这是表面理解。真正有价值的差异在三点:多核利用方式、缓存管理、以及在故障和热点场景下的延迟稳定性。如果你正被 Cassandra 的多核利用率低、GC 停顿导致长尾延迟、或者前面堆了一层 Memcache 来挡读流量的问题困扰,这篇把 ScyllaDB 的设计决策和落地参数一次说清楚。适合的人群:维护 Cassandra 或类似 NoSQL 集群的 DBA、做大数据存储选型的架构师、以及被性能问题追着跑的一线开发。整个方案最早来自 KVM hypervisor 的创建团队,2015 年 Cassandra Summit 上公开,开源且兼容 Cassandra 协议,这意味着你不需要换客户端就能迁移。

2. 抛弃 JVM 后:shard-per-core 与真正的线性扩展

2.1 Cassandra 在多核下的核心瓶颈

先看 Cassandra 在多核处理器上的表现。Java 实现里,数据结构和锁都是全局共享的,多核 CPU 要访问同一个 MemTable、同一条 SSTable 的索引,必须经过锁或者原子操作来串行化。核越多,竞争越激烈,吞吐量增长越来越慢,最终平掉。这就是为什么 Cassandra 集群规模大了之后,单节点吞吐上不去,你只能靠加节点来扛。加节点能解决吞吐,但解决不了延迟——JVM 的 GC 停顿是全堆暂停的,卡一次就是几十到几百毫秒,99% 延迟直接爆炸。

Scylla 团队在 KVM 时代就做过类似的用户态调度器,到了数据库领域把同一套思路带了过来。核心是 Seastar 框架,背后是 shard-per-core 模型:每个 CPU 核是一个独立的 shard,有自己的内存、自己的缓存、自己的事件循环,核之间不共享任何可变状态。没有共享状态就没有锁,没有锁就没有竞争。

2.2 数据怎么在 shard 之间分配

具体数据层面,Scylla 用 token 范围 + 一致性哈希把数据按分区键拆开。每个 shard 负责一部分 token 范围的数据,数据落在哪个 shard 由分区键经过哈希映射决定,路由规则固定。这样做的直接结果是:访问单条数据时,只有处理当前 shard 的那个核参与工作,其他核完全无感,天然避免了跨核通信。

执行模型上,Scylla 在用户态管理线程,响应式编程范式驱动每个 shard 上的任务调度。I/O 操作不阻塞线程,而是注册回调后立即返回,事件循环继续处理其他请求。这个模型下,CPU 不会因为等待磁盘而空转,整机利用率高。

SSTable 文件格式、CQL 协议、JMX 管理接口都和 Cassandra 兼容。让熟悉 Cassandra 的人无缝切入,也让依赖 CQL 驱动的生态直接复用。但这个兼容性也带来坑,后面第 5 章会专门提到。

2.3 核数、内存与磁盘的比例怎么设

部署层面,核数分配是有讲究的。ScyllaDB 官方推荐至少 8 核起步,内存和磁盘比例控制在 1:30 左右,也就是 256GB 内存的机器配 7-8TB 的 NVMe SSD。配置时需要让 Seastar 能拿到机器的全部核,没有别的业务进程抢 CPU。Scylla 会把内存按 shard 数切分,每核一块。一台 32 核机器跑 Scylla,实际运行的就是 32 个独立节点,每个负责自己的数据子集。

通过nodetool info查看当前节点上各 shard 的负载情况:

nodetool info # 关注其中的 Key 指标 # Load : 2.64 TB # Shard 0: # Compacting : 58 MB # CumulativeCompaction : 1200 MB # Cached : 142 MB # Read : 544 ops/s # Write : 1234 ops/s # Write & Read : 0 bytes/s # Read & Write : 0 bytes/s

正常情况下,各 shard 的 ops/s 数应该接近,差值在 10% 以内说明数据分布均匀。如果某个 shard 的读ops显著高于其他 shard,说明 token 范围分配不均匀,常见于初始数据量小、节点少时新建的 keyspace,这时需要跑nodetool repair并且重新平衡 token 范围。

scylla nodetool repair -pr

-pr参数表示只修复主副本对应的范围,避免并行任务太多互相抢磁盘。

2.4 为什么说 Auto Tuned 不只是噱头

Cassandra 的调参是出了名的复杂:堆大小、GC 算法、concurrent_writes、memtable_heap_space 等一堆参数相互影响,调完一个另一个又成了瓶颈。Scylla 把这套东西迁到了自己的运行时里。

比如 CPU 资源的分配策略。Scylla 有个运行时参数叫seastar_utilization,默认值是 0.7。这个数字的含义是:Seastar 调度器会限制 CPU 使用率不超过 70%,剩余 30% 留给后台任务。如果业务需要更高吞吐,可以调高到 0.9,但要承担后台任务饥饿导致 compaction 跟不上的风险。

# 查看当前值 curl -X GET "http://localhost:10000/system/config/seastar_utilization" # 动态调整到 0.85,立即生效,无需重启 curl -X POST "http://localhost:10000/system/config/seastar_utilization" \ -H "Content-Type: application/json" \ -d '{"value": 0.85}'

这里背后的机制是:Scylla 有一个统一的调度组,把 CPU、I/O、内存三类资源放在同一个控制平面里管理。后台的 compaction、repair 和前台的读写请求走不同的调度组,各自有独立的配额。这和 Cassandra 里 compaction 和读写争抢 I/O 的情况形成对比,后者常常出现一次大范围 compaction 把所有读写拖垮的场景。Scylla 中的 compaction 如果检测到前台延时在升高,会自动降低自身的 I/O 带宽占用。

如果你想验证调度是否生效,看nodetool stat里的 background garbage 和 foreground 指标变化对比即可。

3. 从 Cassandra 平滑迁移:协议兼容下的配置与命令实战

3.1 注意:兼容不等同于一场直接迁移

Scylla 对外兼容 Cassandra 的 CQL 和协议,但这不是说可以做一个在线的无缝热迁移。客户端可以无缝切换,因为这层协议兼容;数据层面却还是有差异,需要专门迁移或双写。在第 4 章会看到一个 MySQL 实时数据仓库同步的操作示例,能拓展你对此的理解。

迁移路径要因数据量而异。小数据量(GB 级)直接用scylla-cqlsh导出再导入 is 高效的方式;大数据量(TB 级)则适合用双写或工具过渡。scylla-cqlsh里的COPY命令就是一个很好的起点。先把 CSV 导出来,再灌入 Scylla。

# 从 Cassandra 导出 cqlsh -e "COPY ks.cf TO '/data/backup.csv'" # 导入 Scylla scylla-cqlsh -e "COPY ks.cf FROM '/data/backup.csv' WITH CHUNKSIZE=256 AND INGESTRATE=20000"

这里INGESTRATE=20000的含义是每秒最多灌入 2 万行。不要贪高,太高会影响 compaction 的执行节奏,太快也会增加新节点压力;CHUNKSIZE控制在 256,否则大批量导入时内存会不足。

3.2 cqlsh 在 Scylla 中的差异细节

连接 cqlsh 的默认端口仍然是 9042,保持与 Cassandra 一致。但需要注意,Scylla 支持同时监听 Thrift 协议,如果你没有用到它,建议在scylla.yaml中显式关闭:

# /etc/scylla/scylla.yaml start_native_transport: true start_rpc: false # 关闭 Thrift rpc_address: 0.0.0.0 # 关键配置 memtable_allocation_type: heapmemory # 或使用自动调优的配置:让 Scylla 自己决定内存分配策略 memtable_allocation_type: OMM

start_rpc: false意味着放弃了老客户端(基于 Thrift 的旧版 Cassandra client)的兼容性,获取的是更少的暴露面和更安全的网络性能。如果你的客户端都是 CQL native protocol,这一步可以放心做。

3.3 用 schema 迁移来保障实时同步的一致性

对于一个 MySQL 实时同步到 Scylla 的场景,建议先建表再启同步,顺序不能颠倒,否则写入时序会出现问题。比如一个 user_behavior 表:

CREATE TABLE IF NOT EXISTS scylla_keyspace.user_behavior ( user_id uuid PRIMARY KEY, action_time timestamp, action_type text, page_id bigint, dwell_time_ms int ) WITH comment = '实时记录用户行为漏斗';

其中dwell_time_ms是用户停留时长,单位毫秒。如果把page_id设为主键的一部分就不合算了,会导致同一用户的不同行为没法用主键做范围查询。主键设计要仔细思考查询模式,Scylla 的分区键决定数据落在哪个 shard,查询时带上分区键才能有单次路由的效率;否则要走全分区扫描,性能会衰退到和 Cassandra 最坏情况一样,也是 Scylla 的典型反模式。

4. 从 Outbrain 案例到读写路径压测:一套性能模型是可以复现的验证

4.1 Outbrain 是在验证什么

Outbrain 的改造案例核心很简单:原架构是 Memcached + Cassandra 分两层,读请求先打 Memcached,未命中再落到 Cassandra。后来把 Scylla 部署在旁边,读写请求直接打到 Scylla,不再需要缓存层。结果是仅用 9 台机器同时承接了原来 30 台机器 + 缓存层的流量,读延迟降了一半,最大延迟从 35ms 降到 8ms。

600 万极客注意这个案例的转折点在哪里:延迟指标真正的考验在于冷缓存下的表现。Memcached 一旦被打满或者过期,流量瞬时落到 Cassandra 上,这时的 99% 延迟就会让你看到真实水平。Scylla 自己管理缓存,而且整个缓存逻辑内建在 shard 本地,不会有跨核的缓存一致性问题。

4.2 用自己环境去验证时怎么还原这套模型

在环境和流量足够的情况下去复现,压测工具建议用官方维护的scylla-bench。它比 YCSB 更适合测 Scylla 的原因是:它会按 shard 的分布来规划线程,尽可能压满每个核的能力。

# 安装后,先做基础写的压测 scylla-bench \ -mode=write \ -replication-factor=3 \ -partition-count=200 \ -clustering-row-count=10 \ -concurrency=256 \ -duration=5m \ -nodes=10.0.0.2,10.0.0.3,10.0.0.4 \ -operation-count=10000000

参数说明:

  • -mode=write:纯写入测试。要测读延迟,把模式换成readmixed
  • -replication-factor=3:符合生产环境的副本数,三副本是性价比和可用性的平衡点;
  • -partition-count=200:模拟 200 个逻辑分区的分布,压测覆盖面更广;
  • -concurrency=256:并发数从 256 起步,逐步增大来测试峰值。如果并发太大,例如 1024,会逼近共享瓶颈,结果反而不好看,要按实际业务场景选定;
  • -duration=5m:持续 5 分钟。测试持续太短无法体现稳定性和长尾分布,建议至少 5 分钟起步。

压测跑完以后,用官方提供的报告解析脚本提取 99% 延迟:

scylla-bench --report-format json | jq '.latency_percentiles.p99_ms'

观察 P99 是否始终稳定在 1 毫秒以内。如果 P99 远远高于 1ms,往下看nodetool info里 Cache 命中率,命中率不到 90% 说明缓存分配不足,考虑提高cache_size或者先预热数据:

# 预热操作:在一个分区偏移范围内做扫描读 scylla-bench \ -mode=read \ -partition-offset=0 \ -partition-count=200 \ -concurrency=64

这条命令的意义在于把 key 范围 0-200 内的数据先拉到内存缓存中,后续测试访问就有缓存命中。

4.3 在线业务热缓存负载均衡的意义

另外一个容易被忽略却很有价值的场景是故障恢复后的热缓存负载均衡。Cassandra 故障时,落到某个节点的流量会由副本节点接管。等故障节点恢复,如果新节点缓存是空的,会有一段时间的缓存击穿,压力直逼磁盘层。

Scylla 在故障恢复时会主动把副本节点的缓存内容同步到新节点,这个过程是自动的、后台的,不需要手工预热。验证手段:你可以在压测期间手动 kill 掉一个节点进程,观察恢复后的延迟曲线。正常情况下的恢复过程延迟会出现一次尖峰然后恢复平缓;如果出现持续高水位,要怀疑TCP 重传率是否过高,或者网卡中断没绑定到合适的 NUMA 节点。

5. 谈配置细节前,先看看正确理解 shard-per-core 要避免的坑

5.1 物理部署和 NUMA 绑定的协调

分配错误的后果是看起来 OPS 上不去,实际问题是跨 NUMA 访问内存。举例:一台双路服务器有 2 个 NUMA node,每个 node 有 16 核。如果你让 Scylla 使用了全部 32 核,但每个 shard 对应的内存分配到了远端 NUMA,内存访问延迟会上升 30% 左右。

配置方式:编辑/etc/scylla/scylla.yaml里的cpu_set参数,把它按物理核编号排列清楚。如下:

# 双路 32 核机器,0-15 属于 NUMA node 0,16-31 属于 node 1 cpu_set: 0-15,16-31

scylla.yaml中添加numa相关配置后,用scylla_cpuscaling set让 CPU 调频策略配合,进入高性能模式。Intel 的performance模式跑 Scylla 的吞吐和延迟都优于powersave

5.2 主键设计导致的跨 shard 访问

shard-per-core 对主键设计要求更苛刻。Scylla 的路由基于分区键(partition key)。如果查询没有带分区键,Scylla 必须把请求广播到所有 shard,然后汇总结果。这个代价在 Cassandra 里也存在,但在 Scylla 的架构模型下显得更加昂贵,多核节点的惩罚更重。

举个例子,一个orders表,如果把user_id作为分区键,order_id作为聚类键,查询某个 user 下的订单只需要一个 shard。但如果只知道order_id,就必须全节点扫描。这就是为什么不推荐用 UUID 全局唯一做主键,OpenSearch或者分布式 ID 生成方案设计时最好是带上能够作为分区键的字段。

-- 不好的设计:订单号全局唯一,没法路由 CREATE TABLE orders ( order_id uuid PRIMARY KEY, user_id int, amount int ); -- 更好的设计:分区键是高频查询维度 user_id CREATE TABLE orders ( user_id int, order_id uuid, amount int, PRIMARY KEY (user_id, order_id) );

第一张表你只能在WHERE order_id = xxx的时候全集群扫描;第二张表按用户维度查询时只会访问有对应 token 范围的 shard。数据建模上,请把业务的高频查询维度作为分区键,这也是 NoSQL 应用加速最重要的一条实践经验。

5.3 Compaction 策略的选择与实际参数效果

Scylla 在 Cassandra 的 compaction 策略之外加了更多选择。默认推荐用TimeWindowCompactionStrategy(TWCS),尤其适合时间序列数据。它的优点:避免一遍遍重写同一个 SSTable,把相同时间窗口的数据放到一起。配置时要注意,他的窗口太小则会创建大量碎片,过大则会使单次 compaction 事件资源占比过高、耗时过长,需要设置恰当的阈值。

ALTER TABLE scylla_keyspace.metrics_data WITH compaction = { 'class': 'TimeWindowCompactionStrategy', 'compaction_window_size': 6, 'compaction_window_unit': 'HOURS', 'tombstone_threshold': 0.5 }

tombstone_threshold=0.5表示墓碑占比超过一半时强制触发 compaction。如果你做短时间 TTL 数据的写入和删除,这个值出发紧凑的节奏比默认值短,能防止墓碑堆积导致的查询性能劣化。相反地,如果表里的数据几乎不会更新删除,这个阈值可以调低,让 compaction 运行得少一些。

5.4 利用 Hinted Handoff 和 Lightweight Transactions 特性

Scylla 是一个支持 CAP 系统中 AP 语义和可配置一致性级别的数据库,轻量事务(LWT,基于 Paxos)的使用会造成额外的跨副本通信开销。LWT 适用于需要强制实现唯一约束的稀有场景,日常写入尽量使用普通写。条件里检测到 LWT 延迟占到整体延迟的 20% 以上时,说明业务里过度依赖 LWT 了,需要看应用层能不能做去重。

Hinted Handoff 在故障期间默认开启,它可以保证当一个节点短时间挂掉时,写入数据被邻居临时保存,等节点恢复后再补发。如果集群中同时有多个节点掉线,Hinted Handoff 需要的时间会明显加长,这会侵占正常的 I/O 资源。默认的超时是 3 小时,在维护窗口期你可以动态把hinted_handoff_enabled先关掉,让写入保持低延迟:

curl -X PUT \ -H "Content-Type: application/json" \ -d '{"enabled": false}' \ "http://localhost:10000/system/hinted_handoff"

注意这也是临时的,维护完成后一定要记得重新打开。

6. 保留一份针对 Scylla 延迟排查的实用清单

6.1 延迟上不去时不要只盯 CPU

Scylla 的nodetool stat提供的延时统计数据里,如果 P99 明显劣于 P50,而 CPU 利用率看起来并不高,优先怀疑磁盘层面的随机读性能。Cassandra 时代你还能用 SSD 当缓存层来遮丑,Scylla 全链路自己管理缓存,底层存储性能直接体现到直播链路的 P99。Scylla 在 NVMe 上的随机读取效率有额外的优化,但在普通 SATA SSD 上的效果差距很大。

实测建议:查看节点运行fio的随机读延迟,如果 99 分位存在掉速,普通 SSD 换成企业级 SSD 也能看到明显的提升。另外注意别在虚拟机里跑 Scylla 做基准测试,跨虚机的中断处理时延抖动会把结果拉坏到无法判断问题。

6.2 与现有大数据生态混用的问题

Scylla 对外兼容多种大数据组件接口,比如直接支持 Spark 的Spark Cassandra Connector。如果你的任务是通过 Spark 读 Scylla,务必注意spark.cassandra.input.split.size这个参数。Spark 从 Cassandra 读取时代码里习惯用spark.cassandra.input.split.size控制分区粒度,默认值是 100000。Scylla 读取相同的 token 范围速度更快,应该调大这个值。找到你的 Spark 配置:

spark.conf.set("spark.cassandra.input.split.size", "200000") spark.conf.set("spark.cassandra.read.timeoutMS", "120000")

200000行作为一个 split,让 Spark 的每个分区处理更多数据,减少任务调度开销,整体读取更快。

6.3 一个实践较多的故障判断流程

给你一套可以直接落地的故障定位顺序:

先看nodetool info里的吞吐和 P99,再对照磁盘 util(iostat -x 1)、CPU steal、网络重传三个指标。如果磁盘 util 常年 > 85% 且 Queue 积压,考虑降seastar_utilization,给它留更多余量处理后台任务。如果网络重传率高,先查网卡队列是否绑定在正确的 NUMA 节点上;这部分你直接看scylla.io/sys/class/net/eth0/queues/rx-0/rps_cpus是否分配了独立核。如果问题还是定位不下来,用官方的scylla perftune检查项:

scylla perftune --mode=perftune \ --iface eth0 \ --num-cpus 32

perftune 会把网卡队列、IRQ 亲和、sysctl 参数一次性设置好。运维里最多的延迟抖动,其实出自这类基础设施配置没有对齐,Scylla 自身能做的优化都做到了,剩下的就要靠部署环境去配合。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询