ClickHouse 为高级用户提供问答

XNUMX 月份,Avito 工程师聚集在一起,与 ClickHouse 主要开发人员 Alexey Milovidov 和 Integros 的 Golang 开发人员 Kirill Shvakov 进行在线会议。 我们讨论了如何使用数据库管理系统以及遇到的困难。

根据这次会议,我们整理了一篇文章,其中包含专家对我们和观众关于备份、数据重新分片、外部词典、Golang 驱动程序和更新 ClickHouse 版本的问题的解答。 对于已经积极使用 Yandex DBMS 并对其现在和未来感兴趣的开发人员来说,它可能很有用。 默认情况下,答案由 Alexey Milovidov 提供,除非另有说明。

小心,切口下面有很多文字。 我们希望带有问题的内容能够帮助您导航。

ClickHouse 为高级用户提供问答

内容

如果不想看文字,可以看聚会录音 在我们的 YouTube 频道上。 时间码位于视频下的第一条评论中。

ClickHouse 会不断更新,但我们的数据却不会。 该怎么办?

ClickHouse不断更新,我们经过优化最终处理的数据并没有更新,而是在备份副本中。

假设我们遇到了一些问题并且数据丢失了。 我们决定恢复,结果发现备份服务器上存储的旧分区与当前使用的 ClickHouse 版本有很大不同。 遇到这种情况该怎么办,有可能吗?

从旧格式的备份中恢复数据但无法连接到新版本的情况是不可能的。 我们确保 ClickHouse 中的数据格式始终保持向后兼容。 如果某些很少使用的功能的行为发生了变化,这比功能的向后兼容性重要得多。 新版本的 ClickHouse 应该始终能够读取存储在磁盘上的数据。 这是法律。

当前从 ClickHouse 备份数据的最佳实践是什么?

考虑到我们已经优化了最终操作、一个巨大的 TB 数据库以及最近三天更新的数据,然后没有任何程序发生,如何进行备份?

我们可以制定自己的解决方案并在bash上写下:以这样那样的方式收集这些备份副本。 也许根本不需要拄着拐杖,而且自行车很早就发明了?

让我们从最佳实践开始。 在回答有关备份的问题时,我的同事总是建议提醒他们注意 Yandex.Cloud 服务,该服务已经解决了这个问题。 因此,如果可能的话,请使用它。

没有完整的备份解决方案,百分百内置于 ClickHouse 中。 有一些空白可以使用。 要获得完整的解决方案,您要么必须手动进行一些修改,要么以脚本的形式创建包装器。

我将从最简单的解决方案开始,以最复杂的解决方案结束,具体取决于数据量和集群的大小。 集群越大,解决方案变得越复杂。

如果数据表只有几G,可以这样备份:

  1. 保存表定义,即元数据 - 显示创建表.
  2. 使用 ClickHouse 客户端进行转储 - 选择 * 从表 归档。 默认情况下,您将收到 TabSeparated 格式的文件。 如果你想提高效率,可以采用 Native 格式。

如果数据量较大,则备份将花费更多时间和大量空间。 这称为逻辑备份;它与 ClickHouse 数据格式无关。 如果是,那么作为最后的手段,您可以进行备份并将其上传到 MySQL 进行恢复。

对于更高级的情况,ClickHouse 具有在本地文件系统中创建分区快照的内置功能。 此功能可根据要求提供 更改表冻结分区。 或者简单地 改变表冻结 - 这是整个表的快照。

快照会针对一个分片上的一张表创建一致的快照,也就是说,通过这种方式不可能创建整个集群的一致快照。 但对于大多数任务来说没有这样的需要,在每个分片上执行一个请求并获得一致的快照就足够了。 它以硬链接的形式创建,因此不占用额外的空间。 接下来,将此快照复制到备份服务器或用于备份的存储。

恢复这样的备份非常容易。 首先,使用现有表定义创建表。 接下来,将保存的分区快照复制到这些表的 Directory-Detached 并运行查询 附加分区。 该解决方案非常适合最重要的数据量。

有时您需要更酷的东西 - 如果您的每台服务器和数百台服务器上有数十甚至数百 TB 的数据。 我从 Yandex.Metrica 的同事那里得到了一个解决方案。 我不会向所有人推荐它——阅读它并自己决定它是否合适。

首先,您需要创建多台具有大型磁盘架的服务器。 接下来,在这些服务器上,启动多个 ClickHouse 服务器并配置它们,以便它们充当相同分片的另一个副本。 然后使用这些服务器上的文件系统或某些工具来创建快照。 这里有两个选择。 第一个选项是 LVM 快照,第二个选项是 Linux 上的 ZFS。

此后,您每天都需要创建快照,它会撒谎并占用一些空间。 当然,如果数据发生变化,空间量会随着时间的推移而增加。 这个快照可以随时取出来并恢复数据,这样的解决方案很奇怪。 另外,我们还需要在配置中限制这些副本,以便它们不会尝试成为领导者。

是否有可能在轴中组织受控的复制品滞后?

今年您计划在 ClickHouse 中制作轴。 是否有可能在其中组织受控的副本滞后? 我们希望用它来保护自己免受变更和其他变化带来的负面情况的影响。

是否可以对变更者进行某种回滚? 例如,在现有的竖井中,假设直到这一刻您才应用更改,从这一刻起您停止应用更改?

如果一个命令到达我们的集群并破坏了它,那么我们就有一个有一个小时滞后的条件副本,我们可以说我们现在使用它,但我们不会在最后十分钟内对其应用更改?

首先,关于副本的受控滞后。 有用户提出这样的要求,我们在 Github 上创建了一个问题,要求:“如果有人需要这个,喜欢它,就放个爱心吧。” 没有人交付,问题就结束了。 但是,您已经可以通过设置 ClickHouse 来获得这个机会。 确实,仅从 20.3 版本开始。

ClickHouse 在后台不断进行数据合并。 合并完成后,一组特定的数据将被替换为更大的数据。 同时,之前存在的数据片段会继续保留在磁盘上一段时间。

首先,只要有选择查询使用它们,它们就会继续存储,以提供非阻塞操作。 选择查询可以轻松地从旧块中读取。

其次,还有一个时间阈值——旧数据在磁盘上停留八分钟。 这八分钟可以定制,甚至可以变成一天。 这将消耗磁盘空间:根据数据流,事实证明,在最后一天,数据不仅会增加一倍,还可能增加五倍。 但如果出现严重问题,您可以停止 ClickHouse 服务器并解决所有问题。

现在的问题是如何防止改变。 这里值得深入研究,因为在旧版本的 ClickHouse 中,更改的工作方式是直接更改片段。 有一段数据有一些文件,我们这样做,例如, 改变下降列。 然后从所有块中物理删除该列。

但从 20.3 版本开始,alter 机制已经完全改变,现在数据总是不可变的。 它们根本不会改变 - 更改现在的工作方式与合并大致相同。 我们不是当场更换一件,而是创造一件新的。 在新块中,未更改的文件将成为硬链接,如果我们删除一列,它在新块中就会丢失。 旧的片段将在八分钟后默认删除,在这里您可以调整上述设置。

这同样适用于突变等改变。 当你这样做时 更改删除 или 更改更新,它不会改变该片段,而是创建一个新片段。 然后删除旧的。

