俄罗斯大叔的讲解比那套SD课程细很多,令人有打开新世界之感。觉得需要一套笔记记录之。

需求讨论关注:用户 规模 性能 开销

Users,  who and how will use the system.

总量?每小时统计?月度统计?(查询频率低)或者实时需求

Scale,  how our system will handle a growing amount of data.

每秒处理多少请求?每个请求查询多少数据?是否有忽增高峰期,多大?

Performance,   how fast our system must be.

- 如果不实时,批处理(慢)流处理都可以。
- 如果要求响应时间短,暗示数据必须事先计算好

cost,  budget constraints.

- 如果要开发成本小,就用好评的开源
- 如果要维护成本小,用云
  1. 需求讨论为了:定义功能性/非功能性需求

    功能需求:API

    (在白板上写)

    like 批处理事件,每个事件都是一个对象包括视频、事件类型、发生时间等信息。
    

    非功能需求:system qualities:fast, fault-tolerant, secure

    CAP 取舍

  2. high-level:需要一个db、一个web服务写入db、一个服务读db

    从简单的开始:data —— 存哪些 / 如何存

    如何存:

    两种方式:

    ① [批式]存原始数据,当场计算:费钱,读很慢。

    适用于不要求时延的

    ② [流式]聚合数据 :读的快,可实时决策。很难换方式,需要实现聚合管道,难修bug

    适用于时延低,需动态更新数据

    ③ 两者结合:原始数据存储一段时间就清除,并实时计算和存储数字

    可快速读取 + 以不同方式聚合数据

    但系统更复杂了

    存在哪:

    SQL & NoSQL :根据非功能需求:性能 可扩展性 可用性,来评估

    SQL: 数据规范化

    可能需要分区 → 引入轻量级代理服务器,可以查找正确db

    → 处理和查询都只与集群代理通信,代理需要知道分片的忙闲和分片增减

    →引入新组建:配置服务:维护检查所有分片

    ——— 解决了可扩展性和性能。

    但可用性:分片死了?丢了?

    → 复制数据 + 读写分离

    in all: 代理 + 配置服务 + 领导者 + 副本实例

    NoSQL: 非规范化数据

    无leader,不需要配置服务监控。允许分片间相互交互信息。

    一致性哈希来选择存储节点

    仲裁写入与仲裁读取。(> n/2 则通过)

    Cassandra:最终一致性 | 版本号判定时序

    nosql有四种类型:列、文档、键值、图形

    cassandra:异步无主复制、容错、可扩展、可以很好地处理时间序列数据

    mongoDB:面向文档,基于领导者复制

    HBase:面向列,类cassandra,也有基于leader的架构

    处理数据:

    like更新数据库中的计数器:

    ① 每来一个事件计数器就+1

    ②在内存里累积一段时间,再将累计值加至数据库计数器。(选这个)

    push & pull 都是对service来说的

    push: other service sends events to service

    pull: processing service pulls events from some temporary storage

    更好的容错和易扩展性

    因为可以当还没推给db时data丢失的情况下,可以再从临时存储中拉。

Untitled

  partition:processing service 从partition读取event,对内存中的event计数,并定期将计数值更入数据库。—— 需要一个组件component来读取event

partition consumer: 用户通过tcp连接来拿数据,无限轮询来拿,拿到了就str→object (deserializes)

deduplication cache: 如果是多线程拿取,这里需要去重。

like:使用分布式缓存来存唯一的事件标识符,比如10min。10min内有相同消息,则只会处理其中一条。

aggregator: 然后event到达内存开始计数,called 聚合器。底层是hash,定期计算data。计算的时候,该hash停止写入,并新建一个hash,用来累积新来的data,旧hash的数据旧传入internal queue

internal queue:将消费(consumption)和进程(processing)解耦decouple。(也可以将queue放在聚合器之前)

database write: 负责把数据写入数据库。单线程or多线程都可以。

dead letter queue:当消息无法路由到正确的目的地时,会发送到这个队列。保护性能,增强可用性。数据库变慢/下游降级也可以用。

