数据摄取
就像我们吃食物来获取能量一样,计算机系统“吃”或“摄取”数据来获取信息。
数据摄取系统是一个框架或一组流程,有助于将数据从不同来源传输到可以访问、使用和分析的存储介质。
数据采集
不同的数据来自不同的地方,比如数据库、网站,甚至智能设备。 我们将使用称为协议处理程序的东西来确保我们的系统可以与这些源“对话”而不会出现任何混淆。
对于预定的数据,例如抓取每日天气预报,我们会设置一个调度程序来完成这项工作。 对于实时内容,例如实时推文或即时更新,流处理器等工具就可以发挥作用。
现在,想象一下每个人都试图同时进入一个房间; 那就太混乱了。 数据也会发生同样的情况。 因此,当太多数据试图同时进入时,我们会使用反压(backpressure )策略来进行管理。
我们还要确保所有数据的传输和存储都安全。 这意味着它经过加密或编码以保持私密性和安全性,尤其是在移动时。
最后,我们会密切关注事情的进展。 使用监控工具,我们可以查看是否一切正常或是否存在任何问题。
协议处理程序
在计算中,协议定义了如何通过网络传输和接收数据的规则。 协议处理程序为特定类型的通信协议(例如用于 Web 流量的 HTTP 或用于文件传输的 FTP)解释和实现这些规则。 它们确保数据在不同系统或软件之间正确格式化、传输和理解。
调度程序
- 基于时间的调度:任务在特定时间或间隔运行。
- 事件驱动的调度:响应特定事件或触发器而启动的任务。
- 基于优先级的调度:任务按优先级排列,调度程序选择可用的最高优先级任务。
- 依赖性调度:根据一项或多项先前任务的完成情况或状态来调度任务。
Dependency Scheduling: Tasks are scheduled based on the completion or state of one or more preceding tasks.
流处理器
流处理器在数据到达时持续实时(或接近实时)处理和分析数据。
典型操作:转换、聚合、过滤、丰富(enrichment)。
鉴于流的连续性,数据通常被分为“窗口”进行分析。 这可以基于时间(例如每 10 秒)或事件计数(例如每 1,000 个事件)。
背压(Backpressure)
在数据处理和流媒体领域,背压(Backpressure)是一种机制,接收组件可以向其生产者发出有关其当前可用性的信号,确保数据发送的速度不会快于接收器可以处理的速度。 这对于维持系统稳定性和防止资源耗尽至关重要。
数据处理与转换
我们首先决定如何处理数据。 有时我们会一次性查看大块数据,我们称之为批处理。 其他时候,我们会在它进来时立即检查它,这称为流处理。
为了管理这些传入数据,特别是当数据量很大时,我们使用临时存储或“等待线”,数据可以在其中短暂暂停(we use a temporary storage or "waiting line" where data can briefly pause. )。 这种机制很有帮助,特别是当太多数据涌入太快时,让系统请求暂停或放慢速度。
有些任务需要我们记住以前的数据,这称为维护状态(which is called maintaining state)。 根据情况,我们的系统可能会使用过去的数据(有状态)或将每条数据视为全新的数据(无状态)。 对于有状态处理,定义状态至关重要
当我们处理数据时,我们经常需要调整或改变它以使其更有用,这个过程称为转换。 有时,这意味着向我们的数据添加更多详细信息,例如,如果我们知道某人的城市,我们可能会添加其人口 - 这称为丰富(enrichment)。 确保所有数据看起来和感觉一致也很重要,因此我们对其进行标准化或规范化(It's also essential to ensure all our data looks and feels consistent, so we standardize or normalize it.)。
当我们工作时,定期保存进度是一个好习惯。 这样,如果事情失控,我们就不必重做所有事情。 这种保存称为检查点(checkpointing)。
而且,为了确保顺利操作,我们设计的系统即使我们不小心重复某个操作,也不会导致问题。 这就是所谓的幂等性。
最后,当我们的系统采取行动时,我们确保它完全完成,或者如果出现问题,完全逆转,确保数据的完整性。 这就是所谓的原子性。
Lastly, when our system takes action, we make sure it’s either fully completed or, if there's a hiccup, fully reversed, ensuring the data's integrity. That's called atomicity.
有状态处理
有状态处理涉及系统保留上下文历史数据的能力。 首先确定要记住哪些信息以及将其存储在何处,可以是快速访问的内存存储(例如 RAM),还是更持久的解决方案(例如数据库)。 正确的状态管理需要初始化、更新并偶尔丢弃过时的信息。 可能存在的并发访问,通过锁等策略可确保数据一致性(With potential concurrent access, strategies like locks ensure data consistency.)。 随着系统规模的扩大,状态可能会分布在多台机器上,从而使分布式数据库或缓存变得有用。 为了实现弹性,系统可以保存定期“检查点”或维护数据副本。 可以通过缓存等技术来提高性能,同时安全性仍然至关重要。 定期监控确保系统的可靠性。
幂等性我们通过仔细设计 API 端点并利用唯一标识符来实现幂等性,确保重复的操作具有一致且可预测的结果。
原子性
- 事务:大多数数据库都支持事务,其中一系列操作被分组并作为一个单元执行。 如果事务中的任何操作失败,则整个事务将回滚到其初始状态。
- 两阶段提交:对于涉及多个数据库或服务的分布式系统,两阶段提交可确保它们之间的原子性。 首先,所有参与者“投票”是否可以提交。 如果所有人都投赞成票,则提交发生; 否则,它会被回滚(Two-Phase Commit: For distributed systems, where multiple databases or services are involved, a two-phase commit ensures atomicity across them all. First, all participants "vote" on whether they can commit. If all vote yes, a commit happens; otherwise, it's rolled back.)。
- 补偿事务:在长时间运行的流程中,立即回滚可能不可行。 相反,如果出现问题,则会执行补偿事务来抵消早期操作并使系统恢复到一致状态。
- 锁和并发控制:为了防止多个操作相互干扰,特别是在多用户系统中,请使用锁或其他并发控制机制。
数据存储
在存储数据时,我们首先需要了解其性质和访问模式。 对于结构化数据,例如具有定义字段的表(tables with defined fields),我们使用关系数据库,例如 MySQL 或 PostgreSQL。 如果我们的数据更灵活或更分层,像 MongoDB 或 Cassandra 这样的 NoSQL 数据库可能更合适(If our data is more flexible or hierarchical, NoSQL databases like MongoDB or Cassandra might be more suitable)。
我们的数据量也指导我们的选择。 如果我们正在研究需要分布式存储和快速处理的海量数据集,那么 Hadoop 的 HDFS 或 Google 的 Bigtable 等大数据解决方案就会发挥作用。 对于需要快速检索的临时或缓存数据,Redis 或 Memcached 等内存数据库是理想的选择。
当我们谈论数据的寿命时,备份就变得至关重要。 定期备份数据可确保在发生故障或损坏时,我们不会丢失关键信息。 这些备份可以是增量备份(仅保存更改),也可以是完整备份(复制整个数据集)。
数据安全至关重要。 因此,我们确保静态和传输过程中的加密。 加密会扰乱我们的数据,如果没有正确的解密密钥,数据将无法读取,从而防止未经授权的访问。
随着我们的数据增长或用户群在地理上变得更加多样化,我们可能会使用分片或复制。 分片将我们的数据库划分为更小、更易于管理的部分,而复制则创建数据的副本以提高访问速度和可靠性(As our data grows or our user base becomes more geographically diverse, we might use sharding or replication. Sharding divides our database into smaller, more manageable pieces, while replication creates copies of our data to improve access speed and reliability.)。
备份
备份是我们防止数据丢失的安全网(Backups are our safety net against data loss)。 通过定期在现场、异地或云平台上复制和存储我们的数据,我们确保始终能够恢复重要信息。 根据我们的需要,这些备份可以是完整的,其中复制所有数据,也可以是增量的,仅捕获自上次备份以来的更改。 这些备份的频率、方法和存储是根据数据的重要性和我们的恢复目标定制的。
分片和复制
为了处理大量数据或确保快速访问(无论地理位置如何),我们使用分片和复制等策略。 分片将我们的数据分成块,将它们分布在多个服务器上,确保我们的系统保持响应能力和可扩展性。 另一方面,复制涉及创建数据的副本。 这些副本可以服务读取请求、平衡负载,并且还可以在主数据源遇到问题时充当故障安全装置(and also act as a fail-safe in case the primary data source encounters issues)。
案例研究:具有运营管理的数据摄取管道 - Netflix
数据生成
Netflix 的媒体算法团队对媒体文件(例如电影或节目)运行算法。 这些算法分析内容并生成数据,例如识别视频中的对象。
数据存储
生成的数据(称为注释)被存入 Marken 系统。 Marken 使用数据库系统 Cassandra 以结构化方式存储这些注释(This generated data, referred to as annotations, is ingested into the Marken system. Marken stores these annotations in a structured manner using Cassandra, a database system.)。
数据更新
随着算法的改进或变化,它们可能会为相同的媒体文件生成新的或不同的数据。 这意味着系统需要摄取更新的数据并以不与以前的数据冲突的方式对其进行管理。 它不是直接更新注释(Instead of updating annotations directly),而是单独管理不同的注释集(或版本)(it manages different sets (or versions) of annotations separately)。 不直接更新先前运行的注释的方法可确保效率、维护历史数据并适应算法输出的不可预测性。
数据检索
ElasticSearch 是与 Cassandra 一起使用的另一个系统,有助于快速搜索和检索提取的数据。 这对于向 Netflix 用户提供实时推荐至关重要。
Marken架构
Marken 的架构旨在确保生成注释的团队或系统独立于使用这些注释的团队或系统进行操作(Marken's architecture is designed to ensure that the teams or systems producing annotations operate independently of the teams or systems using those annotations.)。
Marken如何区分它们(How Marken separates them):
- 不同的数据路径(Different Data Paths):生产者将数据放入Marken系统,消费者将数据取出。 他们使用单独的工具(API)来完成这些任务,因此不会互相干扰。这里应该就是用不同的api
- 版本处理:生产者可以添加新的数据版本,而不会弄乱旧的版本。 消费者始终会看到最新版本,而不必担心持续更新。
- 通过使用 ElasticSearch 进行搜索,消费者无需直接查询主存储 (Cassandra)。 这种分离可确保消费者的频繁搜索不会影响主数据库的性能或工作负载。