如果表结构改变了怎么办?

如何恢复用旧方案制作的备份? 第二个问题是关于快照和文件系统工具的情况。 在 Linux LVM 上使用 Btrfs 代替 ZFS 好吗?

如果你这样做 附加分区 不同结构的分区,那么ClickHouse会告诉你这是不可能的。 这就是解决方案。 第一个是使用旧结构创建 MergeTree 类型的临时表,使用 Attach 将数据附加到其中,并进行更改查询。 然后您可以复制或传输此数据并再次附加,或使用请求 更改表移动分区.

现在第二个问题是是否可以使用Btrfs。 首先,如果你有LVM,那么LVM快照就足够了,文件系统可以是ext4,也没关系。 对于 Btrts,一切都取决于您的使用体验。 这是一个成熟的文件系统,但对于在特定场景下实际情况如何,仍然存在一些怀疑。 除非您在生产环境中使用 Btrfs,否则我不建议使用它。

当前数据重新分片的最佳实践是什么?

重新分片的问题是复杂且多方面的。 这里有几个可能的答案。 您可以从一方面说——ClickHouse 没有内置的重新分片功能。 但恐怕这个答案不适合任何人。 因此,你可以从另一个角度说ClickHouse有很多重新分片数据的方法。

如果集群空间不足或无法处理负载,您可以添加新服务器。 但这些服务器默认是空的,上面没有数据,没有负载。 您需要重新排列数据,使其均匀分布在新的、更大的集群中。

第一种方法是使用请求将部分分区复制到新服务器 更改表获取分区。 例如,您按月进行分区,然后将 2017 年第一个月复制到新服务器,然后将第三个月复制到其他新服务器。 这样做直到它变得或多或少均匀。

只能对录制过程中不发生变化的分区进行传输。 对于新分区,必须禁用记录,因为它们的传输不是原子的。 否则,您最终会出现数据重复或空白。 不过,这个方法很实用,而且非常有效。 现成的压缩分区通过网络传输,即数据没有被压缩或重新编码。

这种方法有一个缺点,它取决于分片方案,您是否承诺该分片方案,您拥有什么分片密钥。 在您的指标示例中,分片键是路径的哈希值。 当您选择分布式表时,它会立即转到集群中的所有分片并从那里获取数据。

这意味着什么数据最终出现在哪个分片上实际上对您来说并不重要。 最重要的是,沿着一条路径的数据最终会到达一个分片,但哪一个并不重要。 在这种情况下,传输现成的分区是完美的,因为通过选择查询,您还将收到完整的数据 - 无论是在重新分片之前还是之后,该方案并不重要。

但有些情况更为复杂。 如果在应用程序逻辑级别,您依赖于特殊的分片方案,则该客户端位于某某分片上,并且请求可以直接发送到那里,而不是发送到分布式表。 或者您使用的是 ClickHouse 的最新版本并启用了该设置 优化跳过未使用的碎片。 这种情况下,在select查询时,会分析where部分的表达式,根据分片方案计算出需要使用哪些分片。 如果数据完全按照此分片方案进行分区,则此操作有效。 如果您手动重新排列它们,对应关系可能会发生变化。

所以这是第一个方法。 我正在等待你的答复,方法是否合适,或者我们继续吧。

Vladimir Kolobaev,Avito 首席系统管理员:Alexey,当您需要分散负载(包括阅读)时,您提到的方法效果不佳。 我们可以采用每月的分区,并且可以将上个月的数据转移到另一个节点,但是当请求此数据时,我们只会加载它。 但我们希望加载整个集群,因为否则,在一段时间内整个读取负载将由两个分片处理。

阿列克谢·米洛维多夫: 这里的答案很奇怪——是的,这很糟糕,但它可能有用。 我将具体解释如何进行。 值得查看数据背后的负载场景。 如果这是监控数据,那么我们几乎可以肯定地说绝大多数请求都是针对新数据的。

您安装了新服务器,迁移了旧分区,还更改了记录新数据的方式。 并且新的数据将分布在整个集群中。 这样,仅仅五分钟后,最后五分钟的请求将均匀加载集群;一天后,XNUMX小时的请求将均匀加载集群。 不幸的是,上个月的请求只会发送到部分集群服务器。

但通常您不会收到专门针对 2019 年 2019 月的请求。 最有可能的是,如果请求进入 2019 年,那么它们将是整个 XNUMX 年的时间——很长一段时间,而不是某个小范围。 而且这样的请求也将能够均匀地加载集群。 但总的来说,您的评论是绝对正确的,这是一个临时解决方案,不能完全均匀地传播数据。

我还有几点来回答这个问题。 其中之一是关于如何最初设计分片方案,以便重新分片会减少痛苦。 这并不总是可能的。

例如,您有监控数据。 监测数据不断增长有三个原因。 首先是历史数据的积累。 二是流量增长。 第三是监控对象数量的增加。 有新的微服务和指标需要保存。

其中,最大的增长可能与第三个原因有关——监控使用的增加。 在这种情况下,值得查看负载的性质,主要的选择查询是什么。 基本选择查询很可能基于某些指标子集。

例如,某些服务在某些服务器上的 CPU 使用情况。 事实证明,您可以通过某个键子集来获取此数据。 对该数据的请求本身很可能非常简单,并且在数十毫秒内完成。 用于监控服务和仪表板。 我希望我正确理解这一点。

弗拉基米尔·科洛巴耶夫: 事实上,我们经常求助于历史数据,因为我们实时将当前情况与历史情况进行比较。 快速访问大量数据对我们来说非常重要,ClickHouse 在这方面做得非常出色。

您说得完全正确,我们在最后一天经历了大部分读取请求,就像任何监控系统一样。 但同时,历史数据的负载也相当大。 它基本上来自一个警报系统,该系统每 XNUMX 秒运行一次,并对 ClickHouse 说:“给我过去六周的数据。 现在根据它们构建某种移动平均线,然后将当前值与历史值进行比较。”

我想说的是,对于最近的请求,我们有另一个小表,其中仅存储两天的数据,主要请求飞入其中。 我们只将大型历史查询发送到大型分片表。

阿列克谢·米洛维多夫: 不幸的是,事实证明它不太适用于您的场景,但我会告诉您两个不需要使用但在我朋友的服务中使用的糟糕且复杂的分片方案的描述。

有一个包含 Yandex.Metrica 事件的主集群。 事件是页面浏览量、点击量和转化量。 大多数请求都会发送到特定网站。 您打开 Yandex.Metrica 服务,您有一个网站 - avito.ru,转到报告,并向您的网站发出请求。

但内部分析师还提出了其他要求——分析性的和全球性的。 为了以防万一,我注意到内部分析师仅提出对 Yandex 服务的请求。 但尽管如此,即使是 Yandex 服务也占据了所有数据的很大一部分。 这些请求不是针对特定计数器,而是针对更广泛的过滤。

如何以一种方式组织数据,使所有事情都能在一个计数器上高效运行,并且全局查询也能高效运行? 另一个难点是ClickHouse对Metrics集群的请求数每秒几千个。 同时,一台 ClickHouse 服务器无法处理非常重要的请求,例如每秒数千个。

集群规模为六百多台服务器。 如果您只是在该集群上拉出一个分布式表并向那里发送数千个请求,那么它会变得比将它们发送到一台服务器更糟糕。 另一方面,数据均匀分布、我们向所有服务器发出请求的选项会立即被驳回。

