低资源服务器上Go+Cassandra存10MB文件OOM崩溃问题排查
问题解答
Cassandra是否支持存储10MB文件?
Cassandra完全能存储10MB的文件。它单个列(cell)最大支持2GB数据,10MB远低于这个上限,直接用BLOB类型存储二进制数据即可。不过要注意:
- 大文件读写时会占用更多内存,高并发场景下容易放大内存压力;
- 如果后续有大量这类文件存储需求,更推荐用对象存储存文件,Cassandra只存文件名、路径这类元数据,但当前10MB的场景Cassandra完全能处理。
大请求下Cassandra OOM被kill的修复方案
你的服务器是1核1GB内存,仅调整MAX_HEAP_SIZE=512M不够,得从Cassandra配置、Go后端逻辑、系统层面多维度优化:
1. 精细调整Cassandra JVM参数
1GB内存的机器,Cassandra堆内存不能占太满,要给系统和其他进程留足空间,建议在cassandra-env.sh中设置:
MAX_HEAP_SIZE="400M" NEW_SIZE="100M"
另外,Cassandra依赖Netty处理IO会用到堆外内存,默认无上限,需在jvm.options中添加限制:
-XX:MaxDirectMemorySize=128M
2. 关闭OOM堆转储功能
默认Cassandra在OOM时会生成堆转储文件,这个过程会瞬间占用大量内存直接触发kill,在cassandra-env.sh里注释掉以下两行:
# JVM_OPTS="$JVM_OPTS -XX:+HeapDumpOnOutOfMemoryError" # JVM_OPTS="$JVM_OPTS -XX:HeapDumpPath=$CASSANDRA_HOME/logs/heapdump"
3. 优化Go后端的写入逻辑
- 限制并发请求数:别同时处理过多上传请求,比如限制最多5个并发,避免大量文件数据同时积压在内存;
- 流式写入Cassandra:接收WebSocket的ArrayBuffer后直接写入,不要把多个文件的二进制数据都缓存到内存中;
- 使用预编译语句:Go客户端采用Prepared Statements,减少Cassandra的SQL解析开销,降低内存占用;
- 缩小连接池规模:把Go到Cassandra的连接池最大数设为10左右,避免过多连接占用Cassandra内存资源。
4. 系统层面补充优化
- 启用Swap分区:给机器创建512MB的Swap分区,内存不足时可临时缓解压力:
sudo fallocate -l 512M /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile
- 调整OOM优先级:让系统优先终止Go进程而非Cassandra,把Cassandra的OOM分数调至最低:
echo -1000 | sudo tee /proc/$(pgrep cassandra)/oom_score_adj
5. 检查Cassandra表结构配置
- 查看表的
gc_grace_seconds是否设置过大,过大的话会产生大量墓碑数据占用内存,建议调整为86400秒(1天); - 避免使用
LOGGED BATCH写入数据,这类批量操作会先写日志到内存,改用UNLOGGED BATCH或单条写入。
内容的提问来源于stack exchange,提问作者Zlat
相关产品推荐
相关产品推荐

