ClickHouse v25.6.7.23-stable 补丁版本详解:Keeper 请求日志开关、日志缓存限条与四类缺陷修复
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
本文基于 ClickHouse 官方发布记录 v25.6.7.23-stable,逐项解读该补丁版本(commit4efdb9097eb,对照基线 v25.6.6.29-stable,commit63e6c7573e5)引入的 3 项改进与 4 个用户可见缺陷修复,并结合当前仓库src/Coordination等模块的源码,说明新增 4LW 命令lgrq的底层实现、Keeper 日志缓存阈值参数的默认值与语义、watch 计数统计的计量位置等细节,帮助维护 ClickHouse Keeper 集群和升级 25.6 分支的读者快速评估升级收益。
版本概览
v25.6.7.23-stable 是一个面向 25.6 维护分支的稳定补丁版本,全部条目均为从主线回合(backport)而来,分为三类:
- Improvement(改进):3 项,全部集中在 Keeper(协调服务):新增 4LW 命令
lgrq、降低存储锁争用、限制日志条目缓存规模; - Bug Fix(用户可见缺陷修复):4 项,覆盖访问存储日志使用、lazy 列与外部排序组合、Keeper watch 总数统计、后台线程池内存计量漂移;
- NOT FOR CHANGELOG / INSIGNIFICANT:3 项不列入用户可见变更的内部改动,涉及
FilterTransform常量false处理、MergeTreeBackgroundExecutor全局锁持有时间、SharedLockGuard显式加锁能力。
改进一:Keeper 新增 4LW 命令lgrq开关请求日志
该版本为 Keeper 增加了第 4LW(four-letter-word)命令lgrq,用于在运行时切换“对收到的请求进行日志记录”的行为,无需重启进程即可在排查高 QPS 场景的日志压力与定位客户端问题时动态开关。
从源码结构看,lgrq的实现位于 src/Coordination/FourLetterCommand.h:
struct ToggleRequestLogging : public IFourLetterCommand { explicit ToggleRequestLogging(KeeperDispatcher & keeper_dispatcher_) : IFourLetterCommand(keeper_dispatcher_) { } String name() override { return "lgrq"; } String run() override; ~ToggleRequestLogging() override = default; };其执行逻辑在 src/Coordination/FourLetterCommand.cpp 中,是一个典型的“读旧值—翻转—返回新状态”的切换器:
String ToggleRequestLogging::run() { const auto & keeper_context = keeper_dispatcher.getKeeperContext(); auto old_value = keeper_context->shouldLogRequests(); keeper_context->setLogRequests(!old_value); return old_value ? "disabled" : "enabled"; }也就是说,每次执行lgrq都会把请求日志状态取反,并返回切换后的状态字符串(enabled/disabled),调用方据此确认生效结果。该命令在工厂中随其他 4LW 命令一并注册(见 src/Coordination/FourLetterCommand.cpp),并且已被加入 Keeper 侧合法的 4LW 名称白名单(见 src/Coordination/CoordinationSettings.cpp 中...pfev,lgrq的字符串列表)。
使用方式与其他 4LW 命令一致:向 Keeper 端口发送裸的lgrq四字命令(例如通过clickhouse-keeper-client的交互模式或原始 socket 客户端),即可即时生效。配合同一列表中的stat、wchs等诊断命令,运维人员可以在线上快速完成“开日志—抓样本—关日志”的操作闭环。
改进二:降低 Keeper 存储锁争用
本版本回合了对 Keeper 存储层锁竞争的优化(PR #84732)。Keeper 的节点/watch 存储集中在KeeperNodesStorage/KeeperStorage(见 src/Coordination/KeeperNodesStorage.h),读多写少的会话型负载下,存储锁是热点路径。该改动通过缩小临界区降低锁争用,从而在高并发会话操作(创建/删除节点、设置 watch)场景下提升吞吐。此项为内部性能改进,无新增配置项,升级后直接生效。
改进三:按条目数限制 Keeper 日志缓存
本版本引入(并回合)了两个keeper_server.coordination_settings参数,用于按“条目数量”约束 Keeper changelog 的内存缓存:
| 参数 | 默认值 | 说明 |
|---|---|---|
latest_logs_cache_entry_count_threshold | 200000 | 最新日志条目内存缓存的最大条目数 |
commit_logs_cache_entry_count_threshold | 100000(已废弃) | 提交日志缓存的最大条目数;当前标记为 OBSOLETE,不再起作用,请使用log_readahead_commit_window_bytes替代 |
参数声明位于 src/Coordination/CoordinationSettings.cpp:
DECLARE(UInt64, latest_logs_cache_size_threshold, 1_GiB, "Maximum memory held by the in-memory cache of latest log entries, counting the per-entry allocation overhead and not just the entries themselves.", 0) \ DECLARE(UInt64, latest_logs_cache_entry_count_threshold, 200'000, "Maximum number of entries in in-memory cache of latest log entries.", 0) \ DECLARE(UInt64, commit_logs_cache_size_threshold, 500_MiB, "Deprecated. Used as the value of log_readahead_commit_window_bytes if that setting is not itself set.", SettingsTierType::OBSOLETE) \ DECLARE(UInt64, commit_logs_cache_entry_count_threshold, 100'000, "Deprecated, has no effect. Use log_readahead_commit_window_bytes instead.", SettingsTierType::OBSOLETE) \结合 src/Coordination/Changelog.h 中LogEntryStorage的设计注释可以理解其语义:
- Keeper 的日志读取依赖“最新日志缓存”(latest logs cache),其中保存尚未落盘的日志尾部加上已落盘的日志后缀;
- 该缓存同时受字节数阈值(
latest_logs_cache_size_threshold,默认 1 GiB,按驻留内存计费而非仅计载荷字节)与条目数阈值(latest_logs_cache_entry_count_threshold,默认 20 万条)双重约束; - 由于 Raft 复制与提交对日志是顺序访问,源码注释明确指出 LRU/SLRU 类缓存帮助有限,因此采用“近期日志 + 顺序读前”的结构。
实际配置示例(keeper_server节点下):
<keeper_server> <coordination_settings> <latest_logs_cache_entry_count_threshold>500000</latest_logs_cache_entry_count_threshold> <latest_logs_cache_size_threshold>1073741824</latest_logs_cache_size_threshold> </coordination_settings> </keeper_server>需要特别注意的证据边界:在当前仓库源码中,commit_logs_cache_entry_count_threshold已被标记为OBSOLETE("Deprecated, has no effect"),提交侧缓存改由log_readahead_commit_window_bytes(字节窗口)控制。因此对于本版本引入的“按条目数限缓存”能力,实际生效的是latest_logs_cache_entry_count_threshold;配置commit_logs_cache_entry_count_threshold不会产生效果。这一点以当前源码声明为准。
缺陷修复一览
1. 修复IAccessStorage中的日志器使用
PR #84365 修复了访问控制存储层(src/Access下的IAccessStorage及其派生实现)中 logger 的使用问题,避免日志输出异常或元数据缺失。这是可观察性相关的修复,不改变权限语义。
2. 修复 lazy 列配合外部排序时误报CORRUPTED_DATA
PR #84738 修复了一个数据路径缺陷:当查询使用惰性(lazy)物化的列并触发外部排序(内存不足时将中间结果落盘)时,会错误地抛出CORRUPTED_DATA。该类排序路径的实现位于 src/Processors/Transforms/MergeSortingTransform.cpp,本修复使两者组合下不再误报数据损坏。如果你此前将CORRUPTED_DATA与外部排序组合归因为存储损坏并做了数据修复,可以先升级验证,很多案例升级即可消除。
3. 修复 Keeper 返回的 watch 总数统计错误
PR #84890 修复了 Keeper 统计接口返回的 watch 总数(total watches count)不准确的问题。从源码结构看,该计数维护在 src/Coordination/KeeperStorage.cpp 的getTotalWatchesCount()中:watch 在设置与擦除时分别增减total_watches_count(见同文件 L994、L1073、L1083 附近),该值同时供 4LW 命令stat/wchs输出与KeeperWatchCount异步指标使用(见 src/Coordination/KeeperAsynchronousMetrics.cpp)。修复前某些增减路径不对称,会导致计数漂移,进而影响依赖该指标的监控告警。
4. 修复后台调度池与执行器导致的内存计量漂移
PR #84946 修复了由后台 schedule 线程池和查询执行器引入的内存跟踪(memory tracking)漂移问题。ClickHouse 对线程级内存计量一致性要求很高(system.processes、system.metrics的 MemoryTracking 等指标都依赖它),漂移会导致指标值与实际 RSS 长期不一致,进而干扰max_memory_usage类限制与 OOM 排查,升级后相关指标的可信度得到恢复。
不列入变更说明的内部改动
发布记录中还有 3 条标注为 “NOT FOR CHANGELOG / INSIGNIFICANT” 的内部改动,虽面向内部行为,但对理解引擎稳定性有帮助:
FilterTransform常量false处理(PR #83855):此前FilterTransform在某个 chunk 的过滤表达式求值为常量false时可能提前停止读取;由于执行过程中允许出现常量列、且多数函数默认实现会保留常量,这会造成读取不完整的问题,本次修复消除了该隐患(见 src/Processors 下的 FilterTransform 实现)。- 缩短
MergeTreeBackgroundExecutor全局锁持有时间(PR #84311):此前删除临时 part(尤其在 S3 等慢磁盘上)耗时较长,且发生在持有全局锁期间;当因连接丢失需要重启所有表并等待后台任务结束时,表可能长时间停留在只读模式(最坏可达一小时量级)。改动后发现调用cancel并不需要该锁,从而降低了锁持有时间。 SharedLockGuard支持显式 lock/unlock(PR #84687):为共享锁守卫增加了显式加锁/解锁能力,用于上述后台执行器改造等需要精细控制锁时机的场景。
升级建议与验证要点
- 适用前提:本版本仅面向 ClickHouse 25.6 维护分支。若你运行的是更新的维护分支(25.7+),上述修复很可能已包含,请以各分支的 docs/changelogs 记录为准;若运行 25.6.x 且使用 Keeper,建议直接升级到 v25.6.7.23-stable。
- Keeper 侧验证:升级后可用 4LW 命令
lgrq验证新命令已注册(返回enabled/disabled);通过KeeperWatchCount指标或stat命令观察 watch 计数是否与实际会话规模一致,确认第 3 项修复生效。 - 参数核对:如需限制 Keeper 日志缓存内存,按上文配置
latest_logs_cache_entry_count_threshold与latest_logs_cache_size_threshold;不要依赖已标记 OBSOLETE 的commit_logs_cache_entry_count_threshold。 - 回归关注点:若此前遇到过 lazy 列 + 大结果集排序报
CORRUPTED_DATA的查询,升级后可重放原查询验证是否消除误报。
【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考