有一个选项是截然相反的。 想象一下,如果我们跨站点对数据进行分片,并且对一个站点的请求会发送到一个分片。 现在,集群每秒能够处理一万个请求,但在一个分片上,任何一个请求都会运行得太慢。 它将不再在吞吐量方面进行扩展。 特别是如果这是网站 avito.ru。 如果我说 Avito 是 RuNet 中访问量最大的网站之一,我不会透露这个秘密。 在一个分片上处理它是疯狂的。

因此,分片方案设计得更加狡猾。 整个簇被划分为若干个簇,我们称之为层。 每个集群包含十几个到几十个分片。 这样的星团一共有三十九个。

这一切是如何扩展的? 簇的数量没有变化——几年前是三十九个,现在仍然如此。 但在每个模型中,随着数据的积累,我们逐渐增加分片的数量。 整个分片方案是这样的:这些集群被划分为网站,为了了解哪个网站位于哪个集群上,使用了 MySQL 中单独的元数据库。 一个站点 - 在一个集群上。 在其内部,根据访客 ID 进行分片。

记录时,我们将它们除以访客 ID 的余数。 但是当添加新分片时,分片方案会发生变化;我们继续分裂,但除以另一个数字的余数。 这意味着一个访问者已经位于多个服务器上,您不能依赖这一点。 这样做只是为了确保更好地压缩数据。 当发出请求时,我们会转到分布式表,该表查看集群并访问数十台服务器。 这是一个非常愚蠢的计划。

但如果我不说我们放弃了这个计划,我的故事就不完整。 在新方案中,我们更改了所有内容并使用 clickhouse-copier 复制了所有数据。

在新方案中,所有站点都分为两类——大型站点和小型站点。 我不知道阈值是如何选择的,但结果是大型站点记录在一个集群上,其中有 120 个分片,每个分片有 360 个副本,即 120 台服务器。 分片方案使得任何请求都会立即发送到所有分片。 如果您现在在 Yandex.Metrica 中打开 avito.ru 的任何报告页面,请求将发送至 120 台服务器。 RuNet 中很少有大型站点。 而且请求每秒不是一千个,甚至不到一百个。 所有这些都被分布式表悄悄地消化掉,每个表都由 XNUMX 台服务器处理。

第二个集群适用于小型站点。 这是一种基于站点 ID 的分片方案,每个请求都只发送到一个分片。

ClickHouse 有一个 clickhouse-copier 实用程序。 你能给我们介绍一下她吗?

我马上就会说,这个解决方案比较麻烦,而且效率较低。 优点是它完全按照您指定的模式涂抹数据。 但该实用程序的缺点是它根本不重新分片。 它将数据从一个集群模式复制到另一集群模式。

这意味着要使其工作,您必须有两个集群。 它们可以位于相同的服务器上,但是数据不会增量移动,而是会被复制。

例如,原来有四台服务器,现在有八台。 您在所有服务器上创建一个新的分布式表、新的本地表并启动 clickhouse-copier,在其中指示它应该从那里读取的工作方案,接受新的分片方案并将数据传输到那里。 在旧服务器上,您将需要比现在多一倍半的空间,因为旧数据必须保留在它们上,并且一半相同的旧数据将到达它们之上。 如果你事先想到数据需要重新分片并且有空间,那么这种方法就适合。

clickhouse-copier 内部是如何工作的? 它将所有工作分解为一组任务,用于处理一个分片上一个表的一个分区。 所有这些任务都可以并行执行,clickhouse-copier可以在多个实例的不同机器上运行,但它对一个分区所做的无非是插入选择。 数据被读取、解压缩、重新分区,然后再次压缩、写入某处并重新排序。 这是一个更艰难的决定。

你有一个名为“重新分片”的试点项目。 她怎么了?

早在 2017 年,就有了一个名为“重新分片”的试点项目。 ClickHouse 甚至还有一个选项。 据我了解,它没有起飞。 你能告诉我为什么会这样吗? 这似乎是非常相关的。

整个问题在于,如果需要就地重新分片数据,则需要非常复杂的同步才能以原子方式完成此操作。 当我们开始研究这种同步是如何工作的时,很明显存在根本性的问题。 这些基本问题不仅是理论上的,而且立即开始以可以非常简单地解释的东西的形式在实践中显现出来——没有任何作用。

在将数据移动到慢速磁盘之前是否可以将所有数据合并在一起?

关于合并上下文中移动到慢速磁盘选项的 TTL 问题。 除了通过 cron 之外,还有其他方法可以将所有部分合并为一个,然后再将它们移动到慢速磁盘吗?

这个问题的答案是,有可能在转移之前以某种方式自动将所有碎片粘合在一起——不。 我认为这没有必要。 您不必将所有部分合并为一个,只需指望它们会自动传输到慢速磁盘即可。

我们对于转移规则有两个标准。 第一个是被填满的样子。 如果当前存储层的可用空间少于一定百分比,我们会选择一个块并将其移动到速度较慢的存储。 或者更确切地说,不是更慢,而是下一个 - 根据您的配置。

第二个标准是尺寸。 这是关于移动大件。 您可以根据快盘上的可用空间调整阈值,数据将自动传输。

如果无法提前检查兼容性,如何迁移到新版本的ClickHouse?

这个话题经常被讨论 在 ClickHouse 电报聊天中 考虑到不同的版本,仍然如此。 从版本 19.11 升级到 19.16,例如从 19.16 升级到 20.3 的安全性如何。 在无法提前检查沙盒中兼容性的情况下迁移到新版本的最佳方法是什么?

这里有几个“黄金”规则。 第一的 - 阅读变更日志。 它很大,但有单独的段落介绍向后不兼容的更改。 不要将这些点视为危险信号。 这些通常是轻微的不兼容性,涉及一些您很可能不会使用的边缘功能。

其次,如果沙箱中无法检查兼容性,并且您想在生产中立即更新,建议您不需要这样做。 首先创建一个沙箱并进行测试。 如果没有测试环境,那么您很可能没有一家非常大的公司,这意味着您可以将一些数据复制到您的笔记本电脑并确保一切正常。 您甚至可以在计算机上本地创建多个副本。 或者您可以在附近的某个地方获取新版本并上传一些数据 - 也就是说,创建一个临时测试环境。

另一个规则是版本发布后一周内不更新,因为在生产中发现错误并随后快速修复。 让我们弄清楚 ClickHouse 版本的编号,以免混淆。

有版本20.3.4。 数字20表示制造年份——2020年。从里面的内容来看,这个并不重要,所以我们就不去关注了。 下一步 - 20.3。 每次我们发布带有一些新功能的版本时,我们都会增加第二个数字(在本例中为 3)。 如果我们想给 ClickHouse 添加一些功能,我们必须增加这个数字。 也就是说,在 20.4 版本中,ClickHouse 会工作得更好。 第三位数字是20.3.4。 这里 4 是我们没有添加新功能,但修复了一些错误的补丁版本数量。 4 表示我们做了四次。

不要以为这是一件可怕的事情。 通常,用户可以安装最新版本,并且每年的正常运行时间不会出现任何问题。 但是想象一下,在我们中国同志添加的一些处理位图的函数中,当传递错误的参数时,服务器崩溃了。 我们有责任解决这个问题。 我们将发布新的补丁版本,ClickHouse将变得更加稳定。

