一、背景
在本博客文章系列的前半部分中,解释了Cassandra 设计流数据管道的决策过程。在这篇文章中,我们将把管道分为三个部分,并更详细地讨论每个部分:
- Cassandra 到 Kafka 与 CDC 代理
- Kafka 与 BigQuery 和 KCBQ
- 使用 BigQuery 视图进行转换
相关技术博客:
- Debezium日常分享系列之:流式传输 Cassandra
二、Cassandra 到 Kafka 与 CDC Agent
Cassandra CDC 代理是一个 JVM 进程,旨在部署在 Cassandra 集群中的每个节点上。该代理由多个相互依赖的处理器组成,这些处理器同时运行并协同工作,将更改事件发布到 Kafka。
三、快照处理器
该处理器负责引导新表。它查找 CDC 配置以确定快照模式,并在需要时对启用 CDC 的表执行快照。为了对表进行快照,代理执行全表扫描,并将结果集中的每一行转换为单独的创建事件,然后将它们按顺序排入内存中的 BlockingQueue。
BlockingQueue是Java中的一个接口,它是在并发编程中用于线程安全的队列操作的一种数据结构。BlockingQueue继承自Queue接口,并扩展了一些阻塞操作的方法,使得它在多线程环境下更加安全和高效。
BlockingQueue的主要特点是支持阻塞操作,即当队列为空时,获取元素的操作将会阻塞等待,直到队列中有可用元素;当队列已满时,插入元素的操作将会阻塞等待,直到队列中有空闲位置。
BlockingQueue提供了以下常用的方法:
-
put(E element):将指定的元素插入到队列的尾部,并在队列已满时阻塞等待。
-
take():从队列的头部获取并删除一个元素,并在队列为空时阻塞等待。
-
offer(E element, long timeout, TimeUnit unit):将指定的元素插入到队列的尾部,并在队列已满时等待一定的时间。
-
poll(long timeout, TimeUnit unit):从队列的头部获取并删除一个元素,并在队列为空时等待一定的时间。
BlockingQueue的实现类有多种,如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue等。开发者可以根据具体的需求选择合适的实现类。
总结来说,BlockingQueue是一种线程安全的队列数据结构,它支持阻塞操作,可以在多线程环境下安全地进行队列操作,常用于实现生产者-消费者模型等并发编程场景。
四、提交日志处理器
该处理器负责监视 CDC 目录中的新提交日志,通过 Cassandra 的 CommitLogReader 解析提交日志文件,将反序列化的事件转换为标准化的更改事件,最后将它们排队到与快照处理器相同的队列中。
此时,可能会对并发而不是串行运行快照处理器和提交日志处理器有所顾虑。原因是 Cassandra 使用客户端时间戳来确定事件顺序,并解决与上次写入成功的冲突。这个客户端时间戳被故意存储在每个更改事件中。这就是为什么快照不必进行提交日志处理——稍后在数据仓库中查询数据时确定顺序。
五、队列处理器
该处理器负责使更改事件出队,将它们转换为 Avro 记录,并通过 Kafka 生产者将它们发送到 Kafka。它还跟踪最近发送的事件的位置,以便在重新启动时能够从上次中断的位置继续。
在 CDC 代理中实现内存队列乍一看似乎有点矫枉过正。由于只有一个线程执行入队操作,另一个线程执行出队操作,因此性能提升可以忽略不计。这里的动机是将解析提交日志的工作(应该以正确的顺序串行完成)与序列化和发布 Kafka 事件的工作(可以由不同表的多个线程并行化)分离。尽管目前尚未实现这种并行化,但我们希望在不久的将来能够灵活地添加此功能。
有些人可能还想知道为什么这里不使用 Kafka Connect,因为它似乎很适合流媒体。如果我们想要具有容错能力的分布式并行处理,这是一个很好的选择。然而,它的部署、监控和调试比 Kafka 生产者更复杂。出于构建最小可行基础设施的目的,我们当时选择了Kafka Producer。
六、模式处理器
为了支持自动模式演变,该处理器定期轮询数据库以获取最新的表模式,并在检测到更改时更新内存中的模式缓存。快照处理器和提交日志处理器都从此缓存中查找表架构,并将其作为更改事件的一部分在入队之前附加。然后出列时,队列处理器将附加表模式转换为 Avro 模式以进行记录序列化。
七、提交日志后处理器
该处理器负责在处理提交日志后清理它们。默认的提交日志后处理器实现将简单地执行删除。可以针对用例配置自定义提交日志后处理器,例如将提交日志文件归档到 S3 或 GCS。
八、使用 KCBQ 将 Kafka 转换为 BigQuery
一旦事件到达 Kafka,我们就使用 KCBQ 将事件数据发送到 BigQuery,无需执行特殊转换,就像在 MySQL 流数据管道中一样。
九、使用 BigQuery View 进行转换
一旦事件进入 BigQuery,繁重的工作就在此处完成。我们在原始表之上创建虚拟视图,以镜像 Cassandra 中源表的方式合并数据。请注意,原始表中的每一行包含有限的数据 - 只有已修改的列才有状态。这意味着为每个主键选择最新行不会为我们提供与源一致的数据。相反,查询必须识别每个主键的每列中的最新单元格。这可以通过表中每列的主键上的自联接来实现。尽管 MySQL 中的连接速度很慢,但 BigQuery 的并行执行引擎和列式存储使这成为可能。 BigQuery 中 1TB Cassandra 表顶部的视图大约需要 100 秒来查询。
十、Compaction
BigQuery 视图是虚拟的这一事实意味着每次查询视图时都会触发原始数据的完全压缩。这意味着成本将随着查询数量的增加而增加,更不用说重复的事件会将需要处理的数据量放大 N 倍,其中 N 是复制因子。为了节省成本并提高性能,通过物化视图进行定期压缩是必要的。
十一、未来的开发工作
1.支持Cassandra 4.0
在 Cassandra 4.0 中,改进的 CDC 功能允许连接器能够在写入事件时实时解析事件,而不是在每次提交日志刷新时进行微批量处理。这大大减少了延迟。
在 Cassandra 4.0 中,改进的 CDC 功能允许连接器能够在写入事件时实时解析事件,而不是在每次提交日志刷新时进行微批量处理。这大大减少了延迟。
2.性能优化
如前所述,有一个线程负责使 Kafka 记录出队、序列化和发布。但是,随着写入吞吐量的增加,如果代理的性能跟不上,就会导致未处理的提交日志积压,这可能会影响生产数据库的运行状况。下一步是利用事件的并行处理来优化性能。
3.使用 Debezium 和 Kafka Connect 进行简化
最初将 Cassandra CDC 代理构建为独立项目。现在它作为 Debezium 连接器开源,我们可以用 Debezium 中的现有类替换一些自定义类。另一个改进是支持所有 Debezium 连接器都具有的通用功能,例如支持多种序列化格式。最后,CDC代理不具备容错能力;作为部署的一部分,需要强大的警报和监控。未来需要探索的一个领域是在 Kafka Connect 之上构建 CDC 代理作为源连接器,这进一步简化了 Cassandra 连接器与其他 Debezium 连接器的连接,并免费提供可扩展性和容错能力。
十二、总结
Cassandra 作为一种点对点分布式数据库,给 CDC 带来了一些非常有趣的挑战,这些挑战在 MySQL 和 Postgres 等关系数据库中,甚至在 MongoDB 等单主 NoSQL 数据库中都不存在。请注意,在为 Cassandra 推出您自己的实时数据管道之前,值得评估其限制。
除了了解 Cassandra 内部结构之外,我们还学到了一些有关工程生产力的经验教训:文章来源:https://www.toymoban.com/news/detail-559404.html
最小可行产品理念文章来源地址https://www.toymoban.com/news/detail-559404.html
- 通过剥离除必需功能之外的所有功能,我们能够在合理的时间内利用有限的资源构建、测试和部署可行的解决方案。如果我们的目标是预先设计一个包含所有功能的管道,那么就会花费更长的时间并需要更多的资源。
到了这里,关于Debezium日常分享系列之:流式传输Cassandra第二部分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!