原文地址: https://debezium.io/blog/2019/07/15/streaming-cassandra-at-wepay-part-2/
欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯.
在 WePay 上流式传输 Cassandra - 第 2 部分
七月 15, 2019 作者: Joy 高
卡桑德拉
这篇文章最初出现在WePay Engineering 博客上。
在本博客文章系列的前半部分中,我们解释了为 WePay 的 Cassandra 设计流数据管道的决策过程。在这篇文章中,我们将把管道分为三个部分,并更详细地讨论每个部分:
Cassandra 到 Kafka 与 CDC 代理
Kafka 与 BigQuery 和 KCBQ
使用 BigQuery 视图进行转换
Cassandra 到 Kafka 与 CDC Agent
Cassandra CDC 代理是一个 JVM 进程,旨在部署在 Cassandra 集群中的每个节点上。该代理由多个相互依赖的处理器组成,这些处理器同时运行并协同工作,将更改事件发布到 Kafka。
快照处理器
该处理器负责引导新表。它查找 CDC 配置以确定快照模式,并在需要时对启用 CDC 的表执行快照。为了对表进行快照,代理执行全表扫描并将结果集中的每一行转换为单独的创建事件,然后将它们按顺序排列到内存中的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 秒来查询。
压实
BigQuery 视图是虚拟的这一事实意味着每次查询视图时都会触发原始数据的完全压缩。这意味着成本将随着查询数量的增加而增加,更不用说重复的事件会将需要处理的数据量放大 N 倍,其中 N 是复制因子。为了节省成本并提高性能,通过物化视图进行定期压缩是必要的。
未来的开发工作
支持卡桑德拉 4.0
在 Cassandra 4.0 中,改进的 CDC 功能允许连接器能够在写入事件时实时解析事件,而不是在每次提交日志刷新时进行微批量处理。这大大减少了延迟。
性能优化
如前所述,有一个线程负责使 Kafka 记录出队、序列化和发布。但是,随着写入吞吐量的增加,如果代理的性能跟不上,就会导致未处理的提交日志积压,这可能会影响生产数据库的运行状况。下一步是利用事件的并行处理来优化性能。
使用 Debezium 和 Kafka Connect 进行简化
我们最初将 Cassandra CDC 代理构建为独立项目。现在它作为Debezium连接器开源,我们可以用 Debezium 中的现有类替换一些自定义类。另一个改进是支持所有 Debezium 连接器都具有的通用功能,例如支持多种序列化格式。最后,CDC代理不具备容错能力;作为部署的一部分,需要强大的警报和监控。未来需要探索的一个领域是在 Kafka Connect 之上构建 CDC 代理作为源连接器,这进一步简化了 Cassandra 连接器与其他 Debezium 连接器的连接,并免费提供可扩展性和容错能力。
结束语
Cassandra 作为一种点对点分布式数据库,给 CDC 带来了一些非常有趣的挑战,这些挑战在 MySQL 和 Postgres 等关系数据库中,甚至在 MongoDB 等单主 NoSQL 数据库中都不存在。请注意,在为 Cassandra 推出您自己的实时数据管道之前,值得评估其限制。
除了了解 Cassandra 内部结构之外,我们还学到了一些有关工程生产力的经验教训:
最小可行产品理念
通过剥离除必需功能之外的所有功能,我们能够在合理的时间内利用有限的资源构建、测试和部署可行的解决方案。如果我们的目标是预先设计一个包含所有功能的管道,那么就会花费更长的时间并需要更多的资源。
社区参与
Cassandra 是一个开源项目。我们没有单独解决问题,而是从一开始就与 Cassandra 社区合作(即通过聚会与提交者和用户分享经验、在邮件列表中讨论提案、在会议中提出概念验证等);所有这些都为我们在整个设计和实施阶段提供了宝贵的反馈。