如果您的 ClickHouse 在生产环境中运行,并且 ClickHouse 的新版本发布了附加功能 - 例如,20.4.1 是第一个版本,请不要急于在第一天将其投入生产。 为什么需要它? 如果您还没有使用 ClickHouse,那么您可以安装它,并且很可能一切都会好起来的。 但如果 ClickHouse 已经稳定运行,那么请密切关注补丁和更新,看看我们正在修复哪些问题。

基里尔·什瓦科夫: 我想补充一些关于测试环境的内容。 每个人都非常害怕测试环境,并且出于某种原因,他们认为如果您有一个非常大的 ClickHouse 集群,那么测试环境应该不少于或至少小十倍。 根本不是那样的。

我可以用我自己的例子来告诉你。 我有一个项目,里面有ClickHouse。 我们的测试环境是专门为他设计的 - 这是 Hetzner 的一个小型虚拟机,价格为 XNUMX 欧元,里面几乎部署了所有东西。 为此,我们在 Ansible 中实现了完全自动化,因此原则上,去哪里都没有区别 - 硬件服务器或仅部署在虚拟机中。

可以做什么? 如果能在 ClickHouse 文档中提供一个示例来说明如何在自己家里部署一个小型集群 - 在 Docker 中、在 LXC 中,也许创建一个 Ansible playbook,因为不同的人有不同的部署。 这会简化很多。 当您在五分钟内部署并部署一个集群时,尝试解决问题就会容易得多。 这要方便得多,因为推送到未经测试的生产版本是一条没有出路的路。 有时有效,有时无效。 因此,希望成功是不好的。

Maxim Kotyakov,高级后端工程师 Avito: 我将从大公司面临的一系列问题中添加一些关于测试环境的内容。 我们有一个成熟的 ClickHouse 验收集群;就数据方案和设置而言,它是生产环境的精确副本。 该集群部署在资源最少的相当破旧的容器中。 我们在那里写入一定比例的生产数据,幸运的是可以在 Kafka 中复制流。 那里的一切都是同步的和可扩展的——无论是在容量还是流量方面,而且理论上,在所有其他条件相同的情况下,它在指标方面应该像生产一样。 所有可能爆炸的东西首先被滚到这个架子上,并在那里放置几天,直到准备好。 但自然地,这个解决方案是昂贵的、困难的并且具有非零的支持成本。

阿列克谢·米洛维多夫: 我给大家介绍一下我们Yandex.Metrica的朋友的测试环境是什么样的。 其中一个集群有 600 多台服务器,另一个集群有 360 多台服务器,还有第三个集群和几个集群。 其中一个的测试环境只是两个分片,每个分片有两个副本。 为什么是两个碎片? 这样你并不孤单。 而且应该也有复制品。 只要您能负担得起的最低金额即可。

此测试环境允许您检查查询是否正常工作以及是否有任何重大问题。 但是,当一切正常,但负载出现一些小的变化时,通常会出现完全不同性质的问题。

让我举一个例子。 我们决定安装新版本的 ClickHouse。 它已发布在测试环境中,自动化测试已在 Yandex.Metrica 本身中完成,该测试比较旧版本和新版本的数据,运行整个管道。 当然,还有我们 CI 的绿色测试。 否则我们甚至不会提出这个版本。

一切安好。 我们正开始投入生产。 我收到一条消息,表明图表上的负载增加了数倍。 我们正在回滚版本。 我查看图表并发现:负载实际上在推出期间增加了几次,而在推出时又减少了。 然后我们开始回滚版本。 并且负载以同样的方式增加并以同样的方式下降。 所以结论是这样的:负载由于布局而增加,这并不奇怪。

然后很难说服同事安装新版本。 我说:“没关系,滚出去吧。” 祈祷吧,一切都会好起来的。 现在图表上的负载增加了,但一切都很好。 坚持住。” 一般来说,我们这样做了,就是这样 - 该版本已发布用于生产。 但几乎每种布局都会出现类似的问题。

Kill query 应该杀死查询,但事实并非如此。 为什么?

一位用户(某种分析师)来找我并创建了一个请求来放置我的 ClickHouse 集群。 某个节点或整个集群,具体取决于请求发送到哪个副本或分片。 我看到这台服务器上的所有CPU资源都在一个架子上,一切都是红色的。 同时,ClickHouse本身也会响应请求。 我写道:“请告诉我,进程列表,是什么请求引发了这种疯狂。”

我找到这个请求并向其写入kill。 我发现什么也没有发生。 我的服务器在架子上,ClickHouse 然后给我一些命令,显示服务器处于活动状态,一切都很好。 但是我所有的用户请求都有降级,降级从ClickHouse中的记录开始,并且我的kill查询不起作用。 为什么? 我认为终止查询应该终止查询,但事实并非如此。

现在将会有一个相当奇怪的答案。 重点是终止查询不会终止查询。

终止查询会选中一个名为“我希望终止此查询”的小框。 请求本身在处理每个块时都会查看此标志。 如果已设置,请求将停止工作。 事实证明,没有人杀死这个请求,他自己必须检查一切并停止。 这应该适用于请求处于处理数据块状态的所有情况。 它将处理下一个数据块,检查标志,然后停止。

当请求在某些操作上被阻止时,这不起作用。 确实,这很可能不是您的情况,因为根据您的说法,它使用了大量的服务器资源。 这可能在外部排序和其他一些细节的情况下不起作用。 但一般来说这不应该发生,这是一个错误。 我唯一可以推荐的是更新 ClickHouse。

如何计算阅读负载下的响应时间?

有一个表存储项目聚合 - 各种计数器。 行数约为一亿行。 如果您为 1K 个项目注入 1K RPS,是否可以指望可预测的响应时间?

从上下文来看,我们谈论的是读取负载,因为写入没有问题——甚至可以插入一千、十万、有时几百万行。

阅读要求有很大不同。 在选择1中,ClickHouse每秒可以执行大约数万个请求,因此即使是一个密钥的请求也已经需要一些资源。 而且这样的点查询会比一些键值数据库更加困难,因为每次读取都需要通过索引读取一块数据。 我们的索引不是针对每条记录,而是针对每个范围。 也就是说,您必须读取整个范围 - 默认情况下为 8192 行。 您必须将压缩数据块从 64 KB 解压缩到 1 MB。 通常,此类有针对性的查询需要几毫秒才能完成。 但这是最简单的选择。

让我们尝试一些简单的算术。 如果将几毫秒乘以一千,就会得到几秒。 好像不可能跟上每秒一千个请求,但实际上这是可能的,因为我们有几个处理器核心。 因此,原则上,ClickHouse 有时可以容纳 1000 RPS,但对于短期请求,特别有针对性的请求。

如果您需要通过简单请求的数量来扩展 ClickHouse 集群,那么我建议最简单的方法 - 增加副本数量并将请求发送到随机副本。 如果一个副本每秒处理 XNUMX 个请求(这是完全现实的),那么三个副本将处理 XNUMX 个请求。

当然,有时您可以将 ClickHouse 配置为最大数量的点读数。 为此需要什么? 首先是降低索引的粒度。 在这种情况下,不应该减少到一个,而是基于每台服务器索引中的条目数将是几百万或几千万。 如果表有一亿行,那么粒度可以设置为64。