另一个选项是,将未传递的消息存储在处理服务机器的本地磁盘上。

data enrichment:由于process中的事件只保存了最少量的信息like id,那么其它需要存的的信息,就放在这个embedded db嵌入式数据库里。这个嵌入数据库和处理服务在同一台机器上,方便快速检索。

state store:

数据在内存中待很久,或者很难现场重新计算时,

定期将整个内存的数据保存到持久存储中。

数据摄取管道 data ingestion path

用户打开video,request通过API 网关,路由到后端服务

分成三个部分:客户端、LB、分区服务

client:

IO:

client用套接字启动连接,给服务端发请求,服务端回应。

阻塞IO会产生大量线程处理请求,可能变慢甚至die,所以需要限速。

可以用非阻塞IO替代,which可以用单线程来处理多个并发连接,服务只是将请求排成队列,然后等会处理。

但是非阻塞IO很难debug

buffering and batching:

事件数量规模很大,不能单独传递,需要将事件组合在一起,就是批处理。

首先将事件放入buffer,等这批满了再传递。

增加了吞吐量、节省成本。但是如果个别出错,就很难挑出来。

timeout & retried:

两种超时:连接超时 (几十毫秒) | 请求超时

如果请求超时,就重试。但是要避免大量请求同时重试,或者重试太多次。

用 exponential backoff 指数退避 和jitter 抖动,增加重试间隔和随机性。

再用circuit breaker 断路器模式增加阈值,如果超过就停止。再过一段时间,尝试少量请求,如果成功就恢复。

Load Balancer:

两种:软件和硬件。硬件是买的网络设备。

另一个层面的LB是服务于TCP HTTP的流量

协议:

TCP的LB只转发(forward)包,不检查包内容

HTTP的LB会 查看消息包,并根据消息内容like cookies做出LB决策

算法:

轮询、LR、LF 、hash

DNS:

client如何知道LB?LB如何知道server?LB如何高可用?

DNS:在dns中注册服务,指定域名ip。

当customer点击域名时,请求被转发到LB。为了让LB了解server,需要明确告知LB每台server的IP。LB中提供API注册和注销server,并且知道哪些可用哪些不可用。

LB会定期ping 每台server,如果是坏的就停止发流量,直到它恢复。

高可用性:用一个辅助LB(和主LB位于不同的数据中心)

Partioner Service:

从客户端获取请求,检索事件,并路由到某个分区

partition获取message,用log形式存在disk。(有序的sort by time)

partition strategy:分区策略

hash(不适合大规模,会有热点)

——> 如何解决:用时间分区 | 直接拆分区by一致性哈希

service discovery:

两种发现模式:服务端发现 & 客户端发现

服务端发现:客户端知道lb,lb知道server

分区服务器和分区之间不需要LB,分区服务器自己就是个LB,来分发event给分区 ——— 客户端发现,每个服务器实例都会在服务注册中心注册。

服务注册中心:高可用web服务,可以健康检查。

客户端检查服务注册中心,得到可用服务器列表。like zookeeper

服务发现还可以做:节点之间互相通信。like cassandra。client只用联系其中一个节点,就能知道整个集群。

replication:

三种:单主复制(扩展DB)、多主复制(多个数据中心之间复制)和无主复制(cassandra)

如果只给leader写数据,如果没复制完之前leader就挂了,就会丢失数据。

如果等复制完成,就会增加延迟。

message format:

文本格式:xml,csv,json。人类可读

二进制格式:Thrift、Protocol Buffers 和 Avro。更快。用数字标签代替字段名称。

Data retrieval path 数据检索路径

client → API 网关 → 许多web service like 检索视频信息的、评论的、推荐的

→ db 从这里拿数据 → 检索时进行数据联合,可能调用多个存储,然后拼接数据 → 然后将结果放在cache

rollup data:将每分钟的计数存几天,然后将这些数据汇聚成每小时的数据,然后再存几个月,更旧的数据旧放在aws s3这种地方。

冷储存:不需快速访问。 热储存:常用数据。

