把比特币核心升级到 v31 之后,一部分服务器主人为难了:内存没被别的程序占用,节点的常驻内存却比以前高了一大截,小机器上还触发了系统级的换页与内存回收。这不是内存泄漏,而是这一版改了 -dbcache 的默认取值方式。
默认值从固定值变成”看机器下菜碟”
在 v31 之前,全节点状态数据库缓存的默认值是固定的 450 MB。v31 把它换成了条件逻辑:如果程序检测到这台机器的总内存不少于 4096 MB,默认值升到 1024 MB;检测不到总内存、或者总内存低于这条线,仍沿用 450 MB。也就是说,同一份二进制在一台 2 GB 内存的小机器上和一台 8 GB 内存的机器上,默认缓存是不一样的。
改动的动机不难理解。状态数据库是节点最频繁读写的部分,缓存给得大方,同步期间查询与校验的磁盘往返就少,追块速度明显更快。官方给这台机器内存充足的部署白捡一段性能,而内存紧张的部署不受影响。发布说明同时给出了保持旧行为的方法:显式写 -dbcache=450。
为什么它比看起来更吃内存
有两层。第一层是直接效应:缓存本身从 450 MB 变成 1024 MB,多出来的约 574 MB 是实打实要被占用的。第二层更隐蔽,参数帮助文本里那句容易被略过的说明指出了方向:内存池未使用的部分会与这个缓存共享。换句话说,缓存与内存池在争同一块预算,你把缓存调大,等于把可分配给交易缓存的空间挤压掉一部分;反过来内存池的默认上限(三百多 MB)也会与缓存相互牵制。在小内存机器上同时想要”大缓存 + 大内存池”,最后的结果通常是操作系统介入回收。
怎么决定自己该填多少
不需要精确计算,一个可操作的原则是:给缓存留出的量,不能超过机器空闲物理内存的一半,且必须给操作系统、文件系统缓存和节点自身其余部分留够余量。常见的分档做法是:内存不足 4 GB 的机器显式写回 450 甚至更低;8 GB 且机器只跑节点,可以让默认值工作;更大内存的专用同步机器,可以给到 1024 以上换取首次同步速度,同步完成后再调回去。
需要提醒的是,把缓存设得比状态数据库总量还大并不会更快,多出来的部分只是空占内存。反方向倒有真实收益:内存紧张时把缓存压低、同时保留默认的内存池上限,通常比反过来更稳,因为节点的正确性不依赖缓存大小,只依赖速度。
还有一个容易被忽略的对照实验:怀疑内存占用异常时,先用系统工具确认到底是谁在吃内存,再改参数。比特币节点的正常常驻内存由几块拼起来——状态数据库缓存、交易池、脚本与签名缓存、索引缓存,再加上进程自身与操作系统的页缓存。只看总数字,很容易把”缓存按新默认值生效”误判成”内存泄漏”。正确的观察法是连续几天记录同一时段的常驻内存曲线:缓存是启动时就按配置占住、之后大致平稳的;泄漏则表现为持续单调上涨。两者的处置方式完全不同,前者改参数即可,后者应该带着数据去官方仓库提问。
改完怎么验证生效
缓存改动需要重启进程。启动时把日志的数据库相关分类打开,会看到一行报告当前配置的缓存大小与检测到的机器内存;如果这行的数字与你写进配置的数值不一致,说明参数没有真正被读到——先检查是否被命令行覆盖、是否写在了错误的小节里,再怀疑代码。
风险提示:本文说明客户端参数与默认值,不构成投资或运维建议;默认值随版本可能继续变化,调整内存相关参数前请在副本数据目录验证,并留意操作系统层面的内存告警。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。