您可以减小压缩块的大小。 有这方面的设置 最小压缩块大小, 最大压缩块大小。 可以减少它们,重新填充数据,然后有针对性的查询会更快。 但 ClickHouse 仍然不是一个键值数据库。 大量小请求是负载反模式。

基里尔·什瓦科夫: 如果那里有普通帐户,我会提供建议。 当 ClickHouse 存储某种计数器时,这是相当标准的情况。 我有一个用户,他来自某某国家,还有一些第三领域,我需要增量地增加一些东西。 以 MySQL 为例,创建一个唯一键 - 在 MySQL 中它是重复键,而在 PostgreSQL 中它是冲突 - 并添加一个加号。 这会工作得更好。

当您没有太多数据时,使用 ClickHouse 没有多大意义。 有一些常规数据库,它们在这方面做得很好。

我可以在 ClickHouse 中进行哪些调整以使缓存中有更多数据?

让我们想象一种情况 - 服务器有 256 GB RAM,在日常使用中,ClickHouse 大约需要 60-80 GB,高峰时最多 130 GB。可以启用和调整哪些内容,以便在缓存中存储更多数据,并相应地,磁盘的访问次数减少了吗?

通常,操作系统的页面缓存可以很好地完成此任务。 如果您只是打开顶部,查看缓存或空闲 - 它还说明缓存了多少 - 然后您会注意到所有可用内存都用于缓存。 并且在读取这些数据时,不会从磁盘中读取,而是从RAM中读取。 同时,我可以说缓存得到了有效的利用,因为缓存的是压缩数据。

但是,如果您想进一步加快一些简单查询的速度,可以在 ClickHouse 内的解压数据中启用缓存。 它被称为 未压缩的缓存。 在 config.xml 配置文件中,将未压缩缓存大小设置为您需要的值 - 我建议不要超过可用 RAM 的一半,因为其余部分将进入页面缓存。

此外,还有两个请求级别设置。 第一个设置 - 使用未压缩的缓存 - 包括其使用。 建议对所有请求启用它,除了重型请求,重型请求可以读取所有数据并刷新缓存。 第二个设置类似于使用缓存的最大行数。 它会自动限制大型查询,以便它们绕过缓存。

如何配置 RAM 中存储的 storage_configuration?

在新的 ClickHouse 文档中,我阅读了相关部分 带数据存储。 描述包含快速 SSD 的示例。

我想知道如何使用卷热内存配置同样的东西。 还有一个问题。 select 如何处理此数据组织,它会读取整个数据集还是仅读取磁盘上的数据集,以及该数据是否压缩在内存中? prewhere 部分如何与这样的数据组织一起工作?

此设置会影响数据块的存储,并且它们的格式不会以任何方式改变。
让我们仔细看看。

您可以配置 RAM 中的数据存储。 为磁盘配置的只是其路径。 您创建一个挂载到文件系统中某个路径的 tmpfs 分区。 你指定这个路径作为最热分区的数据存储路径,数据开始到达并写入那里,一切正常。

但我不建议这样做,因为可靠性低,尽管如果您在不同的数据中心至少有三个副本,那么这是可能的。 如果发生任何情况,数据将被恢复。 让我们想象一下服务器突然关闭并重新打开。 分区又挂载了,但是什么也没有。 当 ClickHouse 服务器启动时,它发现它没有这些片段,尽管根据 ZooKeeper 元数据,它们应该在那里。 他查看哪些副本有它们,请求它们并下载它们。 这样数据就会恢复。

从这个意义上说,将数据存储在 RAM 中与将数据存储在磁盘上并没有本质上的区别,因为当数据写入磁盘时,它也会首先出现在页缓存中,然后再进行物理写入。 这取决于文件系统安装选项。 但为了以防万一,我会说 ClickHouse 在插入时不会进行 fsync。

在这种情况下,RAM 中的数据以与磁盘上完全相同的格式存储。 select查询同样的方式选择需要读取的分片,选择分片中需要的数据范围,并读取。 无论数据是在 RAM 中还是在磁盘上, prewhere 的工作原理都完全相同。

低基数最多多少个唯一值才有效?

Low Cardinality 的设计巧妙。 它编译数据字典,但它们是本地的。 首先,每件作品都有不同的词典,其次,即使在一件作品中,每个范围的词典也可能不同。 当唯一值的数量达到阈值(我认为是一百万)时,字典就会被简单地搁置并创建一个新字典。

答案通常是:对于每个局部范围(例如,每天),最多有一百万个唯一值,低基数是有效的。 之后将有一个简单的后备,其中将使用许多不同的词典,而不仅仅是一个。 它的工作方式与常规字符串列大致相同,可能效率稍低,但不会严重降低性能。

对具有 XNUMX 亿行的表进行全文搜索的最佳实践是什么?

有不同的答案。 首先要说的是ClickHouse不是全文搜索引擎。 为此有特殊的系统,例如, Elasticsearch и 人头狮身。 然而,我越来越多地看到人们说他们正在从 Elasticsearch 转向 ClickHouse。

为什么会出现这种情况? 他们通过以下事实来解释这一点:从构建索引开始,Elasticsearch 就不再能够应对某些卷的负载。 索引变得太麻烦了,如果只是将数据传输到 ClickHouse,结果发现它们的存储效率在体积上提高了数倍。 同时,搜索查询通常不需要在整个数据量中查找某些短语,同时考虑形态,而是完全不同的短语。 例如,在过去几个小时的日志中查找一些字节序列。

在本例中,您在 ClickHouse 中创建一个索引,其第一个字段将是日期和时间。 最大数据截止将基于日期范围。 在选定的日期范围内,通常已经可以进行全文搜索,甚至使用类似的暴力方法。 ClickHouse 中的 like 运算符是您能找到的最高效的 like 运算符。 如果你发现更好的东西,请告诉我。

但仍然是完整扫描。 完全扫描不仅在 CPU 上很慢,在磁盘上也很慢。 如果突然间您每天有 XNUMX TB 的数据,并且您在白天搜索一个单词,那么您将不得不扫描 XNUMX TB 数据。 它可能位于普通硬盘上,最终它们将以这样的方式加载,您将无法通过 SSH 访问该服务器。

既然如此,我准备再提供一个小技巧。 它是实验性的——它可能有效,也可能无效。 ClickHouse 具有三元组布隆过滤器形式的全文索引。 我们在 Arenadata 的同事已经尝试过这些索引,并且它们通常完全按照预期工作。

为了正确使用它们,您应该充分了解它们的工作原理:什么是三元布隆过滤器以及如何选择其大小。 我可以说它们将有助于查询一些罕见的短语、数据中很少找到的子字符串。 在这种情况下,将通过索引选择子范围,并且将读取较少的数据。

最近,ClickHouse 增加了更高级的全文搜索功能。 首先,这是一次性搜索一堆子字符串,包括区分大小写、不区分大小写、支持 UTF-8 或仅支持 ASCII 的选项。 选择您需要的最有效的一种。

还出现了一次搜索多个正则表达式的情况。 您不需要将 X 写成一个子字符串或将 X 写成另一子字符串。 你马上写,一切都会尽可能高效地完成。

