clickhouse 中 ReplicasMaxAbsoluteDelay 的计算

小白上路,如有错误,还请指正,谢谢。

一、 问题背景

最近偶尔会收到延迟超时的告警,随后恢复

时间:2022.09.30-10:04:48

replication lag across all tables (ads_ch03:ch_params[ReplicasMaxAbsoluteDelay]): 52y 9m 15d

历史告警日期如下

      可以看到ReplicasMaxAbsoluteDelay的时间,随着告警发送的日期在增长,但是始终是52年左右。微信群里的朋友发现52年前刚好是1970年,即unix的起始时间附近。

       因此大致可以猜测这个值是currenttime减去unix起始时间的秒数,表示一个无穷大而不是真正的延迟。

二、 源码分析

       其实本来是想在网上直接搜资料的,但实在太少了,只能搜ClickHouse ReplicasMaxAbsoluteDelay source code看看。

1. AsynchronousMetrics.cpp文件

       可以查到设置ReplicasMaxAbsoluteDelay的入口函数在AsynchronousMetrics.cpp文件,也就是它对应的系统表名字。

// 循环检查各db
for (const auto & db : databases){// Check if database can contain MergeTree tables// 检查db中是否可以包含MergeTree引擎表,若不能则跳到下个dbif (!db.second->canContainMergeTreeTables())continue;// 循环检查db中每个表for (auto iterator = db.second->getTablesIterator(getContext()); iterator->isValid(); iterator->next()){++total_number_of_tables;…// 如果是ReplicatedMergeTree引擎表if (StorageReplicatedMergeTree * table_replicated_merge_tree = typeid_cast<StorageReplicatedMergeTree *>(table.get())){StorageReplicatedMergeTree::Status status;table_replicated_merge_tree->getStatus(&status, false);…// 如果不是只读状态if (!status.is_readonly){try{time_t absolute_delay = 0;time_t relative_delay = 0;// 这步是主要函数,给两个变量赋值,下面会详细看table_replicated_merge_tree->getReplicaDelays(&absolute_delay, &relative_delay);// calculateMax是个获取最大值的函数:比较max_absolute_delay与absolute_delay,较大者存入max_absolute_delaycalculateMax(&max_absolute_delay, absolute_delay);calculateMax(&max_relative_delay, relative_delay);}catch (...){tryLogCurrentException(__PRETTY_FUNCTION__,"Cannot get replica delay for table: " + backQuoteIfNeed(db.first) + "." + backQuoteIfNeed(iterator->name()));}}}}}…
// 循环获取到每个库每个表的max_absolute_delay后,赋给ReplicasMaxAbsoluteDelaynew_values["ReplicasMaxAbsoluteDelay"] = max_absolute_delay;

 很简单的calculateMax函数

static void calculateMax(Max & max, T x)
{if (Max(x) > max)max = x;
}

2. getReplicaDelays函数

        前面的getReplicaDelays(&absolute_delay, &relative_delay); 主要是调用该函数,并给absolute_delay和relative_delay变量赋值,这里我们只看absolute_delay。

void StorageReplicatedMergeTree::getReplicaDelays(time_t & out_absolute_delay, time_t & out_relative_delay)
{assertNotReadonly();time_t current_time = time(nullptr);out_absolute_delay = getAbsoluteDelay();out_relative_delay = 0;
…
}

         首先执行一个assertNotReadonly,判断表非只读

void StorageReplicatedMergeTree::assertNotReadonly() const
{if (is_readonly)throw Exception(ErrorCodes::TABLE_IS_READ_ONLY, "Table is in readonly mode (replica path: {})", replica_path);
}

然后是主要的,执行getAbsoluteDelay函数,获取延迟值。

3. getAbsoluteDelay函数

time_t StorageReplicatedMergeTree::getAbsoluteDelay() const
{// 队列中未处理日志的最早插入时间time_t min_unprocessed_insert_time = 0;// 队列中已处理日志的最大插入时间time_t max_processed_insert_time = 0;// 获取这两个变量值queue.getInsertTimes(&min_unprocessed_insert_time, &max_processed_insert_time);// Load start time, then finish time to avoid reporting false delay when start time is updated between loading of two variables.// 获取队列更新的开始及结束时间time_t queue_update_start_time = last_queue_update_start_time.load();time_t queue_update_finish_time = last_queue_update_finish_time.load();// 当前时间,返回的是从纪元开始(1970-01-01)至今的秒数time_t current_time = time(nullptr);if (!queue_update_finish_time){/// We have not updated queue even once yet (perhaps replica is readonly). As we have no info about the current state of replication log, return effectively infinite delay./// 看到一篇文章的解释是:如果队列最近一次的更新一直没结束,表示正在向当前队列中加操作日志,则认为延迟时间是无穷大
return current_time;}else if (min_unprocessed_insert_time){/// There are some unprocessed insert entries in queue. 
/// 如果队列中有尚未处理的日志,且其时间早于当前时间,则输出两者差值作为delay;否则,说明是后生成的,delay记为0.return (current_time > min_unprocessed_insert_time) ? (current_time - min_unprocessed_insert_time) : 0;}
/// 如果队列更新开始时间大于结束时间else if (queue_update_start_time > queue_update_finish_time){/// Queue is empty, but there are some in-flight or failed queue update attempts (likely because of problems with connecting to ZooKeeper)./// Return the time passed since last attempt./// 说明队列为空,但有一些正在运行或失败的队列更新尝试(可能是由于连接到ZooKeeper时出现问题)。// 返回自上次尝试后经过的时间。return (current_time > queue_update_start_time) ? (current_time - queue_update_start_time) : 0;}else{/// Everything is up-to-date. 否则,说明没有延迟return 0;}
}

4. queue_update_finish_time的计算

上面函数中只简单提到了

time_t queue_update_finish_time = last_queue_update_finish_time.load();

其定义在

    /** The queue of what needs to be done on this replica to catch up with everyone. It is taken from ZooKeeper (/replicas/me/queue/).* In ZK entries in chronological order. Here it is not necessary.*/ReplicatedMergeTreeQueue queue;std::atomic<time_t> last_queue_update_start_time{0};std::atomic<time_t> last_queue_update_finish_time{0};

找到一张图

在这里插入图片描述

可以看到,其计算主要在queueUpdatingTask函数

void StorageReplicatedMergeTree::queueUpdatingTask()
{if (!queue_update_in_progress){last_queue_update_start_time.store(time(nullptr));queue_update_in_progress = true;}try{queue.pullLogsToQueue(getZooKeeperAndAssertNotReadonly(), queue_updating_task->getWatchCallback(), ReplicatedMergeTreeQueue::UPDATE);last_queue_update_finish_time.store(time(nullptr));queue_update_in_progress = false;}catch (const Coordination::Exception & e){...}catch (...){...}
}

根据chatgpt的介绍:

queue.pullLogsToQueue(getZooKeeperAndAssertNotReadonly(), queue_updating_task->getWatchCallback(), ReplicatedMergeTreeQueue::UPDATE);

queue.pullLogsToQueue 函数用于从日志表中获取更新任务,并将其添加到队列中。具体来说,该函数会检查当前副本是否处于只读模式,如果是,则直接返回;否则,使用 ZooKeeper 客户端对象从日志表中获取更新任务,并将其添加到队列中。

在调用 queue.pullLogsToQueue 函数时可能出现以下异常:

  • 如果当前副本处于只读模式,会抛出 Exception 异常。
  • 如果无法获取到 ZooKeeper 客户端对象,会抛出 zkutil::KeeperException 异常。
  • 如果从日志表中获取更新任务失败,会抛出 Exception 异常。

此外,在使用客户端对象操作ZooKeeper时,还可能遇到网络连接问题或ZooKeeper服务器响应超时等问题,这些情况也有可能导致 zkutil::KeeperException 异常。

last_queue_update_finish_time.store(time(nullptr));

last_queue_update_finish_time 表示最近一次更新操作完成的时间。

time(nullptr) 函数返回当前系统时间(以秒为单位),用于更新 last_queue_update_finish_time 的值。通过调用 store 函数将新的时间戳写入到原子变量中,在这个过程中使用了锁,以保证多线程环境下的原子性和可见性。

这个时间戳可以用来计算当前更新操作的延迟,具体来说,可以通过与最近一次更新完成时间的比较,得到当前更新操作等待的时间长度,从而判断该更新操作是否需要加速执行。同时,由于该变量会被多个线程访问,因此需要使用原子变量来确保线程安全。

        因此可以猜测,当queue.pullLogsToQueue 函数抛异常时,会跳过last_queue_update_finish_time的计算,导致其值为0。具体可能包括:

  • 当前副本处于只读模式
  • 无法获取到 ZooKeeper 客户端对象
  • 从日志表中获取更新任务失败

三、 遗留问题

        至此,我们清楚了ReplicasMaxAbsoluteDelay返回52年的原因,以及可能导致queue_update_finish_time0的场景。但结合到实例监控

  • clickhousezookeeper的日志中目前没发现报错
  • Read-Only Replicas监控也一直显示为0

  • 队列中的任务数也很少

       没有发现符合上述问题的具体场景,且从实际来看业务没反馈过有什么影响,或许可以改为连续出现两次或多次才告警?

       希望熟悉clickhouse的朋友指点指点~

参考

AsynchronousMetrics.cpp source code [ClickHouse/src/Interpreters/AsynchronousMetrics.cpp] - Woboq Code Browser

ReplicatedMergeTreeQueue.h source code [ClickHouse/src/Storages/MergeTree/ReplicatedMergeTreeQueue.h] - Woboq Code Browser

StorageReplicatedMergeTree.cpp source code [ClickHouse/src/Storages/StorageReplicatedMergeTree.cpp] - Woboq Code Browser

StorageReplicatedMergeTree.h source code [ClickHouse/src/Storages/StorageReplicatedMergeTree.h] - Woboq Code Browser

https://www-programmersought-com.translate.goog/article/56754023733/?_x_tr_sl=en&_x_tr_tl=zh-CN&_x_tr_hl=zh-CN&_x_tr_pto=sc

https://www.dounaite.com/article/62c907c8f4ab41be4873aadd.html

Clickhouse ReplicatedMergeTree 后台任务的工作原理-pudn.com

【ClickHouse源码】ReplicatedMergeTree之数据同步流程_一只努力的微服务的博客-CSDN博客

chatgpt的回答

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39933.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chatgpt赋能python:如何排除Python运行失败问题:常见错误和解决方法

如何排除Python运行失败问题&#xff1a;常见错误和解决方法 作为一个有10年Python编程经验的工程师&#xff0c;我深知Python编程不断发展&#xff0c;新库和语法变得越来越流行。然而&#xff0c;即使你是一个经验丰富的Python编程人员&#xff0c;最终难免会遇到一些问题&a…

调用ChatGpt openai官方node.js包Error: connect ETIMEDOUT问题

原因是调用的axios库不走系统代理&#xff0c;需要额外配置。 openai在文档中有说明增加axios配置的方法 只需请求时配置下proxy就ok了

GitHub Copilot 体验

LHS 475 b NASA’s Webb Confirms Its First Exoplanet | NASA 介绍 什么是GitHub Copilot GitHub Copilot是由GitHub和OpenAI公司共同开发的基于云的AI编程工具&#xff0c;目前支持Visual Studio Code、Visual Studio、Neovim和JetBrains集成开发环境集成开发环境(IDE)&…

Cerebral Cortex:静息态fMRI功能连接可以预测男女关系的相容性

即使在信息技术显著发展的情况下&#xff0c;基于自我报告的特征和偏好来预测异性恋个体最初的相容性也并不成功。为了克服自我报告测量和预测相容性的局限性&#xff0c;我们使用了来自静息状态功能磁共振成像(fMRI)数据的功能连接&#xff0c;这些数据携带丰富的个体特异性信…

被讨厌的勇气:目的论

目录 1. 弗洛伊德式的决定论2. 决定我们的不是过去的经历&#xff0c;而是赋予这些经历的意义。2.1. 场景&#xff1a;闭门不出的男子2.2. 场景&#xff1a;愤怒2.3. 场景&#xff1a;梦想小说家2.4. 生活方式 3. 要勇于改变 我们的生活方式3.1. 拒绝改变3.2. 千里之行&#xf…

解析后人类时代类人机器人的优越性

如今&#xff0c;机器人在我们的日常生活和社会中已无处不在。新型机器人亦是层出不穷&#xff0c;比如可以替代人类从事迎宾、安保、保洁等工作的服务机器人以及行为举止如家人或宠物般的陪伴机器人等等。而使这些新型机器人动作自然流畅的便是配置在其主体的电机与传感器的组…

心理学与生活 - 发展与教育

文章目录 延迟满足婴儿气质情感依恋咿呀学语性别认同游戏人间学习方式行为塑造 延迟满足 延迟满足的能力对孩子的人格形成和未来能够获得的成就非常重要如果孩子们意识到学会转移注意力和思想就能够实现自我控制&#xff0c;那么他们就成功了一大步“冷”系统是认知的策略性的…

怎样摆脱焦虑型依恋?

转载&#xff1a;远叔https://www.zhihu.com/question/21126414/answer/1346533425 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 心理学上通常将人类的人格特性分为三种&#xff1a;安全型&#xff0c;焦虑型以及…

chatgpt赋能python:用Python做游戏辅助指南

用Python做游戏辅助指南 随着游戏越来越受欢迎&#xff0c;越来越多的玩家开始使用各种辅助工具来提高自己的游戏技能和竞争力。Python是一个非常强大的编程语言&#xff0c;可以用于处理和分析大量的游戏数据&#xff0c;同时也可以用于编写游戏辅助脚本和软件。在这篇文章中…

广告流量反作弊风控中的模型应用

作者&#xff1a;vivo 互联网安全团队- Duan Yunxin 商业化广告流量变现&#xff0c;媒体侧和广告主侧的作弊现象严重&#xff0c;损害各方的利益&#xff0c;基于策略和算法模型的业务风控&#xff0c;有效保证各方的利益&#xff1b;算法模型可有效识别策略无法实现的复杂作弊…

Microsoft Edge 大规模崩溃,这是又跟谷歌搜索互掐了?

昨天&#xff0c;有部分网友反馈微软的 Edge 浏览器似乎出了问题&#xff0c;在地址栏输入任何字符时浏览器都会发生崩溃&#xff0c;即使关闭重启也依然无法正常使用。但是把微软必应设置为默认浏览器后&#xff0c;就可以修复… 图源&#xff1a;Reddit 谷歌回应了&#xff…

“不要用 Edge 默认的必应,我被骗了”

整理 | 郑丽媛 出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09; 在搜索引擎中输入关键词&#xff0c;我们可以很快捷地找到所需信息——一般来说&#xff0c;的确是这样的。 然而最近&#xff0c;国外有一位网友 derekantrican 发现&#xff0c;同一个关键词&…

快捷指令快速调用

快捷指令快速调用 今天在玩手机的时候&#xff0c;随便翻到 辅助功能&#xff0c;在里面发现了一个轻点背面的功能&#xff0c;以前听过感觉很鸡肋&#xff0c;没想到点进去一看发现大有门道&#xff0c;居然还能调用快捷指令&#xff0c;那不就很方便了吗 在添加快捷指令之后…

OpenAI CEO:ChatGPT比想象的更有用 但不会取代传统搜索

雷递网 乐天 2月5日 ChatGPT激发了全世界的想象力&#xff0c;从教授到广告商、黑客和法官&#xff0c;每个人都在思考如何最好地利用其功能。但是这一切背后的人是怎么想的呢&#xff1f; 对开发人工智能聊天机器人的公司OpenAI的首席执行官Sam Altman来说&#xff0c;ChatGPT…

浏览器如何截全屏的图

1.进入F12调试模式 2.快捷键&#xff1a; window:Ctrl Shift P mac:command Shift P 3.输入指令full&#xff0c;会提示有一个选项,该选项即为截取全屏&#xff0c;如下图&#xff1a; 此外&#xff0c;还有&#xff1a;node 模式以及当前范围&#xff0c;输入指令 captu…

解决验证码乱码

问题&#xff1a;在测试环境正常,但是发到线上服务器就乱码 经过检查发现是代码中设置的字体服务器中没有对应字体 Graphics2D g2 image.createGraphics();[图 片] 在服务器加上 Algerian字体(字体从windows中复制到服务器),重启服务就好了。

亚马逊测评系统有哪些?

本人做了3年测评&#xff0c;用遍了市面上的各种系统网络环境有些经验想和大家分享一下&#xff0c;我也是踩了坑多坑&#xff0c;被割过很多次韭菜&#xff0c;今天给大家分享下&#xff0c;希望能的让大家少走一些弯路&#xff0c;避免一些坑。 现在市面上的网络环境有非常多…

浏览器主流内核分析,浏览器版本过低升级方法

我们在工作生活中几乎每天都需要用到浏览器&#xff0c;但是&#xff0c;尽管用了这么多年的浏览器&#xff0c;仍然有很多人对浏览器内核不是很了解。比如&#xff0c;常见的浏览器内核有几种吗&#xff0c;浏览器版本过低怎么办&#xff0c;我们应如何升级浏览器版本&#xf…

候鸟浏览器cookie登录教程

1.下载一个候鸟浏览器&#xff08;下载链接&#xff1a; https://www.mbbrowser.com &#xff09;&#xff0c;随便找个邮箱注册个候鸟账号&#xff0c;候鸟浏览器里面是谷歌浏览器&#xff0c;可能需要梯子&#xff08;v.p.n&#xff09;才能打开&#xff0c;建议用香港IP 2.…

不用插件!教你一键显示浏览器自动保存的密码

本文转自&#xff1a;https://pcedu.pconline.com.cn/1114/11141924.html 现在的浏览器大多都有智能填表功能&#xff0c;通俗点说&#xff0c;就是当你在一个网站填写好账号密码并登录后&#xff0c;浏览器会自动保存下来&#xff0c;然后在下次打开该网站时自动填好上次保存的…