Cassandra 的 cassandra.yaml 中有两个非常容易忽略但对性能影响很大的参数:concurrent_reads 和 concurrent_writes。它们并不是限制客户端能够建立多少连接,也不是限制整个集群某一时刻能处理多少请求,而是节点内部执行本地读任务和写任务时的最大并行度。理解这一点是调优的前提。

一、参数本质:限制的是节点内部并行度
在 Cassandra 的线程模型里,客户端发来的读请求会先经过网络层,随后进入 ReadStage 线程池;写请求则进入 MutationStage。cassandra.yaml 中的 concurrent_reads 和 concurrent_writes 正是控制这两个阶段线程池能够同时活跃执行的任务数量,以及对应本地磁盘操作队列的并发上限。默认值都是 32。
这个 32 只是一个通用起始值,并不代表每个节点只能处理 32 个请求。如果并发请求超过这个值,多余任务会进入队列等待。节点不会拒绝请求,但延迟会增加。更重要的是,这里的并发指的是本地任务,而不是客户端连接数。例如一个客户端同时发起 200 个查询,这 200 个请求到达节点后,同一时间最多只有 32 个会真正执行本地读,其余在 pending 队列中排队。
写入路径也类似。Cassandra 的写入先追加到 commitlog,再更新 memtable,但返回客户端之前还要完成行数据的分发和冲突处理,这些步骤都受 concurrent_writes 约束。写操作看起来简单,但如果集群有二级索引、物化视图或批处理,单次写入在节点内部可能触发多次本地读写,因此并发写限制同样会影响吞吐。
二、按硬件和负载确定合适的并发值
没有一个适用于所有集群的固定数值,但可以先从硬件能力推算出合理的起始范围。读并发主要受磁盘随机读能力影响,写并发更多受 CPU 核数和 commitlog 顺序写带宽影响。对于 SATA SSD 或机械盘,磁盘数量少、IOPS 有限时,concurrent_reads 设置过高会让磁盘队列堆积,超时概率增加。对于 NVMe 磁盘,磁盘本身能够承受更深队列,配合更多核数时可以把并发读调高到 64 或更高。
一个常用的起始经验是:concurrent_reads 设置为磁盘数量乘以4,同时不超过 CPU 核数乘以2;concurrent_writes 设置为 CPU 核数的 1 到 2 倍,但通常不需要超过 64。比如 8 核 16GB、单块 SATA SSD 的节点,可以先保持 16 到 32;16 核 64GB、两块 NVMe 的节点,可以尝试 concurrent_reads: 64 和 concurrent_writes: 32。这些只是起点,最终必须靠监控数据修正。
还需要结合读写比例。读多写少的在线查询场景,可以适当调高 concurrent_reads,写并发保持默认;写多读少或日志类场景,可以增加 concurrent_writes,但要观察 commitlog 和 memtable flush 的压力。若存在大量分区扫读或范围查询,单个读操作消耗更多磁盘资源,并发值反而要保守一些。
下面是一段 cassandra.yaml 中的配置示例:
# 16核、64GB、两块NVMe节点的起始配置 concurrent_reads: 64 concurrent_writes: 32 concurrent_counter_writes: 32
其中 concurrent_counter_writes 用于计数器表的写入,计数器的读改写合并操作更重,通常不超过 concurrent_writes。
三、用监控数据验证调整是否有效
修改参数后,必须查看节点内部的排队情况。执行 nodetool tpstats 可以输出每个线程池的 Active、Pending、Completed 和 Blocked 统计。重点观察 ReadStage 和 MutationStage。如果 Active 长期接近配置的最大值,而 Pending 持续大于 0,说明并发数不足,请求正在排队;如果 Active 不高,但磁盘利用率已经接近 100%,说明瓶颈在磁盘而不是线程池,继续调大并发没有帮助甚至有害。
以下是一个可能的输出片段:
nodetool tpstats Pool Name Active Pending Completed Blocked ReadStage 32 48 1023421 0 MutationStage 18 3 823331 0
这个例子中 ReadStage 的 Active 已经达到上限 32,但 Pending 还有 48 个任务,说明读并发可能偏低;MutationStage 的 Pending 很少,写并发配置基本合适。如果磁盘指标显示单盘 util 在 90% 以上,则应先考虑增加磁盘或优化数据模型,而不是盲目调大 concurrent_reads。
还需要结合操作系统监控,例如 iostat -x 1 查看磁盘 await 和 util,vmstat 1 查看 CPU run queue 和上下文切换。如果并发数过高,CPU 的 sys 使用率会上升,磁盘平均等待时间增加,此时反而要降低并发值。常见误区是只看到吞吐不够就翻倍参数,结果 p99 延迟更差。
四、常见误区与配置建议
第一个误区是把客户端并发数等同于节点内部并发数。应用层连接池可能配置 100 或 200 个并发请求,但 Cassandra 节点内部仍然按照 concurrent_reads 和 concurrent_writes 排队执行。与其无限制增大这两个值,不如在客户端控制并发、使用令牌感知策略,避免请求被转发到不持有数据的协调节点。
第二个误区是忽略数据模型和查询模式。并发读设置得再高,如果一张表存在超大分区、频繁范围扫描或未使用合适的主键,单次读会拉取大量数据,磁盘和堆内存先成为瓶颈。此时应先优化查询,再调整参数。
第三个误区是调整后不做灰度验证。生产环境不要一次性全集群修改。可以先在单个节点上改,重启后观察一段时间,对比 p99 延迟、超时率和 tpstats 中的 pending 变化。Cassandra 集群可以滚动重启,逐台生效。建议每次只改动一个参数,便于定位影响。
综合来看,在硬件和负载稳定的前提下,可以从 concurrent_reads: 32 和 concurrent_writes: 32 开始,根据监控逐步加减 16 或 32。如果节点规模较小或共享云盘,设置 16 往往更稳定;如果节点核数多且 NVMe 磁盘充足,64 到 128 也是合理范围。真正合适的值是在目标延迟和吞吐之间找到平衡点,而不是追求最大并发。
Cassandra并发数concurrent_readsconcurrent_writes修改时间:2026-08-24 18:20:03