第三,现在有正则表达式的近似搜索和子字符串的近似搜索。 如果有人拼错了某个单词,则会搜索最大匹配项。

组织大量用户访问 ClickHouse 的最佳方式是什么?

告诉我们如何最好地组织大量消费者和分析师的访问。 如何形成队列、确定最大并发查询的优先级以及使用什么工具?

如果集群足够大,那么一个好的解决方案是再增加两台服务器,这将成为分析师的切入点。 即不允许分析人员访问集群中的特定分片,而只是创建两台没有数据的空服务器,并在其上配置访问权限。 在这种情况下,分布式请求的用户设置将传输到远程服务器。 也就是说,您在这两台服务器上配置所有内容,并且这些设置会对整个集群产生影响。

原则上,这些服务器没有数据,但其上的 RAM 量对于执行请求非常重要。 如果启用外部聚合或外部排序,该磁盘还可以用于临时数据。

查看与所有可能限制相关的设置非常重要。 如果我现在以分析师的身份进入 Yandex.Metrica 集群并提出请求 从点击中选择计数,那么我将立即得到一个异常,即我无法执行该请求。 我允许扫描的最大行数是 XNUMX 亿行,集群上的一张表中总共有 XNUMX 万亿行。 这是第一个限制。

假设我删除了行限制并再次运行查询。 然后我会看到以下异常 - 设置已启用 按日期强制索引。 如果未指定日期范围,我无法完成查询。 您不必依赖分析师手动指定它。 典型的情况是日期范围写为事件日期在周之间。 然后他们只是在错误的位置指定了一个括号,而不是 and 结果是 or - or URL 匹配。 如果没有限制,它就会抓取URL列,浪费大量资源。

另外,ClickHouse还有两个优先级设置。 不幸的是,它们非常原始。 一种简单地称为 优先。 如果priority ≠ 0,并且正在执行某个优先级的请求,但是正在执行优先级值小于(即优先级较高)的请求,则优先级值大于(即优先级较低)的请求正在执行,只是暂停,在此期间根本不会工作。

这是一个非常粗略的设置,不适合集群负载恒定的情况。 但是,如果您有重要的短的突发请求,并且集群大部分处于空闲状态,则此设置很合适。

下一个优先级设置称为 操作系统线程优先级。 它只是为 Linux 调度程序的所有请求执行线程设置好值。 它工作马马虎虎,但仍然有效。 如果您设置最小的nice值(它是最大的值,因此优先级最低),并为高优先级的请求设置-19,那么CPU消耗的低优先级请求大约是高优先级请求的四倍。

您还需要配置最大请求执行时间 - 例如五分钟。 查询执行的最低速度是最酷的事情。 这个设置已经存在很长时间了,不仅需要断言ClickHouse不会变慢,而且需要强制它。

想象一下,您设置:如果某个查询每秒处理的行数少于一百万行,您就不能这样做。 这玷污了我们的好名声、我们良好的数据库。 我们就禁止这个吧。 实际上有两种设置。 一种叫做 最小执行速度 - 以每秒行数为单位,第二个称为检查最小执行速度之前的超时 - 默认情况下为十五秒。 也就是说,十五秒是可能的,然后,如果很慢,则抛出异常并中止请求。

您还需要设置配额。 ClickHouse有一个内置的配额功能,可以统计资源消耗。 但不幸的是,不是 CPU、磁盘等硬件资源,而是逻辑资源——处理的请求数、读取的行数和字节数。 例如,您可以配置五分钟内最多一百个请求和每小时一千个请求。

它为什么如此重要? 因为某些分析查询将直接从 ClickHouse 客户端手动执行。 一切都会好起来的。 但如果你公司里有高级分析师,他们会写一个脚本,脚本中可能会有错误。 并且这个错误会导致请求无限循环执行。 这就是我们需要保护自己免受的影响。

是否可以将一个查询的结果提供给十个客户端?

我们有几个用户喜欢在同一时间点提出非常大的请求。 请求很大,原则上执行得很快,但由于同时有很多这样的请求,所以变得非常痛苦。 是否可以执行连续十次到达的同一请求一次,并将结果提供给十个客户端?

问题是我们没有缓存结果或者缓存中间数据。 操作系统有一个页面缓存,它会阻止你再次从磁盘读取数据,但不幸的是,数据仍然会被解压缩、反序列化和重新处理。

我想以某种方式避免这种情况,要么通过缓存中间数据,要么通过在某种队列中排列类似的查询并添加结果缓存。 目前,我们正在开发一个拉取请求,该请求添加了请求缓存,但仅适用于 in 和 join 部分中的子查询 - 也就是说,该解决方案是不完整的。

然而,我们也面临着这样的情况。 一个特别典型的例子是分页查询。 有一份报告,有好几页,要求限制10。然后同样的事情,但是限制10,10。 然后是下一页。 问题是,为什么我们每次都要计算这一切? 但现在没有解决办法,也没有办法避免。

有一个替代解决方案,作为 ClickHouse 旁边的 sidecar 放置 - ClickHouse代理.

基里尔·什瓦科夫: ClickHouse Proxy 有一个内置的速率限制器和一个内置的结果缓存。 那里做了很多设置,因为正在解决类似的问题。 代理允许您通过对请求进行排队来限制请求并配置请求缓存的生存时间。 如果请求确实相同,Proxy 会发送多次,但只会发送到 ClickHouse 一次。

Nginx 在免费版本中也有缓存,这也可以工作。 Nginx 甚至有一个设置,如果请求同时到达,它会减慢其他请求,直到一个请求完成。 但在 ClickHouse Proxy 中,设置要好得多。 它是专门为ClickHouse做的,专门针对这些请求,所以更适合。 嗯,安装很容易。

异步操作和物化视图怎么样?

存在一个问题,即重放引擎的操作是异步的 - 首先写入数据,然后数据崩溃。 如果具有某些聚合的物化平板电脑位于该标志下,则将向其写入副本。 而如果没有复杂的逻辑,那么数据就会重复。 你能为这个做什么?

有一个明显的解决方案 - 在异步折叠操作期间在特定类别的 matview 上实现触发器。 是否有任何灵丹妙药或计划来实现类似的功能?

值得了解重复数据删除的工作原理。 我现在要告诉你的内容与这个问题无关,但以防万一值得记住。

当插入到复制表时,会对整个插入的块进行重复数据删除。 如果您以相同的顺序重新插入包含相同数量的相同行的同一块,则会对数据进行重复数据删除。 插入时会收到“Ok”响应,但实际上会写入一包数据,并且不会重复。

为了确定性,这是必要的。 如果在插入过程中收到“Ok”,则表明您的数据已插入。 如果您收到来自 ClickHouse 的错误,则意味着它们未插入,您需要重复插入。 但如果在插入过程中连接断开,那么你就不知道数据是否插入了。 唯一的选择是再次重复插入。 如果数据确实已插入并且您重新插入它,则会进行块重复数据删除。 这是避免重复所必需的。

它如何适用于物化视图也很重要。 如果数据在插入主表时进行了重复数据删除,那么它也不会进入物化视图。

