You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
现场疑问:切主时主库会先设 readonly、等从库位点追上才切吗?→ 不会,主动切主是直接选一个从节点 slaveof no one 提升为主。
代码核对(已逐条坐实):
① 选主只在从节点里挑、按 binlog 位点选最新,且明确跳过老主:Group.SelectNewMaster()(codis/pkg/models/group.go:29-58)循环里 index == 0(老主)直接 continue 跳过(group.go:34),其余从节点先比 DbBinlogFileNum、再比 DbBinlogOffset,选位点最大的从节点(group.go:41-50)。→ 现场判断属实:只在从节点间比位点选最新,从不与老主位点比对。
② 自动切主路径连「新主是否追上」都没校验:trySwitchGroupMaster(codis/pkg/topom/topom_group.go:461-476)选完新主后,本该校验可用性的 isAvailableAsNewMaster(检查 master_link_status == down,即全量同步未完成)那段被 // TODO liuchengyu check new master is available 整段注释掉了(topom_group.go:469-473)。isAvailableAsNewMaster 函数虽然实现了(topom_group.go:478-499),但未被调用。
③ 主动切主(GroupPromoteServer)全程无位点比对、无 readonly、无等待追平:GroupPromoteServer(topom_group.go:201 起)入参直接是人工/调用方指定的 addr,流程 ActionPrepared 阶段(topom_group.go:269-306)直接把 g.Servers[index] 当新主,调 promoteServerToNewMaster(slice[0].Addr, ...)(topom_group.go:305)执行 slaveof no one(codis/pkg/utils/redis/client.go:331),没有任何"先 readonly→等从库位点追平→再切"的环节。
若从库请求的 binlog 文件已被 purge → 返回 kSyncPointBePurged、日志 "binlog has been purged, may need full sync"(pika_repl_server_conn.cc:198-203)→ 触发全量同步。这正对应「binlog-file-size 太小 → 文件滚动快被清 → 全量」的现场怀疑。
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Pika PMC 会议纪要
一、议题概览
二、议题详细讨论
议题 1:Codis-Proxy 日志清理与滚动策略增强
codis/pkg/utils/log/rolling.go,切割依据是time.Now().Format(...)的时间后缀(支持Monthly / Daily / Hourly等按时间维度滚动,见rolling.go:35-53)。O_CREATE|O_WRONLY|O_APPEND打开当前时间片对应文件(rolling.go:60),未发现任何max_age / max_backups / rotate_size之类的清理或按大小切割逻辑。rolling.go中新增日志保留策略:log-keep-days):超过 N 天的历史日志文件自动删除。log-keep-files):仅保留最近 N 个滚动文件。议题 2:高低配混部下主从同步追不上的优化方案
compaction-strategy实际取值:代码中该配置仅支持full-compact/obd-compact,否则回落none(src/pika_conf.cc:339-345,891-897)。当前仓库中并不存在progressive-compact这个取值,对progressive关键字检索无任何命中。compaction-strategy = progressive-compact(取值不支持)progressive-compact-intervalprogressive-compact-max-filesprogressive-compact-max-time-msconf/pika.conf/pika_conf.cc/pika_conf.h核对):disable-auto-compactionslevel0-file-num-compaction-trigger/level0-slowdown-writes-trigger/level0-stop-writes-triggermax-background-flushes/max-background-compactions/max-background-jobs/max-subcompactionssync-binlog-thread-num/sync-thread-num/sync-window-sizemax-cache-statistic-keys/small-compaction-thresholdcompressionsrc/storage/src/{strings,base,lists,zsets}_filter.h),从实现形态看是 DB 侧统一 compaction 过程触发,未见「仅主库启用、从库禁用」的角色判断。从节点同样会跑 compaction filter,因此「优化从节点 compaction filter 以减轻从库负载」方向值得探索(如降低从库 filter 的清理频率/开销)。progressive-compact取值当前不存在,需先确认该特性是否在目标分支落地(关联议题:渐进式 Compaction PR)。progressive-compact特性在哪个分支/PR,是否可供从库使用。议题 3:unstable 主从同步(rsync 全量同步)写文件路径疑似存在 bug
RsyncWriter用O_APPEND+write()写文件,忽略传入的 offsetinclude/rsync_client.h:113-136、调用点src/rsync_client.cc:242。open(filepath.c_str(), O_RDWR | O_APPEND | O_CREAT, 0644)(rsync_client.h:115)—— 用了O_APPEND。Write(uint64_t offset, size_t n, const char* data)内部用write(fd_, ptr, left)而非pwrite()(rsync_client.h:123),循环里offset += done(rsync_client.h:133)只是个局部变量自增,对O_APPEND无效——O_APPEND语义下每次write都强制写到文件当前末尾,传入的offset被完全忽略。writer->Write((uint64_t)offset, ret_count, resp->file_resp().data().c_str())(rsync_client.cc:242)把 offset 传进去了,但被上述实现忽略。RsyncWriter以O_APPEND打开,新数据会追加到旧文件末尾,而不是从 offset 0 覆盖。include/rsync_server.h:105-118、src/rsync_server.cc:201-219、src/rsync_client.cc:242。RsyncReader::Read(...)的checksum出参全程未被赋值(初值为空串"",rsync_server.h:105-118内只memcpy数据、设置bytes_read/is_eof,从不计算 checksum)。file_resp->set_checksum(checksum)(rsync_server.cc:216)——实际塞进去的是空串。rsync_client.cc:242收到响应后完全没有校验resp->file_resp().checksum(),直接writer->Write(...)。O_APPEND,Write改用pwrite(fd_, ptr, left, offset)按真实 offset 定位写入。RsyncReader::Read计算 checksum,client 写前比对,不一致则重传该 chunk。议题 4:Codis 切主不比对老主位点,写入高时切主丢数据 + 老主被迫全量重做
binlog-file-size调得偏小 → binlog 滚动快、老文件被 purge → 老主想增量 slaveof 新主时位点对不上 → 触发全量同步;老主只能整库重做(dump + rsync)。slaveof no one提升为主。Group.SelectNewMaster()(codis/pkg/models/group.go:29-58)循环里index == 0(老主)直接continue跳过(group.go:34),其余从节点先比DbBinlogFileNum、再比DbBinlogOffset,选位点最大的从节点(group.go:41-50)。→ 现场判断属实:只在从节点间比位点选最新,从不与老主位点比对。trySwitchGroupMaster(codis/pkg/topom/topom_group.go:461-476)选完新主后,本该校验可用性的isAvailableAsNewMaster(检查master_link_status == down,即全量同步未完成)那段被// TODO liuchengyu check new master is available整段注释掉了(topom_group.go:469-473)。isAvailableAsNewMaster函数虽然实现了(topom_group.go:478-499),但未被调用。GroupPromoteServer(topom_group.go:201起)入参直接是人工/调用方指定的addr,流程ActionPrepared阶段(topom_group.go:269-306)直接把g.Servers[index]当新主,调promoteServerToNewMaster(slice[0].Addr, ...)(topom_group.go:305)执行slaveof no one(codis/pkg/utils/redis/client.go:331),没有任何"先 readonly→等从库位点追平→再切"的环节。slave-read-only配置项(src/pika_conf.cc:119、include/pika_conf.h:404-406),但全仓src/*.cc中没有任何写命令路径用它来拦截写(grep 零命中)。→ 印证现场说法:Pika 实际没有 readonly 写开关,要让老主停写只能slaveof一个不存在的实例。PikaReplServerConn::TrySyncOffsetCheck(src/pika_repl_server_conn.cc:172-217):kSyncPointLarger(pika_repl_server_conn.cc:189-196),增量 TrySync 失败 → 老主无法增量挂到新主下。kSyncPointBePurged、日志"binlog has been purged, may need full sync"(pika_repl_server_conn.cc:198-203)→ 触发全量同步。这正对应「binlog-file-size太小 → 文件滚动快被清 → 全量」的现场怀疑。SelectNewMaster已经在用DbBinlogFileNum/DbBinlogOffset,可复用)。slaveof不存在实例(或新增真正生效的 readonly 开关)冻结写入,再等新主位点追平到阈值内、最后slaveof no one,把丢数据窗口压到最小。isAvailableAsNewMaster校验,至少保证新主master_link_status != down(全量已完成)才允许被选为新主。force,避免「静默丢数据」。isAvailableAsNewMaster(去掉topom_group.go:469-473的 TODO 注释),切主前校验候选新主同步状态。binlog-file-size与 binlog 保留策略的推荐配置,降低切主即全量的概率。三、下一步计划
O_APPEND→pwrite修复 + chunk checksum 校验补齐四、下次会议安排
progressive-compact特性落地情况确认All reactions