节点地址库里的每条地址都带一个时间戳,它决定这条地址算不算新鲜、会不会在下次选邻居时被优先考虑。这个时间戳不是记下来就不再变的:源码 addrman.cpp 里有一整套重写规则,谁的话能被采信、采信的折扣多大,都写得明明白白。理解这套规则,才能理解为什么节点有时候”抱着旧名单不放”,有时候又把新鲜地址打入冷宫。
更新门槛:在线一小时,离线一天
地址已在库中时,新消息能不能刷新它的时间戳,取决于该地址当前的在线判定:距上次记录不到二十四小时算在线,更新门槛是一小时;超过二十四小时算离线,门槛放宽到一天。这个不对称的含义是:活跃地址的”新鲜度”需要更快的节奏维持,一小时内的重复消息不会推进时间戳,防止对端用高频自报把地址伪造成永远新鲜;而久未露面的地址反而容易被一条新消息救活。
来源还带时间折扣:邻居转告的地址统一扣两小时才入库,只有地址持有者自报(来源就是地址本身)免扣。传播链越长折扣越难造假,这条规则与处理流水线里的两小时罚时是同一思想的落库端。

被连接成功刷新
另一条独立通道来自实测:节点主动连接某地址成功后,只要距上次时间戳超过二十分钟就直接推进到当前时间,不受一小时门槛约束。也就是说”我亲自连上过”比”别人转告”的证据等级高。
四条”判死刑”规则
地址会不会被彻底清除,看 IsTerrible 判定:距最近一次尝试不到一分钟的暂不处理;时间戳超前本地时钟十分钟的(源码注释戏称”坐时光机来的”)直接判死;超过三十天没有任何记录的判死;从未连接成功且已尝试三次以上的判死;以及一整个星期没成功、累计失败十次以上的判死。后两条把”长期拨不通”的节点清出去,给新地址腾位置。
分桶结构顺带一提
地址库分”已尝试”与”新发现”两区:拨通过的进已尝试桶,容量较小、淘汰苛刻;刚收进来的进新发现桶,容量大得多、按组轮换清理。上面那套时间重写规则主要作用于新发现区,决定一条地址是很快被提拔成候选、还是悄悄沉底。重启后节点优先从已尝试区挑熟人连接,这也是”地址库决定你重启后连上谁”的底层原因。两个 RPC 能各看一面:getaddrmaninfo 报告两区在各类网络下的数量分布,getnodeaddresses 抽样展示当前候选,对照着看就能判断时间戳规则是在正常换血还是被时钟问题卡死。
时钟偏差的连锁反应
这套规则全部以本地时钟为参照,所以本机时间漂移会连锁出错:机器时钟快了,正常地址会被看成”时光机来的”当场判死;时钟慢了三小时,一切自报地址都显得”超前”而被钳制成五天前,邻居名单老化,新连接质量下滑。发现 getaddrmaninfo 里新地址进得少、getpeerinfo 显示连接常年不换血,先跑一次时间同步再看地址库,比调网络参数见效更快。
一条实操顺序
把上面拼起来,排查地址库老化按四步走:第一步校准系统时钟并开启自动同步;第二步用 getaddrmaninfo 看新发现区数量是否在增长,只出不进说明入库端有问题;第三步看已尝试区的失败统计,判断是不是网络可达性问题把熟人都拖成了”失败十次”;最后才考虑删 peers.dat 重建——这会丢掉全部换血记录,属于核选项。每一步都有对应观测点,不需要凭感觉调参。
以上阈值均对照 v31.0 源码常量(二十四小时在线窗口、一小时与一天门槛、三十天地平线、重试与失败阈值);历史版本部分取值有过调整,跨版本核对请以对应 tag 源码为准。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。