现在关于这个问题。 您的情况更加复杂,因为您正在记录各个行的重复项。 也就是说,复制的不是整个包,而是特定的行,并且它们在背景中折叠。 事实上,数据将在主表中折叠,但未折叠的数据将转到物化视图,并且在合并期间物化视图不会发生任何变化。 因为物化视图无非就是一个插入触发器。 在其他操作期间,不会发生任何其他情况。

我在这里无法让你快乐。 您只需要针对这种情况寻找特定的解决方案。 例如,是否可以在物化视图中重放它,并且重复数据删除方法可能会以相同的方式工作。 但不幸的是,情况并非总是如此。 如果是聚合的话,就不行了。

基里尔·什瓦科夫: 那时我们还建造了拐杖。 存在一个问题,即有广告印象,并且有一些我们可以实时显示的数据 - 这些只是印象。 它们很少被重复,但如果发生这种情况,我们无论如何都会在以后折叠它们。 有些东西是无法复制的——点击和整个故事。 但我也想立即向他们展示。

物化视图是如何制作的? 有些视图是直接写入的——它被写入原始数据,并写入视图。 在那里,在某些时候数据不是很正确,它是重复的,等等。 还有表格的第二部分,它们看起来与物化视图完全相同,也就是说,它们在结构上绝对相同。 我们偶尔会重新计算数据,计算没有重复的数据,然后写入这些表。

我们通过了 API - 这在 ClickHouse 中手动不起作用。 API 看起来:当我有最后一次添加到表中的日期时,可以保证已经计算出正确的数据,并且它向一个表和另一个表发出请求。 请求从一个请求中选择最多一定的时间,从另一个请求中获取尚未计算的时间。 它可以工作,但不能单独通过 ClickHouse。

如果您有某种 API(供分析师、用户使用),那么原则上这是一个选择。 你总是在数,总是在数。 这可以每天进行一次或在其他时间进行。 您可以为自己选择一个不需要且不重要的范围。

ClickHouse有很多日志。 如何才能对服务器发生的一切一目了然?

ClickHouse 拥有非常大量的不同日志,并且这个数量还在不断增加。 在新版本中,其中一些甚至默认启用;在旧版本中,更新时必须启用它们。 然而,这样的人越来越多。 最终,我想看看我的服务器现在发生了什么,也许是在某种摘要仪表板上。

您是否有 ClickHouse 团队或您朋友的团队支持现成仪表板的某些功能,将这些日志显示为成品? 最终,仅查看 ClickHouse 中的日志就很棒了。 但如果它已经以仪表板的形式准备好了,那就太酷了。 我会从中得到乐趣。

有仪表板,尽管它们不是标准化的。 在我们公司,大约有60个团队使用ClickHouse,最奇怪的是他们中的许多人都有自己制作的仪表板,并且略有不同。 有些团队使用内部 Yandex.Cloud 安装。 有一些现成的报告,但不是所有必要的报告。 其他人有他们自己的。

我来自 Metrica 的同事在 Grafana 中有他们自己的仪表板,我也有自己的仪表板用于他们的集群。 我正在研究诸如衬线缓存的缓存命中之类的事情。 更困难的是我们使用不同的工具。 我使用一个名为 Graphite-web 的非常古老的工具创建了仪表板。 他完全丑陋了。 我仍然这样使用它,尽管 Grafana 可能会更方便、更美观。

仪表板中的基本内容是相同的。 这些是集群的系统指标:CPU、内存、磁盘、网络。 其他 - 同时请求数、同时合并数、每秒请求数、MergeTree 表分区的最大块数、复制延迟、复制队列大小、每秒插入的行数、每秒插入的块数。 这不是从日志中获得的,而是从指标中获得的。

弗拉基米尔·科洛巴耶夫: 阿列克谢,我想纠正一下。 有格拉法纳。 Grafana有一个数据源,就是ClickHouse。 也就是说,我可以从 Grafana 直接向 ClickHouse 发出请求。 ClickHouse有一个包含日志的表,对于每个人来说都是一样的。 因此,我想访问 Grafana 中的这个日志表并查看我的服务器发出的请求。 如果有一个这样的仪表板就太好了。

我自己骑自行车去的。 但我有一个问题——如果都是标准化的,而且Grafana大家都用,为什么Yandex没有这样的官方仪表板呢?

基里尔·什瓦科夫: 事实上,进入 ClickHouse 的数据源现在支持 Altinity。 我只想给出一个向量,说明在哪里挖掘以及推谁。 你可以问他们,因为 Yandex 仍然在制作 ClickHouse,而不是围绕它的故事。 Altinity是目前推广ClickHouse的主要公司。 他们不会抛弃他,而是会支持他。 因为原则上,要将仪表板上传到 Grafana 网站,您只需要注册并上传即可 - 没有特殊问题。

阿列克谢·米洛维多夫: 在过去的一年里,ClickHouse 添加了许多查询分析功能。 每个请求都有关于资源使用情况的指标。 就在最近,我们添加了一个更低级别的查询分析器来查看查询每毫秒花费在哪里。 但要使用此功能,我必须打开控制台客户端并输入请求,但我总是忘记这一点。 我把它保存在某个地方,但一直忘记具体在哪里。

我希望有一个工具可以说,这是您的大量查询,按查询类分组。 我按了一个,他们会告诉我这就是它重的原因。 现在还没有这样的解决方案。 而且真的很奇怪,当人们问我:“告诉我,Grafana 有现成的仪表板吗?”,我说:“去 Grafana 网站,有一个‘Dashboards’社区,还有一个仪表板来自 Dimka 的仪表板来自 Kostyan。 我不知道那是什么,我自己没用过。”

如何影响合并以使服务器不会崩溃 OOM?

我有一张表,表中只有一个分区,它是ReplacingMergeTree。 我已经向其中写入数据四年了。 我需要对其进行更改并删除一些数据。

我这样做了,在处理这个请求的过程中,集群中所有服务器上的内存都被消耗掉了,集群中所有服务器都进入了OOM状态。 然后他们都一起站起来,开始合并这个相同的操作,这个数据块,然后又陷入了OOM。 然后他们又站起来,又跌倒了。 而这件事并没有停止。

后来发现这实际上是他们修复的一个错误。 这非常酷,非常感谢。 但仍有残留物。 现在,当我考虑在表中进行某种合并时,我有一个问题 - 为什么我不能以某种方式影响这些合并? 例如,按所需的 RAM 量来限制它们,或者原则上按处理此特定表的量来限制它们。

我有一个名为“Metrics”的表,请在两个线程中为我处理它。 无需并行创建十个或五个合并,只需分两次进行即可。 我认为我的内存足够处理两个,但可能不足以处理十个。 为什么恐惧依然存在? 因为表正在增长,有一天我将面临一种情况,原则上不再是由于错误,而是因为数据会发生大量变化,以至于我根本没有足够的内存服务器。 然后合并时服务器会崩溃OOM。 而且,我可以取消变异,但梅尔吉已经不在了。

要知道,合并时,服务器不会陷入 OOM,因为合并时,RAM 量仅用于一小部分数据。 所以无论数据量有多大,一切都会好起来的。

弗拉基米尔·科洛巴耶夫: 美好的。 此刻,在错误修复后,我为自己下载了一个新版本,在另一个较小的表上,有很多分区,我执行了类似的操作。 在合并过程中,服务器上大约 100 GB 的 RAM 被烧毁。 我有 150 个被占用,100 个被吃掉,还剩下 50 GB 的窗口,所以我没有陷入 OOM。