data flow simulation

tecknology stack

netty:高性能的非阻塞IO框架,用于开发网络应用程序

Netflix 的 Hystrix /Polly : 简化了超时、重试、断路器模式

Citrix NetScaler: 著名的硬件负载均衡器

NGINX: 软件负载均衡器

Elastic Load Balancer:当计数系统运行在云中时用。

Kafka:不用自定义patitioner服务和分区

Amazon Kinesis:kafka的公共云对应物

Spark / Flink:流处理框架。处理事件并将它们聚合到内存中 或者用云Kinesis

Cassandra, HBase:存储时间序列数据。and InfluxDB

Hadoop / AWS Redshift : 存原始数据

AWS S3 :汇总数据并 归档

Vitess :用于扩展和管理大型 MySQL 实例集群的数据库解决方案

Redis:分布式缓存

RabbitMQ:死信队列机制 or Amazon SQS

RocksDB: 高性能嵌入式数据库,存本地富余信息

Zookeeper:分布式配置服务,进行分区的领导者选举和管理服务发现(or Eureka Web)

CloudWatch:云。监控每个系统设计组件 or 开源框架堆栈:Elasticsearch、Logstash、Kibana

MurmurHash:散列函数,用于Partitioner 服务对数据进行分区

瓶颈性能取舍

how to identify bottlenecks?

要识别瓶颈,需要在高负载下测试

几种性能测试:

负载测试:测量系统在特定预期负载下的行为

压力测试:超出正常运营能力时达到的临界点

找到breaking point:内存、CPU、网络、磁盘 IO

浸泡测试:长时间测试具有典型生产负载的系统

找到资源中的泄漏like 内存泄漏 leaks

可以用Apache JMeter等工具

how do you make sure the system is running healthy?

健康监测:

监控的四个黄金信号:延迟、流量、错误和饱和度 latency, traffic, errors, and saturation.

指标:衡量的变量,例如错误计数或处理时间

仪表板:提供服务核心指标的摘要视图

警报:针对服务中发生的某些问题而发送给服务所有者的通知

how to make sure the system produces accurate results?

构建审计系统

两种:weak strong

弱审计系统:一个持续运行的端到端测试。但不是100%可靠,尤其在长期运行中。

我们每分钟在系统中生成几个视频观看事件时,调用查询服务并验证返回值是否等于预期计数

强审核系统:使用与主系统完全不同的路径计算视频观看次数

like 将原始事件存储在 Hadoop 中并使用 MapReduce 对事件进行计数。然后比较两个系统的结果。

called Lambda Architecture:关键思想是将事件并行发送到批处理系统和流处理系统

如果我们对延迟不敏感,我们应该使用像 MapReduce 这样的批处理框架,如果是,我们应该使用流处理框架,但除非绝对必须,否则不要尝试同时进行两者

单点故障怎么办,处理速度跟不上怎么办

将事件批处理并存在对象存储服务中,例如 AWS S3。

每次持久化一批事件时,都会向消息代理发送一条消息,例如 SQS。

然后我们有一个大型机器集群,例如 EC2,从 SQS 检索消息,从 S3 读取相应批次的事件并处理每个事件。

这种方法比流处理慢一点,但比批处理快。

总结:

  1. 明确需求:定义 API, 系统到底应该做什么。

定义 API,我们与面试官讨论我们需要设计系统的哪些特定行为或功能。

写下函数定义,及输入参数和返回值。

可以进行多次迭代来更新 API。

  1. 讨论非功能性需求,并找出她最感兴趣的系统质量。

建议关注可扩展性、可用性和性能。

以及一致性、耐用性、可维护性和成本

尽量选择不超过 3 种

  1. 概述系统的高级架构,在白板上画出一些关键部件。

考虑数据如何进入系统、如何离开系统以及数据在系统内部的存储位置

  1. 深入研究其中的几个组件。面试官将帮助我们了解我们应该关注哪些组件。

设计特定组件时,从数据开始,它是如何存储、传输和处理的。

5.讨论瓶颈以及如何处理它们。