如果实际消耗 100 GB RAM,目前什么可以保护我免于陷入 OOM? 如果合并时的 RAM 突然耗尽怎么办?

阿列克谢·米洛维多夫: 存在这样的问题:专门用于合并的RAM的消耗不受限制。 第二个问题是,如果已经分配了某种合并,那么它必须被执行,因为它记录在复制日志中。 复制日志是使副本进入一致状态所需的操作。 如果您不进行手动操作来回滚此复制日志,则必须以一种或另一种方式执行合并。

当然,为了“以防万一”防止 OOM 而设置 RAM 限制并不是多余的。 它不会帮助合并完成,它会再次开始,达到某个阈值,抛出异常,然后再次开始 - 这不会带来任何好处。 但原则上,引入此限制是有用的。

ClickHouse 的 Golang 驱动程序将如何开发?

由 Kirill Shvakov 编写的 Golang 驱动程序现已得到 ClickHouse 团队的正式支持。 他 在 ClickHouse 存储库中,他现在又大又真实了。

一个小笔记。 有一个美妙且受人喜爱的无限有序范式存储库 - 这就是 Vertica。 他们还有自己的官方 python 驱动程序,并得到 Vertica 开发人员的支持。 有几次,存储版本和驱动程序版本差异很大,驱动程序在某个时候停止工作。 还有第二点。 在我看来,对这个官方驱动程序的支持是由“nipple”系统执行的 - 你给他们写一个问题,它就会永远挂起。

我有两个问题。 现在,Kirill 的 Golang 驱动程序几乎是 Golang 与 ClickHouse 通信的默认方式。 除非有人仍然通过http接口进行通信,因为他喜欢那样。 该驱动程序的开发将如何进行? 它会与存储库本身的任何重大更改同步吗? 考虑问题的程序是什么?

基里尔·什瓦科夫: 首先是一切都是如何官僚化组织的。 这一点没有讨论过,所以我无话可说。

为了回答这个问题,我们需要了解一下驱动程序的历史。 我在一家拥有大量数据的公司工作。 这是一个广告旋转器,有大量事件需要存储在某个地方。 在某个时候 ClickHouse 出现了。 我们向其中填充了数据,一开始一切都很好,但后来 ClickHouse 崩溃了。 那一刻我们决定不需要它。

一年后,我们又回到了使用ClickHouse的想法,我们需要以某种方式在那里写入数据。 介绍信息是这样的:硬件很薄弱,资源很少。 但我们一直都是这样工作的,因此我们转向了原生协议。

由于我们使用 Go 工作,很明显我们需要一个 Go 驱动程序。 我几乎全职做这件事——这是我的工作任务。 我们把它带到了一定程度,原则上没有人认为除了我们之外的任何人都会使用它。 然后CloudFlare也遇到了完全相同的问题,有一段时间我们和他们合作得非常顺利,因为他们有相同的任务。 此外,我们在 ClickHouse 中和驱动程序中都这样做了。

在某些时候,我干脆停止这样做,因为我在 ClickHouse 和工作方面的活动发生了一些变化。 因此问题并未结束。 需要某些东西的人会定期向存储库提交内容。 然后我查看拉取请求,有时我什至自己编辑一些东西,但这种情况很少发生。

我想回到司机那里。 几年前,当这一切开始时,ClickHouse 也是不同的,并且具有不同的功能。 现在我们已经了解了如何重新制作驱动程序以使其正常工作。 如果发生这种情况,那么由于积累的拐杖,版本 2 无论如何都将不兼容。

我不知道如何组织这件事。 我自己的时间不多。 如果有人完成了驱动程序,我可以帮助他们并告诉他们该怎么做。 但Yandex是否积极参与该项目的开发尚未被讨论。

阿列克谢·米洛维多夫: 事实上,这些司机还没有官僚主义。 唯一的一点是它们是提交给官方组织的,也就是说这个驱动程序被认可为Go官方的默认解决方案。 还有一些其他驱动程序,但它们是分开的。

我们没有对这些驱动程序进行任何内部开发。 问题是我们是否可以雇佣一个个人,不是为了这个特定的司机,而是为了所有社区司机的发展,或者我们可以从外部找到一个人。

启用lazy_load 设置后重新启动后,外部字典不会加载。 该怎么办?

我们启用了lazy_load设置,并且在服务器重新启动后,字典不会自行加载。 仅在用户访问此字典后才会引发它。 当我第一次访问它时,它给出了一个错误。 是否可以使用 ClickHouse 以某种方式自动加载字典,或者您是否需要始终自己控制它们的准备情况,以便用户不会收到错误?

也许我们有一个旧版本的 ClickHouse,所以字典没有自动加载。 可能是这样吗?

首先,可以使用查询强制加载字典 系统重新加载词典。 其次,关于错误 - 如果字典已经加载,那么查询将根据加载的数据进行工作。 如果字典尚未加载,则在请求时直接加载。

这对于厚重的词典来说不太方便。 例如,您需要从 MySQL 中提取一百万行。 有人做了一个简单的选择,但这个选择将等待同样的百万行。 这里有两种解决方案。 首先是关闭lazy_load。 其次,当服务器启动时,在对其施加负载之前,执行以下操作 系统重新加载字典 或者只是使用字典进行查询。 然后字典将被加载。 您需要在启用lazy_load设置的情况下控制字典的可用性,因为ClickHouse不会自动加载它们。

最后一个问题的答案是要么版本旧,要么需要调试。

如果系统重新加载字典中至少有一个字典因错误而崩溃,那么系统重新加载字典不会加载任何字典,该怎么办?

还有一个关于系统重载字典的问题。 我们有两本字典 - 一本未加载,第二本已加载。 在这种情况下,系统重新加载字典不会加载任何字典,您必须使用系统重新加载字典按名称逐点加载特定字典。 这也和ClickHouse版本有关吗?

我想让你幸福。 这种行为正在改变。 这意味着如果你更新ClickHouse,它也会改变。 如果您对自己目前的行为不满意 系统重新加载词典,更新,希望它能变得更好。

有没有办法在 ClickHouse 配置中配置详细信息,但在出现错误时不显示它们?

下一个问题是与字典相关的错误,即细节。 我们已在 ClickHouse 配置中为字典指定了连接详细信息,如果出现错误,我们会收到这些详细信息和密码作为响应。

我们通过向 ODBC 驱动程序配置添加详细信息解决了此错误。 有没有办法在 ClickHouse 配置中配置详细信息,但在出现错误时不显示这些详细信息?

这里真正的解决方案是在 odbc.ini 中指定这些凭据,并在 ClickHouse 本身中仅指定 ODBC 数据源名称。 对于其他字典源,这种情况不会发生 - 无论是 MySQL 字典还是其他字典,当您收到错误消息时,您都不应该看到密码。 对于 ODBC,我也会查看 - 如果存在,则只需将其删除即可。

奖励:来自聚会的 Zoom 背景

通过点击图片,聚会的奖励背景将为最执着的读者打开。 我们与 Avito 技术吉祥物一起扑灭大火,与系统管理员室或老式计算机俱乐部的同事进行协商,并在桥下的涂鸦背景下进行日常会议。

ClickHouse 为高级用户提供问答

来源: habr.com

添加评论