YouTube以两秒切片控带宽 架构设计视网络为最昂贵开销

[Chinese] Case Study: Design Youtube / Douyu / Twitch — Scott Shi

Scott Shi

视频系统架构的核心在于将上传流水线拆解为异步状态机并依赖边缘切片分发,因为网络带宽远比数据存储昂贵,无节制的预拉取将直接压垮源站。

AI-assisted summary of [Chinese] Case Study: Design Youtube / Douyu / Twitch — original source. Check the original for full context.

Source published:

Key ideas

  • 关注点分离是设计超大规模视频平台的核心哲学,系统应拆分为视频上传与离线处理、社区与用户画像、推荐与热点系统、实时直播与弹幕流四大解耦子系统,大幅降低架构复杂度。 (10:48)
  • 网络带宽是系统设计中最昂贵且稀缺的物理资源,YouTube 激进采用 2 秒极短切片配合高压缩编码,相较 Twitch 的 90 秒长切片可显著减少跳出用户的带宽浪费并提升首屏响应速度。 (30:00)
  • 严禁在视频上传中使用跨存储的单一原子事务;工程上必须采用显式状态机(New → Uploaded → Available)与 Kafka 轻量指令解耦 S3 物理写入与异步转码后处理工作流。 (20:00)
  • 点赞与播放量等高频行为属于容忍微量丢失的非事务型数据,架构应通过 Redis 承接高并发内存自增,再通过异步批处理定期回写持久化数据库,避免单行高频更新锁死数据库。 (55:00)

Detailed notes

## Background 该视频由 Scott Shi 于 2020 年 11 月 17 日在 YouTube 平台发布。视频简介说明本次研讨旨在深入探索超大规模视频平台(如 YouTube、斗鱼及 Twitch)的系统设计,并附有配套的设计参考文档。

## TL;DR 本次分享将复杂的视频系统严格拆解为四大独立模块:视频上传与异步转码切片流水线、高并发社区与元数据服务、个性化推荐引擎以及实时直播与弹幕系统。主讲人深入剖析了 YouTube 的 2 秒切片与客户端 Buffer 调控机制,确立了“网络带宽永远是系统设计中最昂贵资源”的工程哲学,并强调避免在大文件上传中采用跨系统分布式事务,应采用轻量状态机驱动异步管线。针对社区与直播场景,方案探讨了借助 Kafka 异步日志结合 Redis 计数器抗击播放点赞洪峰、基于 DynamoDB 的评论分片与局部索引设计,以及利用 Flink 滚动窗口与 CDN 链表指针实现低延迟直播与弹幕对齐的完整架构落地路径。

## Atmosphere & style 整场研讨散发着浓郁的工程师技术沙龙与实战答疑氛围,讲师风格平实稳健、直击本质,充满对工业界反模式与技术直觉的务实评判。互动环节中听众针对主键设计与 S3 状态流转频频发问,讲师不仅乐于接受现场纠错与方案重构,还坦诚指出自己在推荐算法生产经验上的局限,毫无居高临下的说教感。整个分享在硬核推导底层网络协议与存储 Schema 的同时,始终贯穿着“以低成本实现从 0 到 90 分”的商业化工程思维,节奏紧凑而充满真诚探讨的温度。

## Bulletin - [10:48](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=648s) 关注点分离是设计超大规模视频平台的核心哲学,系统应拆分为视频上传与离线处理、社区与用户画像、推荐与热点系统、实时直播与弹幕流四大解耦子系统,大幅降低架构复杂度。 - [30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1800s) 网络带宽是系统设计中最昂贵且稀缺的物理资源,YouTube 激进采用 2 秒极短切片配合高压缩编码,相较 Twitch 的 90 秒长切片可显著减少跳出用户的带宽浪费并提升首屏响应速度。 - [20:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1200s) 严禁在视频上传中使用跨存储的单一原子事务;工程上必须采用显式状态机(New → Uploaded → Available)与 Kafka 轻量指令解耦 S3 物理写入与异步转码后处理工作流。 - [55:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3300s) 点赞与播放量等高频行为属于容忍微量丢失的非事务型数据,架构应通过 Redis 承接高并发内存自增,再通过异步批处理定期回写持久化数据库,避免单行高频更新锁死数据库。

## Key takeaways - [00:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=0s) CDN 边缘节点作为视频架构的关键缓冲层,不仅大幅平抑回源带宽成本,更将冷数据读取延迟从 S3 的约 500ms 压缩至边缘节点的 50ms 以内(P90/P95 指标)。 - [03:44](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=224s) 大文件上传应采用开源的 tus 协议或断点续传协议,支持网络中断后的分块校验与继续上传,避免传输中断后全量重传。 - [07:22](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=442s) 在容量与吞吐量估算中,CDN 边缘缓存可消化 90% 以上的读请求,使得系统未缓存状态下的 1:200 读写比在回源到源站时收敛至 1:20 甚至 1:5。 - [13:17](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=797s) 视频上传必须实现数据与元数据物理分离:原始视频大文件直接流式写入 S3 等对象存储,轻量结构化元数据存入关系型数据库,完成后再触发异步转码流水线。 - [15:42](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=942s) YouTube 播放器根据本地维持的约 80 秒 Buffer Health 水位动态发起 2 秒切片的 HTTP Range 请求,进度条拖动则由 Video Mapping Service 将播放百分比精准换算为切片 offset。 - [25:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1500s) 视频切片索引表的全局唯一主键必须由 video_id + clip_id + resolution 联合构成,以支撑同一视频在多种分辨率与不同分段下的唯一定位。 - [30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1800s) 服务端必须针对各主流分辨率预先完成压缩转码和独立存储,严禁向低清播放端统一下发 1080p 并在客户端降码,否则会导致公网带宽被极度挥霍。 - [45:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2700s) 点播切片映射具备不可变性,可直接打包为单行 JSON 字段存储;而直播场景切片持续动态追加,必须进行规范化独立建表,避免单行记录被反复 UPDATE 产生系统反模式。 - [45:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2700s) 互联网流媒体平台除法律法规强制要求外一律采用软删除(Soft Delete),删除操作需经过 delete_pending 状态异步清理 Elasticsearch 倒排索引及关联引用。 - [55:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3300s) 全平台 99% 的流量往往属于轻量级用户行为日志,统一输入 Kafka 后可扇出至更新个人历史记录的 History Service 与累加热度的 Popularity Service。 - [01:00:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3600s) 应对 Read-After-Write 一致性延迟,可在客户端内存中将本地最新操作与远端历史做临时合并,或在服务端将已持久化数据与 Kafka 增量日志实时归并读取。 - [01:03:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3780s) 评论系统极度契合 DynamoDB 架构:以 videoId 为 Partition Key,以雪花算法或 ULID 生成的 commentId 为 Sort Key,并通过 Local Secondary Index 快速拉取父子回复楼层。 - [01:15:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=4500s) 推荐系统的计算本质上是用户兴趣偏好向量与候选视频标签得分的线性点积,配合时间衰减机制与协同过滤,能以极高性价比在工业界完成 0 到 90 分的高效落地。 - [01:30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=5400s) 直播传输中斗鱼通过在当前切片中附带下一片段的 Next Pointer,引导客户端直接向 CDN 轮询拉取下一段切片,从而彻底卸载主服务器的寻址压力。 - [01:30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=5400s) 利用 Apache Flink 针对用户行为日志流维护 24 小时滚动窗口,即可通过有状态流计算实时统计观看与点赞指标,以极简逻辑驱动微博热搜或热门直播榜单。

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=0s) 系统需求与 CDN 边缘加速的核心价值

在设计类似 YouTube、TikTok 或 Twitch 这种超大规模视频平台时,首先需要拆解核心功能与非功能性指标。以 YouTube 为例,核心功能聚焦在视频上传、转码处理以及播放观看;而扩展的 Bonus 功能则涵盖热门频道、订阅机制、Trending 趋势榜单、个性化推荐以及实时弹幕(Live Chat)。在服务质量(SLA)要求上,系统必须具备极高的一致性与可靠性——用户的每一次视频上传绝不能丢失,尤其是接口返回“上传成功”后,数据必须持久稳固;同时整体架构要保证高可用与低延迟,点播需要秒开,直播更要求毫秒级的实时体验。

为了达成低延迟和减少源站带宽压力的目标,CDN(内容分发网络)在视频流媒体架构中扮演着生死攸关的角色。若没有 CDN,全球用户都必须直接访问部署在主区域(如美西)的源站服务器(Origin Server),跨国链路不仅延迟极高,而且昂贵的跨地域公网带宽成本会直接压垮企业。通过在加拿大、中国、印度及欧美各地部署 CDN 边缘节点,大体积的静态资源(如图片封面、切片视频)可以直接缓存在离用户最近的边缘服务器中:

- **大幅削减带宽成本**:数以万计的并发请求在边缘节点直接命中缓存,只有第一次未命中或文件过期时才会回源请求源站。 - **提升可用性与网站安全**:CDN 自带抗 DDoS 攻击与流量清洗能力,结合合理的 TTL(Time-To-Live)缓存失效策略,有效平抑流量洪峰。 - **显著改善首屏加载体验**:直接从 Amazon S3 读取冷数据的延迟通常在 500ms 左右,而 CDN 边缘节点的读取延迟在 P90、P95 指标下可以轻松压缩至 50ms 以内,用户几乎感受不到白屏等待。 - **配置与使用简便**:接入 CDN 在工程上非常直观,通常只需在 DNS 和资源路径上做一层映射配置,例如将原始域名 `myspace.com/image1` 改写为 CDN 域名 `cdn.myspace.com/image1`,剩下的缓存分发逻辑交由 CDN 厂商处理。

---

[03:44](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=224s) 各大视频平台分片机制与 tus 上传协议

各大头部流媒体公司在 CDN 与视频切片上的具体实现各有千秋。像 Cloudflare 这类行业领先的 CDN 供应商,如今已经不仅局限于静态资源缓存,而是对外提供完整的全托管视频流媒体服务(Cloudflare Stream API),原生支持视频转码切片、推流拉流、订阅管理以及自动生成字幕等功能。

深入对比 Twitch、斗鱼和 YouTube 在浏览器端的加载机制,可以发现它们截然不同的工程取舍: 1. **Twitch**:采用标准的 HLS 协议(.m3u8 索引),将视频切分成大约 30 秒一个片段,单个分片大小被压缩至仅约 20KB,这种轻量级切片极大降低了播放缓冲开销。 2. **斗鱼(Douyu)**:采用持续的流式传输文件,吞吐速率大约维持在 500KB/s 上下,用户端一边拉取切片一边解码播放。 3. **YouTube**:YouTube 的切片策略极其激进,客户端抓包可以看到它被切成了极短的 2 秒切片(2-second clips),并采用先进的高压缩比编码格式(如 AV01 / AV1 编解码器)。用户端根据当前的 IP 地址、网速和时间戳,动态拉取对应分辨率的 2 秒编码文件。

如果想要快速从零搭建一个类似斗鱼的直播/点播系统,直接调用 Cloudflare API 是一种最高效的实践途径。开发者只需注册配置自己的域名(例如 `douyu.com`),通过标准 API 即可列举视频库并完成推流。在文件上传协议上,Cloudflare 和现代视频系统广泛采用了新兴的开放协议 **tus(tus protocol)**。这是一个专门针对大文件断点续传(resumable file uploads)制定的开源通信协议。传统 HTTP 上传如果遭遇网络中断,用户只能全部推倒重来;而 tus 协议不限制文件大小,原生支持分块、暂停与断点续传,同时还能伴随音轨上传字幕文件,是现代视频基建的最佳搭档。

---

[07:22](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=442s) CDN 缓存原理与容量估算 (Back-of-the-Envelope)

针对现场同学提出的疑问——“CDN 节点是否需要与源站的数据库(DB)进行实时同步”,这里存在一个概念误区:CDN 节点本质上只是分布式文件缓存系统,并不承载核心业务数据库。CDN 内部维护的是热点视频分片和高频资源的内存(Memory)与高速固态盘映射,根本不需要考虑传统数据库的数据同步问题。

从物理硬件性能来看,如果直接从磁盘中读取 100MB 的视频文件,磁盘寻道与 I/O 带来的 Overhead 往往需要数秒;而 CDN 依靠全球边缘节点的内存缓存(In-Memory Cache),能将 P95 或 P99 响应时间压至 50ms 级别。这就是为什么 CDN 是视频点播架构的标准解法——它像一道巨大的边缘缓冲墙,隔绝了海量读请求对后端数据库与对象存储的冲击。当然,即使完全脱离 CDN,系统在架构上也能运行,只是用户体验和源站负载将面临灾难性挑战。

在系统设计面试中,容量与吞吐量的粗略估算(Back-of-the-Envelope Estimation)至关重要。参考 *Grokking the System Design Interview* 的典型数据推导: - **读并发(View QPS)**:假设系统每秒承受约 46,000 次视频播放请求(46k views/sec)。 - **写并发(Upload QPS)**:系统预期每秒约 230 次上传,为了面试方便心算,可以四舍五入估算为 1,000 video uploads/sec。 - **带宽吞吐**:源站每秒需要处理的上传流吞吐量在 25GB/s 到 100GB/s 之间。 - **读写比(Upload to View Ratio)**:在没有缓存拦截的极端情况下,读写比例约为 1:200。但一旦引入 CDN 边缘缓存,90% 以上的请求在边缘直接被消化,回源请求的读写比会大幅收敛到 1:20、甚至 1:4 至 1:5。

面试官看重的不是精确的小数点,而是候选人是否具备 Scale 的工程直觉。面对 1 GB/min 与 500 GB/min 的系统规模,底层的分片(Sharding)策略与架构选型是截然不同的。

---

[10:48](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=648s) 系统拆分:YouTube 的四大核心模块

由于 YouTube 架构过于庞杂,如果在面试中试图一把抓,整个讨论很容易陷入失控的泥潭。遵循“关注点分离”(Separation of Concerns)原则,可以将复杂的 YouTube 业务清晰地拆解为四大相互独立的子系统:

1. **视频上传、处理与播放流水线(Video Upload, Process & View)**:核心主链路。覆盖视频创作者(Producer)上传源视频、生成缩略图(Thumbnail)、设置标题标签,以及最终供播放端调取的全过程。 2. **元数据管理系统(Metadata Management)**:纯业务数据维度。维护用户信息、用户画像、播放量(View Count)、点赞数(Likes)、观看历史(Watching History)、评论互动(Comments)以及频道订阅关注关系。 3. **实时流媒体与互动系统(Streaming & Real-time)**:涵盖 YouTube Live 直播流、实时趋势榜单(Trending Topics),以及高并发弹幕系统(Live Chat)。正如弹幕的直观形态——在直播或讨论时,所有在线观众发送的文本以一行行文字的形式实时横跨屏幕飘过。 4. **个性化推荐引擎(Video Recommendation)**:依托海量用户画像与历史观影习惯,执行实时机器学习召回与精排,为用户首页精准推送感兴趣的个性化视频。

将这四个模块解耦后,不仅系统边界清晰,而且每个模块的技术选型都可以独立演进,大幅降低了整体架构的设计复杂度。

---

[13:17](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=797s) 视频上传处理流水线与异步解耦设计

聚焦于核心的“视频上传与处理”链路,系统必须承载重型的多媒体转码与安全合规管线。当创作者上传视频时,请求首先抵达 `Video Upload Service`,随后触发两套并行的处理机制:元数据写入与视频物理落地。

元数据(如视频标题、描述、上传者 ID、基础规格等)体量极小且结构明确,应直接存入关系型数据库(如 SQL 数据库)中;而原始大文件视频(Raw Video,格式多为 MP4、AVI)则必须直接流式写入专用的分布式对象存储(如 Amazon S3)。一旦原始文件与基础元数据写入完毕,服务端即可率先响应客户端“上传完成”,紧接着唤起底层的异步转码与后处理流水线(Asynchronous Post-Processing):

```mermaid flowchart TD accTitle: Video Upload and Processing Pipeline accDescr: Architectural flowchart showing video upload ingestion, storage, async workers for safety, transcoding, and indexing into search and CDN.

subgraph INGEST["接入与初始存储 (Ingestion)"] U["Uploader (创作者客户端)"] -->|1. 上传视频与元数据| VUS["Video Upload Service"] VUS -->|2. 写入元数据| SQL[("SQL Database")] VUS -->|3. 存储 Raw 视频| S3[("Amazon S3 Object Storage")] VUS -.->|4. 返回接收成功| U end

subgraph ASYNC["异步后处理工作流 (Async Workers)"] S3 --> W["Async Post-Processor"] W -->|合规风控审核| SAFE["Safety Check (暴力/血腥检测/人工抽检)"] W -->|封面与预览生成| THUMB["Generate Thumbnails & Hover Preview"] W -->|转码与2秒切片| ENCODE["Compress & Transcode (1080P/720P/AV01) -> Chop 2s Clips"] end

subgraph SERVE["分发与检索 (Serving & Discovery)"] ENCODE --> CDN["CDN Edge Nodes (Buffer & Cache)"] W -->|同步视频索引| ES[("Elasticsearch (Video Search Service)")] CLIENT["Viewer Client"] -->|检索关键词| ES CLIENT -->|拉取2秒切片播放| CDN end ```

在后处理工作流中,包含多项核心任务: - **安全合规过滤(Safety & Content Moderation)**:检测视频是否涉及暴力、血腥或违规内容,结合算法机器初审与人工复审剔除违规视频。 - **缩略图与微预览生成(Thumbnails & Previews)**:若用户未指定封面图,异步服务自动提取关键帧生成 Thumbnail;同时生成一段极短的小尺寸动图预览(Hover Preview),供用户鼠标悬停时快速预览内容。 - **多码率转码与 2 秒切片(Transcoding & Chopping)**:将单一格式的原始视频压缩转码为多种主流分辨率(1080P、720P、360P、240P 等),并利用 YouTube 风格的切片机制,切成一个个长约 2 秒的小文件片(2-second clips),持久化存储回 S3 并预热推向 CDN 边缘节点。 - **搜索引擎同步(Search Indexing)**:将视频标题、标签及元数据同步推入 Elasticsearch,确保前台搜索功能能即时检索到最新上架的视频。

---

[15:42](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=942s) 客户端 Buffer 机制与上传状态机设计

针对现场关于底层切片与并发控制的深度提问,讲师剖析了 YouTube 播放器内部的“Buffer Health”调控逻辑。用户在 YouTube 播放器中开启“专业统计信息”(Stats for Nerds)时,会看到一项名为 `Buffer Health` 的监控指标(例如显示 79 秒)。这个数值与用户正在观看的整段视频总时长无关,而是指当前客户端本地内存中预缓存的媒体切片裕量。

播放器内部维护着严格的高低水位阈值:当网络状况良好且本地 `Buffer Health` 高于安全阈值时,播放器暂停向 CDN 发起拉流;一旦本地缓冲区消耗低于阈值,播放器会以 2 秒为一个单位,持续向 CDN 发送 HTTP Range 请求获取下一个 2 秒切片,动态将本地缓冲维持在一个稳定的时间区间内。这种极短切片的设计不仅让用户在任意拖拽进度条时可以极速定位起播,而且如果用户中途放弃观看,也不会浪费过多未播放片段的下行带宽。

``` [播放器本地缓冲] ===== 已缓存切片 (~79s) ===== [播放游标 ▶] │ ▼ (低于安全水位时) [向 CDN 请求] ──> [拉取下一个 2 秒 Clip] ──> [动态维持 Buffer Health] ```

针对断网续传以及系统间事务一致性(Consistency)的棘手问题,架构设计必须确立清晰的边界: - **网络中断断点续传**:如果用户在上传几个 G 的大视频时刷新页面或遇到网络波动,现代传输协议(如标准的 FTP 断点方案或最新的 tus 协议)完全支持校验已上传 Offset,无需从头重传。 - **绝不能将 SQL、S3 与 Thumbnail 包装在单一分布式事务中**:有学员提问“上传 S3 失败怎么办?SQL 写入、S3 落地和缩略图生成三者是否需要 Atomic 事务保证强一致?”答案是绝对不能。视频上传到 S3 往往耗时巨大,从几分钟到长达一个小时都有可能,在分布式系统中长时间持有本地数据库事务或跨系统两阶段提交(2PC)会直接导致连接池枯竭与雪崩。 - **显式状态机设计(State Machine)**:应对此场景的标准实践是为视频元数据定义一套轻量的状态跃迁机制,如 `New`(已创建) $\to$ `Uploaded`(原始文件已落地) $\to$ `Processing`(转码与后处理中) $\to$ `Available`(已就绪发布)或 `Failed`(上传处理失败)。每一步处理都是幂等且异步驱动的,通过状态轮询或事件通知解耦,系统得以在高吞吐环境下保持强劲的韧性。

[20:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1200s) 状态机事务设计与 API / 搜索与切片机制

在视频上传系统设计中,状态流转(State Machine)扮演着将庞大流程拆解为异步事务的核心角色。当用户发起上传时,系统先标记为 `new`,上传成功后再变更为 `uploaded`。Scott 严肃警告,切忌把“视频上传到 S3”、“元数据入库”以及“生成预览缩略图”打包在同一个原子事务中,这种做法是面试中的“非常非常 red flag 的 design”,因为跨网络且耗时极长的事务体量太大,失败概率极高。他类比了支付系统的经典架构:用户转账时,绝不能把“扣减付款方资金”和“向收款方入账”绑定为单个事务,而应先扣减付款方并转入中介账户(例如 Visa 渠道),记录状态为已扣款,随后通过异步重试机制不断尝试转账给收款方,配合异常补偿逻辑,否则整体系统的吞吐量和稳定性会非常低下。

```mermaid flowchart LR accTitle: Asynchronous Video Processing Flow accDescr: Video upload decouples file upload from thumbnail generation via S3 and Kafka.

subgraph ClientAndUpload["客户端与上传服务"] Client["客户端 Client"] UploadSvc["上传服务 Video Upload"] end

subgraph StorageQueue["存储与消息"] S3Raw["Amazon S3 (原始视频)"] MQ["Kafka (轻量 Command 指令)"] end

subgraph WorkerPool["处理服务"] ProcSvc["视频处理服务 Video Processing"] S3Thumb["Amazon S3 (切片 / 缩略图)"] end

Client -- "1. 上传元数据 + 建立连接" --> UploadSvc UploadSvc -- "2. 分块写入" --> S3Raw UploadSvc -- "3. 发送 Action 消息" --> MQ MQ -- "4. 消费小指令" --> ProcSvc ProcSvc -- "5. 读取原始视频" --> S3Raw ProcSvc -- "6. 写入目标切片/预览图" --> S3Thumb ```

随后讨论了具体的 API 设计与客户端切片逻辑: - `uploadVideo` API:接收 `dev_key` 或 `user_token`、`video_title`、`video_description`、`tags`、`category_id`、`default_language`、`recording_details` 和 `video_content`(指向本地文件路径)。底层建立 WebSocket,使用可断点复传的传输协议(Reusable File Transfer Protocol)将文件分块上传。 - `searchVideo` API:传入 `search_query`、`user_location`、`max_video_to_return` 及 `page_token` 实现分页,支持元数据过滤(如时长限制在 20 分钟以内)与标题/类别搜索。 - `getVideo` API:视频由离散的小片段(Clips)组成,请求参数由 `video_id` 与 `offset` 决定。若以 2 秒为一个 Clip,`offset=10` 即代表第 20 秒起始的视频片段。通常短视频约包含 150 个 Clips,而两小时的长视频约切分为 3600 个 Clips。切片时长取决于业务场景,YouTube 观察为 2 秒左右,而 Twitch 或采用 90 秒,只要切片适中合理即可。 - 消息队列(Message Queue)规范:针对李志文同学的提问,Scott 澄清 Kafka 消息中**绝不能塞入视频本身**,必须仅传递轻量级元数据与控制指令(类似命令行 Action,包含原始视频 S3 URL、目标缩略图 S3 Target URL、操作类型等)。Kafka 消息体通常严格限制在极其小额的级别(例如不超过 1 MB),否则系统性能会彻底崩溃。

---

[25:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1500s) 存储 Schema 纠错、S3 传完判定与主键定义

进入内部存储模式讨论,Scott 原本提出的视频切片存储字段包含 `video_id`、`clip_id`、`owner_name`、`timestamp`、`offset` 及 `next_clip`。其中 `next_clip` 借鉴了斗鱼的链表设计思想——客户端播放当前片段时,能直接根据下一节点的索引连续拉取,避免反复向斗鱼的核心元数据服务发起请求。

面对欣杨提问“视频上传后还能编辑视频本身吗”,Scott 指出:任何剪辑或清晰度转码(如 1080p 与 720p),在底层系统视角中都是完全独立的两个文件资源,仅靠元数据在逻辑层面做关联。至于“处理服务如何感知 S3 传完视频”,不需要低效轮询(Polling)数据库;因为客户端与上传服务存在长连接(Live Connection)甚至专属数据流通道,网络流遇到 EOF(End-of-File)或触发文件关闭事件(File Close),系统立即确切知悉文件已传输完毕。

雨泉等同学在讨论区敏锐指出设计缺陷:若按原 Schema,同一个 `video_id` 会出现成百上千行,主键设计存在问题。Scott 欣然采纳并纠正了方案: - 唯一主键(Primary Key)绝非单独的 `video_id`,必须由 `video_id + clip_id + resolution` 联合构成,以确保清晰度、切片编号和视频全局的全局唯一性。 - 视频切片本身存放在 Amazon S3,所谓的表格可以是关系型数据库(如 SQL)记录索引指向 S3 Object URL,也可以直接将包含切片信息的 JSON 配置文件与视频数据块作为 Object 一同存入 S3。 - 至于有了 `clip_id` 为何还保留 `offset`,虽然 `clip_id` 能标识切片,但 `offset` 能直观表示当前片段所处的播放时间轴(例如累计播放到 240 秒);不过在引入专门的 Video Mapping Service 后,`offset` 即可由映射层直接计算。

---

[30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1800s) 网络是系统设计中最贵的资源:进度条拖动与协议选型

讨论深入到存储与系统成本权衡。有人询问是否需要将所有切片表直接塞进 SQL,Scott 澄清具体的海量媒体二进制切片肯定存放在 Amazon S3,数据库只保存精炼的元数据索引映射。针对“不同清晰度是否需要各存一份副本”的问题,Scott 给出了系统设计中的核心哲学定论:“在系统设计中,最珍贵的资源永远是 Network,Network 最 expensive,Storage 不是非常 expensive。”

从技术上讲,系统无法将低分辨率凭空还原为高分辨率,但完全能够实时把 1080p 降码为 720p。然而,若不管用户端播放 360p 还是 240p,服务端均一律下发 1080p 原始视频并让客户端本地降码,在架构上是灾难性的,因为公网带宽被极度挥霍。

关于“用户在进度条上随意拖拽到任意一秒是如何实现的”: - 核心依赖前端与后端映射服务(Video Mapping Service)联动。 - 前端将用户的进度条点击位置转化为百分比,再由总时长计算出目标秒数时间戳,进一步换算为 `offset`。 - 系统根据 `video_id + offset` 精确命中目标切片并立即加载,完成平滑跳转。

对于网络协议选型,欣王提问系统设计中是否默认所有视频都用 UDP。Scott 分析了不同业务形态的区别: - 像 Zoom、电话会议或普通低延迟直播等追求实时性、允许丢包的场景,采用 UDP 更加合适。 - 像 YouTube 这一类点播平台,用户体验建立在画面无损且连贯的基础上,绝对不希望出现任何丢失分包(Packet Loss)导致的画面花屏或撕裂,必须采用 TCP 进行可靠传输。 - 整个 YouTube / 斗鱼这类庞大系统必须遵循“关注点分离”(Separation of Concerns),整体可划分为四大核心领域: 1. 视频上传与后台处理(Video Upload & Processing); 2. 社区与社交互动(YouTube Community); 3. 智能推荐系统(Recommendation System); 4. 直播与实时推拉流(Streaming)。

---

[35:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2100s) 切片粒度取舍(YouTube vs Twitch)与 Elasticsearch 词袋构建

针对切片传输与缓冲机制,客户端并非一次性接收整部影片,而是每次拉取一个独立的短切片(例如 2 秒)。客户端本地会维护一个流媒体缓冲区(Buffer),通常维持在 80 秒左右的缓冲空间,随着播放持续按需请求新片段,如果缓冲区水位低于阈值则迅速补拉。

针对长视频拥有 3600 个片段是否导致记录过多的疑虑,Scott 深入探讨了切片长度(Chunk / Clip Lens)的商业与架构权衡:

| 平台 | 切片长度 (Clip Length) | 业务考量与用户行为模式 (Access Pattern) | 传输特征 | |:--- |:--- |:--- |:--- | | **YouTube** | 约 2 秒 | 极端碎片化,用户常因跳出或划走仅看几秒,短切片能显著提升带宽有效利用率(Video Utilization Rate),避免 90% 以上预拉取流量白白浪费。 | 细粒度、低突发、渐进式拉取 | | **Twitch** | 近 90~100 秒 | 包含直播与长录播属性,用户粘性极强,点进直播间后通常连续停留数分钟乃至数小时。 | 突发传输(Burst Transfer),减少高频网络握手 |

两家巨头的切片时长整整相差了 50 倍(两个数量级),这充分说明系统架构参数的选型并非凭空设定,而是必须贴合用户访问模式进行精细优化。

最后,Scott 展开了 Elasticsearch 检索索引的搭建方案。当视频上传成功后,系统会搜集多维度文本信息:作者填写的 Video Title、Label/Tags,以及借助自然语言处理(NLP)和语音识别技术从音轨中提取生成的字幕文本。文本处理模块会将文章和字幕拆解解析,统计每个词汇出现的频次(例如某个关键词出现了 15 次),将其降维构建为“词袋”(Bag of words),以此为基础录入倒排索引,驱动高并发的全文检索。

[40:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2400s) 视频文本化、倒排索引与 BM25 检索

在视频搜索的核心思路上,视频可以通过语音识别(ASR)转录(transcript)、标题、标签等文本信号转化成文章或网页形式,进而利用经典的倒排索引(Inverted Index)进行检索。倒排索引记录了词(word/term)与包含该词的资源(如视频或文档)之间的映射。

在文本相关度打分方面,主讲人提到了经典启发式函数 BM25。该算法虽然诞生了几十年,但至今依然是文本检索领域的 state-of-the-art。其核心逻辑是将视频的文本信息(语料库)提取为特征向量(vector),通过启发式函数计算搜索 query(如 "system design")与视频特征的相关度得分(relevance score),分数越高代表匹配度越好,并可叠加时长、上传时间等过滤条件:

- **特征匹配举例**:如果视频讨论的是系统设计,其特征就是 "system design";若讨论政治热点(如特朗普、约翰·博尔顿相关的事件),其特征关键词就是 "Trump"、"John Bolton"。 - **文本数据体量轶事**:主讲人回忆起 2013 年在 UIUC 上翟成祥(ChengXiang Zhai)老师的《Text Information Systems》课程时的经历。当时整部英文维基百科(English Wikipedia)下载下来只有约 9GB(如今 7~8 年过去也才涨到 13~14GB 左右)。 - **数据增长的对比**:虽然互联网多媒体(音频、视频)呈现指数级爆发(每两三年翻倍),但纯文本词汇和语法相对固定,整个英文维基百科压缩后仅 10GB 左右。翟老师的课上曾有一个非常有趣的作业和竞赛:花 15 分钟写一个类似 Google 的微型搜索引擎,并比拼检索准确率。

---

[45:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2700s) 视频元数据表设计与复杂的删除流程(Soft Delete vs Hard Delete)

对于视频元数据(Video Metadata),主讲人采用了一张常规的关系型数据库表(MySQL / Relational DB)来管理核心信息,并重点剖析了视频切片映射(clip mapping)与状态机(state machine)的流转:

```mermaid flowchart LR accTitle: Video State Machine accDescr: 视频上传处理到删除的生命周期状态流转图

A["New (创建记录)"] --> B["Uploaded (文件上传完成)"] B --> C["Available (处理/审核完毕)"] C --> D["Delete Pending (触发删除)"] D --> E["Deleted (全局索引与引用清理完毕)"] ```

#### 1. 视频元数据与切片映射 - **核心字段**:包含 `user_id`、`timestamp`(上传时间)、`title`、`description`、`total_length`、`thumbnail_uid`、`preview_uid`、`sharing_rules` 和 `state`。 - **Video Clip Mapping**:例如 offset 0 对应哪个 clip UID,offset 1 对应哪个 clip UID。前端根据用户拖动进度条的位置结合 `total_length` 计算出 offset,继而根据 `video_id` + `clip_id`(可能附带分辨率 resolution)定位真实的切片文件。 - **点播与直播的存储差异**: - *点播(VOD)*:视频上传切片后具有不可变性(immutable),整个 clip mapping 可以直接作为一个字段(如 JSON)保存在同一行 row 中。 - *直播(Live Streaming)*:数据流会不断动态追加(append)新的 clip。如果每次生成 clip 都去反复 update 同一行记录,是极其恶劣的系统反模式(fundamentally bad system design)。因此直播场景必须对 clip 进行规范化拆分(normalize),独立建表存储。

#### 2. 状态机与复杂的删除流程(Delete Process) 视频生命周期经历 `new` $\to$ `uploaded` $\to$ `available`(完成缩略图、预览图生成及暴力合规审查)$\to$ `delete_pending` $\to$ `deleted`。 - **为什么需要 `delete_pending`**:删除一个视频是极其繁复的级联操作。不仅需要撤回文件访问权限,还必须同步从 Elasticsearch 等搜索引擎的倒排索引中剔除。在异步清理未完全闭环前,必须置为 pending 状态。 - **互联网公司不做硬删除**:除法律法规强行要求外,现代互联网系统几乎**一律采用软删除(soft delete)**。数据是互联网公司最宝贵的核心资产,一旦物理删除便永久丢失;而且用户数据在系统中往往存在大量副本和引用。

---

[50:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3000s) 视频去重、S3 映射优化与冷热分级存储

针对互动区王兆宇和静怡等观众提出的技术细节,主讲人进行了逐一解答与拓展:

- **视频去重(Deduplication)**:视频去重在实际工业界是必选项。正如新闻聚合器(News Aggregator)通过算法比对 CNN 与《华尔街日报》报道同一弹劾事件的文本相似度(如转为 Bag of Words 算相似值)一样,视频也可以提取特征指纹计算高维相似度,高相似即可命中去重。 - **MySQL 与 S3 的关联方式**:S3 的存储 key 可以直接采用 `video_id + clip_id`(或加上分辨率),也可以在数据库中直接保存 S3 URL。由于企业在 S3 下拥有独立绑定的域名,将 `video_id` 与 `clip_id` 经过特定 Hash 生成 URL 存入表中同样通用可行。 - **冷存储成本优化(Cost Optimization)**:针对已标记删除的视频文件,纯粹从用户访问层面只要删掉索引和链接即可;但出于成本考量,可将冷数据从 S3 Standard 沉降至 S3 Glacier 乃至更便宜的深冷层归档(不过需要注意 Glacier 有最短 6 个月等保留周期的账单限制)。

---

[55:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3300s) 社区服务架构与基于 Kafka + Redis 的高并发点赞/播放数设计

主讲人接着展开了下一核心模块——**社区系统(Community)**。它细分为 User Service、Channel Service、Follow Service、Comment Service、History Service,以及专为高并发设计的 **Popularity Service**。

```mermaid flowchart TD accTitle: User Activity and Popularity Pipeline accDescr: 用户轻量级行为流经Kafka异步分发到Redis与下游服务的架构

subgraph Ingestion ["用户行为接入"] A["User Activity (播放进度/点赞/点踩)"] --> B["UserActivity Kafka Topic"] end

subgraph AsyncConsumers ["异步处理与消费者"] B --> C["History Service (更新个人历史)"] B --> D["Popularity Service (实时计费/热度更新)"] end

subgraph CacheAndDB ["缓存与持久化"] D --> E[("Redis Cache (原子计数/高频读写)")] E -.->|"周期性批量回写 (Batch Sync)"| F[("Database (冷存储)")] end ```

#### 1. 为什么将 Popularity(热度指标)独立成微服务? - 用户资料修改、频道创建播放列表、关注等行为发生频率极低;而**播放量(views)、点赞(likes)、点踩(dislikes)的更新频率极高**。 - **容忍微量数据丢失(Data Loss Tolerance)**:Popularity 属于典型的非事务(Non-Transactional)轻量级数据。哪怕节点 crash 偶然漏掉了 100 个播放量或 200 个赞,对终端用户和业务大局几乎毫无负面影响。 - **架构方案**:使用 **Redis** 承接海量的高并发读写(如自增操作),随后通过异步机制周期性批量回写(asynchronous write back)到后端持久化数据库。

#### 2. 轻量级用户行为日志(UserActivity Kafka Pipeline) - **日志事件模型**:当用户产生观看行为(如 Scott 观看视频 `12345` 进度跳转到 30 秒 offset)或互动行为(如对新闻视频点赞)时,统一构造轻量级事件投递至 `UserActivity Kafka`。 - **扇出与订阅(Fan-out & Subscriptions)**: - **History Service**:消费该 Topic,即时更新用户的观看历史进度与播放列表记录。 - **Popularity Service**:消费相同消息流,触发对应视频的播放数与点赞数累加。 - **架构通用性**:这种基于 Kafka 活动日志解耦非事务链路的设计在工业界高度通用,类似 LinkedIn 的点赞、评论聚合动态流水线也是基于完全相同的机制搭建。

#### 3. 状态更新频次的系统设计哲学(关于有状态与 GPS 上报的反模式辩析) 在针对状态字段(State)是否需要独立分表的讨论中,主讲人指出: - 视频状态属于典型的**有限状态机(Finite-State Machine)**,生命周期内仅流转 3~4 次(`new` $\to$ `uploaded` $\to$ `available` $\to$ `delete_pending` $\to$ `deleted`),在一张宽表的同一行原地更新(in-place update)完全没有任何性能问题。 - 真正**根本性错误(fundamentally wrong)**的设计,是将高频、无限次变更的数据塞入常规表不断 UPDATE 单行——例如设计 Uber 这类打车软件时,如果把司机的实时 GPS 轨迹每隔几秒就 UPDATE 到 user 单表某行中,由于单次行程包含数千次上报,频繁锁行与写放大将直接压垮数据库。对于高频追加的数据,必须通过独立追加表或流式管道来支撑。

[01:00:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3600s) 用户行为数据的特性与 Read-After-Write 一致性权衡

用户在平台上的绝大多数操作本质上都是非事务型数据(Non-transactional data)。正如 LinkedIn 曾在技术分享中披露的数据,其全平台 99% 以上的数据流量其实都是用户行为日志(User Activity Data)。而在处理像视频观看记录这样的高频写入时,系统设计常面临一个典型的“Read-After-Write”一致性挑战:当用户刚点开一个名为《System Design 1》的视频时,观看事件会先迅速打入 Kafka 这一类消息管道,但具体何时沉淀并写入最终的观看历史表(`ViewHistoryTable`)存在异步延迟。此时,如果用户立刻点击打开自己的“观看历史”,很可能刷新不出刚才看过的那个视频。

```mermaid flowchart TD accTitle: Real-time and Analytic Data Merge Pipeline accDescr: An architecture showing dual-read pattern from real-time Kafka logs and analytical Hive storage. subgraph Ingestion["数据写入与沉淀"] A["客户端用户行为"] --> B["Kafka 实时日志"] B --> C["Hive / 分析型数据仓库"] end subgraph Query["一致性合并读取"] D["读取历史请求"] --> E["合并层 (Merge Service)"] B -- "读取最近数秒/分钟日志" --> E C -- "读取已固化结构化数据" --> E E --> F["返回最新完整历史"] end ```

在系统工程中,解决这类一致性延迟主要有两种实践方案: 1. **客户端本地缓存合并(Client-side Cache Merge)**:用户在当前设备(如手机 App 或同一个 Web 端会话)发起浏览时,客户端本地会留存最近观看的视频缓存。当用户打开历史记录页,客户端直接将从服务端数据库拉取回来的历史列表与本地最新的几条缓存做一次内存 Merge。这种方式轻量快捷,但缺陷在于“跨设备无法同步”——如果在手机上看完了视频,立刻拿起 iPad 打开历史记录,仍旧看不到更新。 2. **读时合并最近日志(Read Last Few Seconds Log)**:类似 Uber 等公司开源系统(如针对 Kafka 沉淀至 Hive/Pinot 分析存储)的设计,在读取端为了提供最新视图,服务端会同时读取分析数据库中已整理好的结构化数据,以及 Kafka 消息队列中“过去几分钟的 Write-Ahead Log”,在服务层动态合并返回。在类似 Salesforce、ScyllaDB 的系统设计中也是同理,通过将未落盘或未重排的分区增量日志与后端持久化数据做实时归并,从而在允许异步落库的前提下保证实时的读取体验。

[01:03:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3780s) 频道与评论系统的领域建模及 DynamoDB 分区设计

在 YouTube 类视频平台的社区功能中,常规的频道(Channel)与用户 CRUD 相对标准化,例如频道包含 Playlist、首页展示、频道简介(Channel Description)以及关注(Follow/Unfollow)关系。相比之下,评论系统(Comment Service)在并发度、层级结构和排序要求上具备更高的复杂度。

评论系统的基础写模型主要分为两条链路:新增评论(`addComment`)与更新评论(`updateComment`)。在新增评论时,入参包括 `videoId`、`userId`、父评论标识 `parentCommentId`(用于区分顶级评论还是针对特定评论的嵌套回复)、`replyToUserId` 以及文本内容 `content`,并在服务端统一打上不可篡改的 `creationTimestamp`;更新评论时则传入 `videoId`、`userId`、`commentId` 与修改内容,服务端追加 `editTimestamp` 以防客户端伪造编辑时间。

```mermaid flowchart LR accTitle: DynamoDB Comment Storage Architecture accDescr: Partitioning and index structure for storing comments in DynamoDB using videoId and commentId. subgraph DynamoDB["DynamoDB 评论表"] direction TB PK["Partition Key: videoId"] SK["Sort Key: commentId"] LSI["Local Secondary Index: parentCommentId"] end subgraph QueryPatterns["查询模式"] Q1["主表查询: 单次批量拉取视频下评论"] Q2["LSI 查询: 快速拉取某个评论的全部子回复"] end PK --- Q1 SK --- Q1 LSI --- Q2 ```

在存储选型上,评论系统极度契合 DynamoDB 这一类 NoSQL 分布式数据库: - **Partition Key**:选择 `videoId`。这意味着单个视频下的所有评论数据都物理存放在同一个分片(Shard/Partition)内,当需要拉取该视频的评论流时,单次 Query 即可高效读出。 - **Sort Key**:采用全局唯一的 `commentId`。在 DynamoDB 中,复合主键(Partition Key + Sort Key)必须保证绝对全局唯一。 - **Local Secondary Index (LSI)**:在同一个 Partition 内针对 `parentCommentId` 建立本地二级索引。因为父评论和子回复严格属于同一个 `videoId`,数据完全在一个分片内部,使用 LSI 即可支持高效检索某个主楼评论下的所有回复楼层,完全不需要引入开销更大、且具有跨节点最终一致性延迟的 Global Secondary Index(GSI)。 - **热点节点(Hotspot)释疑**:有听众担忧所有评论集中在同一个 Shard 是否会打崩节点。事实上绝大部分视频的评论量都在数千条量级,文本总体体积非常小,即便遇到爆款视频,对于现代分布式存储集群的单 Partition 负载能力而言也完全在承受范围之内。

[01:05:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=3900s) 评论排序逻辑、冷热分离与 Redis 计数器缓存

不同产品对评论排序的产品哲学完全不同。例如《华尔街日报》(The Wall Street Journal)的评论区是严格基于时间轴排序的,最新的评论永远置顶,此时使用递增的时间戳(Timestamp)作为 Sort Key 做分页最为直观;然而在 YouTube 或主流社交媒体上,评论是以热度、争议度和赞同数(Popularity & Controversy)为主导进行排序,最精彩、点赞最多的评论优先展示。

单纯依靠数据库排序无法抗住千万级点赞的超高频更新。点赞与观看量是非事务型、容忍极小程度丢失的数据,因此极为适合在 Redis 内存缓存中以 Key-Value 形式维系状态:

| 缓存字段 / 逻辑组件 | 作用与技术实现细节 | |:--- |:--- | | `video_views` / `video_likes` | 基于 Redis 原子递增(`INCR`),以 `videoId` 为分片路由,单机可轻松支撑上万 QPS 的点赞与观看吞吐。 | | `comment_likes` / `dislikes` | 挂载于评论维度的热度计数器,记录每个 `commentId` 的正负向反馈。 | | 后台离线/准实时批处理任务 (Batch Worker) | 每 30 分钟或 1 小时运行一次,从 Redis 扫入该视频下的全部评论得分,计算出 Top 榜单并固化为 `popularComments` 预计算列表。 | | 混合读取策略 (Hybrid Fallback) | 前端拉取时,前 5 页(约前 100 条)热门内容直接消费预先生成的 Popular List;100 条之后的长尾评论再降级走普通时间戳降序分页。 |

当讨论到如果使用非递增或杂乱的 `commentId` 作为 Sort Key 会不会破坏列表时,事实证明顶级评论(Top-level comments,`parentCommentId = 0`)彼此之间天然是并发且无强因果依赖的;如果没有时间轴强保证的诉求,展示顺序本身具有一定随机性也并不违反业务契约。

[01:09:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=4140s) 评论边缘场景、分布式 ID 与用户行为流走向推荐系统

针对评论区删除的边缘异常,有听众提出:“如果热度 Top 1 的主楼评论被作者删除,但底下已经挂了数十个用户的子回复,整个评论树应该如何保证展示一致性?”对此,YouTube、Bilibili 或 Reddit 等平台通常采用软删除策略:并不会物理抹除整棵树,而是在展示端将该主评论标记或替换为“该评论已被删除”,其下挂载的树状回复依然能够顺畅渲染,避免下游评论悬空或上下文断裂。

关于 `commentId` 的生成算法,采用类似 Twitter 的 Snowflake(雪花算法)或较新的 ULID 是行业通用的优选思路: - **Snowflake 机制**:将 64 位整数划分为时间戳前缀、数据中心 ID、机器 Worker ID 和递增自增序号。这样生成的 ID 既能保障在分布式集群环境下的绝对全局唯一性,又在宏观上天然保持按时间递增的单调性,极大方便数据库做索引范围扫描。 - **Snowflake 的潜在问题**:强依赖机器本地时钟,遇到时钟回拨(Clock Drift)时可能会引发 ID 冲突或生成受阻;如今也有像 ULID 等基于单调递增时钟序列的新一代方案作为替代。

最后梳理整个社区与用户模块的数据流向:当用户客户端拉取视频切片(Clips)观看、或点击 Like/Dislike 时,系统会以极轻量的方式同步生成 User Activity 日志,经由异步管道注入 Kafka,再流向最终存储。这些行为流在平台架构中承担着两个截然不同的核心职责: 1. **持久化与回溯**:写入 DynamoDB 的用户历史记录表(User History Table),供用户个人翻阅足迹; 2. **算力驱动与商业价值**:汇总流向大数据计算平台与机器学习特征工程平台,不仅用于近实时的视频热度与榜单计算,更是 YouTube、TikTok、Netflix 等工业级个性化推荐系统(Personal Recommendation & Machine Learning)最核心的训练与召回特征来源。在此,整体系统设计由基础的社区交互正式平滑过渡到了核心的推荐算法架构。

[01:15:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=4500s) 推荐系统的核心思路:标签向量、流行度与协同过滤

在设计一个像 YouTube 或 Netflix 规模的视频推荐系统时,如果把它看成一整个黑盒,会觉得极其复杂。然而,如果将其拆解开来,其核心逻辑清晰可见。首先是为每个视频打上标签(tags),这些标签的生成可以通过系统自动提取,也可以由上传者手动添加。标签可以包括新闻、股票、相声(如郭德纲、于谦)等类别。对于冷门视频(比如观看量极少的桥牌比赛视频 Bridge Tournament),自动化分类的效果往往很差,因为缺乏足够的互动数据进行训练。

用户的兴趣画像(User Profile)则体现为一个多维偏好向量(Vector)。比如一个用户看某个分类的内容看了 50 个小时,或者经常给某类内容点赞,那么他在该维度上的权重分值就会显著升高。例如对《文明6》(Civilization VI)或者股票、美食的偏好权重都会体现在向量中。除了个性化的向量打分,系统还会结合全局流行度服务(Popularity Service)来衡量全网正在热门传播的内容。在个人推荐、流行度推荐的基础上,还可以引入经典的协同过滤(Collaborative Filtering)算法,综合平衡各个类别的推荐权重后计算出最终得分(Rank),并将排名前列的推荐结果写入 Redis 缓存。客户端在打开 YouTube 时,先拉取前 100 条推荐视频,后续再根据需要进行翻页或流式加载。

```mermaid flowchart TD accTitle: Video Recommendation Pipeline Architecture accDescr: Pipeline showing video tags, user preference vectors, popularity service, collaborative filtering, Redis cache, and client delivery.

subgraph Inputs["1. 特征与输入"] VT["视频元数据与标签<br/>(Auto/Manual Tags)"] UP["用户偏好向量<br/>(User Vector: 时长/点赞)"] PS["全局热度服务<br/>(Popularity Service)"] end

subgraph Engine["2. 推荐计算引擎"] CF["协同过滤 / 向量乘积<br/>(Collaborative Filtering)"] Rank["综合排序与类别平衡<br/>(Score & Rank)"] end

subgraph StorageClient["3. 存储与分发"] RC[("Redis 缓存<br/>(Top N 推荐列表)")] APP["客户端客户端<br/>(分页/流式拉取)"] end

VT --> Engine UP --> CF PS --> Rank CF --> Rank Rank --> RC RC --> APP ```

---

[01:20:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=4800s) 流式推荐刷新、分页机制与协同过滤的实际应用

流式推荐(Streaming Recommendation)的关键在于给推荐结果的相关性(Relevance Score)引入时间衰减机制(Decay)。例如,15个小时前的推荐结果,其相关度会衰减 10%;当有新视频产生时,由于初始相关度更高,就会挤占并弹出推荐队列(Queue Pop)中老旧过期的项。对于客户端加载推荐的最佳实践("What's the best way to load recommendation?"),通常的做法是后台预生成几百条数据,前端通过分页(Pagination)拉取:第一页拉取 60 条,点击“加载更多”再拉取 60 到 100 条。如果用户一直翻到底部,既可以直接停止显示(如 Google News 每天大致只推荐 100 条新闻),也可以不断补充推荐全局热门视频或重新触发推荐生成。

针对讨论中有人担心“标签排列组合会导致指数级复杂度”,实际上推荐计算是完全线性的向量点积运算。如果一个用户对美食分类的偏好分值是 5.4,而当前美食库中候选视频的热门打分分别是 10、9、8,只需要简单做一次乘法即可得出该分类下的排序列表,绝不存在指数级复杂度的问题。

协同过滤(Collaborative Filtering)的原理非常直观朴素:系统寻找行为契合度极高的用户群体。如果三个用户在历史上都喜欢图书和图片、讨厌电子游戏和电视,那么当其中一个用户尚未看过某张图片时,由于他与另外两人极度相似,系统便能推断出他有极大概率喜欢该图片;反之,给他推荐电子游戏他大概率会反感。正如喜欢看“郭德纲、于谦”相声的用户,通常也会喜欢看“苗阜、王声”,即便用户从未搜过后者,系统也会进行关联推荐。协同过滤在负反馈(Vote Down)处理上偶尔会存在“误杀”现象,例如用户在看到关于特朗普(Trump)建议“用消毒剂杀灭 COVID-19 病毒”的争议新闻时点了踩,这往往代表其对言论内容的反感而非讨厌看政治新闻本身,但算法可能误判为用户不爱看新闻资讯。

- 推荐衰减公式简析:经过指定时长 $T$(如 15 小时),得分依设定百分比(如 10%)发生 Decay,新内容凭借更高的即时 Score 完成置顶。 - 分页拉取策略:首屏初始载入 60 条,后续按增量分批(60-100 条)Lazy Load,见底后可降级为 Popular 内容兜底。 - 计算复杂度:单纯的 User Vector 与 Item Score 线性乘积,整体复杂度为 $O(N)$,无需进行爆炸式的多标签组合穷举。

---

[01:25:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=5100s) 工业界落地视角的冷思考:边际效益与学术研究的差异

从企业工程落地的商业角度来审视推荐系统,如果自己创业做一个视频平台,最重要的是用最快的方式将系统从 0 推进到 90 分。采用十几年前成熟的协同过滤公式快速上线,往往就能满足绝大部分业务诉求。许多人热衷于追求顶尖的机器学习模型或去读博(PhD)做深入的优化研究,但在商业现实中,将相关度从 90% 提升到 95%,甚至从 95% 优化到 97%、99% 到 99.5%,所带来的边际效益(Marginal Benefit)其实非常微小,通常需要耗费大量昂贵的研究人力。

在面临经济周期下行时,企业最先削减的往往就是这类边际效益很小的高成本研发。类似的现象也发生在金融高频交易领域:许多人研究使用 FPGA 来加速对冲基金(Hedge Fund)的交易逻辑,虽然在特定场景下一毫秒的时延差异可能涉及上亿美元的盈亏,但就技术本身的优化空间而言,它同样是极度垂直、钻牛角尖的从 95 分到 97 分的局部微调。作为系统架构师或技术负责人,应当转换思维代入老板视角:商业价值的大头永远在于以低成本、高确定性的方式实现“从无到有”的 0 到 90 分,而不是陷在边际增益极其有限的学术微调里。

---

[01:30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=5400s) 直播架构实战(斗鱼/Twitch/YouTube):Flink 滚动窗口与切片拉取

直播(Streaming)系统从架构上看,实际上是整个平台中相对最单纯、标准化的模块。对于热搜/热门流媒体(Trending Video / Trending Topic)的处理,只需要将所有的用户活跃行为(User Activity)作为日志流输入 Kafka,并在其上架设一个 Apache Flink 计算引擎。利用 Flink 的实时有状态计算能力(Real-time Stateful Computation)维护一个例如 24 小时的滚动窗口(Rolling Window),实时统计并按观看量(Views)和点赞量(Likes)的综合指标排序,几十行代码即可满足类似微博热搜或热门直播榜单的需求;计算得到的数据再归档进分析型数据库(Analytic Database)供后续挖掘。

对于视频流的传输架构,不同平台有不同策略: 1. **单文件长连接推流**:类似斗鱼早期的做法,建立 WebSocket 连接,源源不断地向客户端管道式传输视频数据(Data Pipe)。 2. **切片文件分发**:类似 Twitch 的设计,将直播内容切分成多个独立的文件切片(Clips)。

主播开播前会预填元数据(Prefill Metadata),如直播间分类(游戏、带货、颜值娱乐等)并设置封面 Thumbnail。主播的推流数据通过 WebSocket 送达服务器,服务器若需要归档录播(如 YouTube Live 结束后保留完整视频),则负责落盘并推送到 CDN,无需归档的则直接经 CDN 边缘节点分发。在斗鱼的切片处理中,客户端在观看当前片段(例如 7分08秒 的 Clip)时,服务器会在返回数据中附带下一个片段(7分09秒)的 URI 指针(Next Pointer),即使该切片在服务端尚未生成。客户端播放完当前切片后,直接依据指针去 CDN 轮询拉取下一段,无需再次访问业务主服务器。若用户网络中断重连,才会重新向斗鱼主站请求当前最新的 Clip URL,从而极大地减轻了中心服务器的并发压力。

```mermaid flowchart LR accTitle: Live Streaming Delivery and Next Pointer Flow accDescr: Video chunk ingestion via WebSocket, delivery through CDN with next chunk pointer chaining, and reconnection fallback.

subgraph Ingestion["推流与切片"] Streamer["主播端"] -->|"WebSocket"| EdgeServer["直播接入网关"] EdgeServer -->|"生成切片与Pointer"| CDN[("CDN 边缘集群")] end

subgraph ClientDelivery["客户端播放链路"] CDN -->|"1. 拉取 Clip 7:08 (附带 7:09 指针)"| Viewer["观众端播放器"] Viewer -->|"2. 直接按指针向 CDN 请求 Clip 7:09"| CDN Viewer -.->|"网络断开重连拉取最新 Clip URL"| MainAPI["业务服务器 (Re-sync)"] MainAPI -.-> CDN end ```

实时弹幕(Live Chat)与视频切片 ID(Video Clip ID)和相对时间戳绑定存储。为主播端呈现弹幕时,系统通常会设定一个短时阈值(Short Threshold),比如 5 秒:由于推流传输和观众端接收存在固有延迟,只有在主播当前直播时间往前数 5 秒内返回的弹幕才会被呈现在主播的实时互动面板上,超过该时间阈值的滞后弹幕则在主播端略去。而普通观众端(Viewer)在观看时原本就有数秒的播放延迟(Buffer),反而可以将弹幕精准对齐到对应的视频时间点上回放。

---

[01:35:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=5700s) 关注点分离设计哲学:将复杂系统拆解为四大轻量服务

很多工程师在面对 YouTube 或斗鱼这样的庞然大物时会感到无从下手,甚至把直播流分发和视频社区、转码等逻辑混为一谈。实际上,在观看直播时,播放器完全只与 CDN 交互读取文件切片,直播流服务与社区服务(Community Service)、离线视频上传与处理服务(Video Upload & Processing Service)是完全解耦隔离的。

离线处理中耗时的生成缩略图、全文检索元数据、压缩转码等流程,在直播场景下被全部重塑:缩略图可以使用开播预设封面或采用异步低频延时截图;检索信息在开播前已预写入;视频压缩也是边推流边进行实时编码,无需等待完整视频。只要贯彻关注点分离(Separation of Concerns),整个庞大系统即可拆解为四个相互独立且易于实现的子服务: 1. **视频上传与离线处理服务(Upload & Processing)**:负责分块上传、异步转码切片、生成封面与元数据索引。 2. **社区与用户关系服务(Community & User Profiles)**:负责评论、点赞、频道关注、用户动态与交易。 3. **推荐与热度系统(Recommendation & Trending)**:利用协同过滤与 Flink 滚动窗口,完成千人千面分发与热点榜单追踪。 4. **实时直播与弹幕流系统(Live Streaming & Chat)**:基于 WebSocket、CDN 切片分发指针与时间戳绑定弹幕。

一旦借助第三方成熟的 CDN 流媒体分发 API,直播业务的核心只剩下基础的配置存储、用户登录与 CRUD 接口;对于匿名观看场景,甚至连复杂的后端逻辑都不需要。从早年星际争霸职业解说黄旭东(“黄老仙”)转型游戏直播的案例可以看出,单纯的流媒体直播在业务逻辑上并不具备高不可攀的技术壁垒。只要能理清这四个维度的业务边界,即使从零动手写一个 YouTube 雏形,工程上也完全是清晰可控、可以快速落地的。

[01:40:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=6000s) 推荐系统的工业界局限与同行探讨

在结束 YouTube 的整体架构讲解时,Scott 坦诚地向大家征求反馈与补充建议。他坦言自己在某些模块上缺乏真实的工业界生产环境经验,尤其是推荐系统(Recommendation System):“我从来没有做过 recommendation,这都是我上学时候的 knowledge。”他希望如果听众里有在工业界真正落地过推荐系统的朋友,能够从生产实践(production experience)的角度补充更多架构落地的工程细节。

此外,Scott 提到听友中有一位在 YouTube 工作的同行王赵宇,本想现场向他请教,听听真正的内部工程师对这次设计的评价,看哪些模块还能进一步优化,不过发现对方似乎已经离开会议室了。Scott 表示等下次王赵宇在场时,会当面请教 YouTube 内部的真实设计细节。总体而言,YouTube 的系统架构非常丰富有趣,值得持续推敲。

[01:40:40](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=6040s) 系统设计实战演练构想与课程日程调整

关于接下来的活动安排,Scott 计划先讲一次 LeetCode 算法题,因为相对系统设计而言,纯算法题更直观、更简单一些。在算法讲解告一段落后,他打算组织大家开展系统设计的模拟面试(Mock Interview)实战演练。Scott 强调,系统设计光听别人讲是远远不够的,必须亲自上手练习——如何主动发问厘清需求、如何组织语言作答、以及在步步推进中暴露并解决设计难点。

针对模拟面试的具体落地形式,Scott 提出了一个对照复盘的构想: - **分组横向对比**:将参与者分成三个小组,针对同一个系统设计题目分别派出一位面试者进行现场作答。 - **参考答案对照**:Scott 会预先准备一份自己的推荐方案(recommended solution),并在三位候选人作答完成后进行统一 Review,横向对比三者在架构权衡、细节处理上的优缺点。 - **注重工程思维而非死记硬背**:Scott 直言自己其实“不太 care interview 本身”,他更看重的是背后的系统工程架构思维;但考虑到许多小伙伴眼下确实有迫切的找工作跳槽需求,这种贴近真实面试的高强度实战演练能为大家提供最直接的帮助。

在时间安排上,Scott 宣布取消周六的分享,将日程统一调整为每周两天,以便更好协调个人精力: - **周二**:固定为系统设计(System Design)专题,通过具体案例或模拟面试深入剖析架构; - **周四**:继续研读经典著作《Designing Data-Intensive Applications》(DDIA,数据密集型应用系统设计)。

安排交代完毕后,Scott 向大家致谢道别,圆满结束了本次关于流媒体与直播系统架构的分享。

## Notable quotes > [20:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1200s) 非常非常 red flag 的 design — Scott Shi

> [30:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=1800s) 在系统设计中,最珍贵的资源永远是 Network,Network 最 expensive,Storage 不是非常 expensive。 — Scott Shi

> [45:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2700s) fundamentally bad system design — Scott Shi

> [45:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=2700s) delete_pending — Scott Shi

> [01:20:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=4800s) What's the best way to load recommendation? — Scott Shi

> [01:40:00](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=6000s) 我从来没有做过 recommendation,这都是我上学时候的 knowledge。 — Scott Shi

> [01:40:40](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=6040s) 不太 care interview 本身 — Scott Shi

> [01:40:40](https://www.youtube.com/watch?v=quJ7hwo5x8E&t=6040s) recommended solution — Scott Shi

## Mentioned YouTube, TikTok, Twitch, CDN, Amazon S3, Cloudflare, Cloudflare Stream API, 斗鱼 (Douyu), HLS, AV01 / AV1, tus protocol, Grokking the System Design Interview, Elasticsearch, Kafka, WebSocket, Zoom, BM25, 翟成祥 (ChengXiang Zhai), UIUC, English Wikipedia, Google, MySQL, S3 Glacier, Redis, LinkedIn, Uber, Hive, Pinot, Salesforce, ScyllaDB, DynamoDB, The Wall Street Journal, Twitter, Snowflake, ULID, Netflix, Bilibili, Reddit, Google News, Apache Flink, 黄旭东, LeetCode, Designing Data-Intensive Applications (DDIA), Scott Shi, 王赵宇

## Video description In this session, we will explore the design of youtube, douyu or twitch.

doc: https://docs.google.com/document/d/1dAGfgfnlsUgxUqE2z6lR6xOdGg_suOoSJKd63JZNfXw/edit?usp=sharing

[Source](https://www.youtube.com/watch?v=quJ7hwo5x8E)

中文简报

YouTube以两秒切片控带宽 架构设计视网络为最昂贵开销 视频系统架构的核心在于将上传流水线拆解为异步状态机并依赖边缘切片分发,因为网络带宽远比数据存储昂贵,无节制的预拉取将直接压垮源站。 本次分享将复杂的视频系统严格拆解为四大独立模块:视频上传与异步转码切片流水线、高并发社区与元数据服务、个性化推荐引擎以及实时直播与弹幕系统。主讲人深入剖析了 YouTube 的 2 秒切片与客户端 Buffer 调控机制,确立了“网络带宽永远是系统设计中最昂贵资源”的工程哲学,并强调避免在大文件上传中采用跨系统分布式事务,应采用轻量状态机驱动异步管线。针对社区与直播场景,方案探讨了借助 Kafka 异步日志结合 Redis 计数器抗击播放点赞洪峰、基于 DynamoDB 的评论分片与局部索引设计,以及利用 Flink 滚动窗口与 CDN 链表指针实现低延迟直播与弹幕对齐的完整架构落地路径。 关注点分离是设计超大规模视频平台的核心哲学,系统应拆分为视频上传与离线处理、社区与用户画像、推荐与热点系统、实时直播与弹幕流四大解耦子系统,大幅降低架构复杂度。 (10:48) 网络带宽是系统设计中最昂贵且稀缺的物理资源,YouTube 激进采用 2 秒极短切片配合高压缩编码,相较 Twitch 的 90 秒长切片可显著减少跳出用户的带宽浪费并提升首屏响应速度。 (30:00) 严禁在视频上传中使用跨存储的单一原子事务;工程上必须采用显式状态机(New → Uploaded → Available)与 Kafka 轻量指令解耦 S3 物理写入与异步转码后处理工作流。 (20:00) 点赞与播放量等高频行为属于容忍微量丢失的非事务型数据,架构应通过 Redis 承接高并发内存自增,再通过异步批处理定期回写持久化数据库,避免单行高频更新锁死数据库。 (55:00)

Reading summary

讲师 Scott Shi 指出,设计 YouTube、Twitch 和斗鱼等超大规模视频平台的核心在于贯彻“关注点分离”,并围绕公网网络带宽这一最昂贵资源做架构取舍,将复杂的视频平台解耦为相互独立的微服务链路。 四大核心解耦与上传状态机架构 (10:48) 面对复杂的视频平台架构,系统应拆分为视频离线上传与处理、社区互动元数据、实时直播分发以及个性化推荐四大模块。针对视频上传链路,严禁将“SQL 元数据写入”、“对象存储落盘”与“生成缩略图”包装为强一致的原子分布式事务,否则长耗时上传与网络波动极易耗尽连接池导致系统崩溃。 工业界标准实践是采用 tus 协议保障大文件断点续传,并通过状态机(New → Uploaded → Processing/Available → Delete Pending → Deleted)驱动异步转码与内容安全审核。消息队列仅传递轻量级控制指令而不承载大文件,媒体切片物理落地 Amazon S3,数据库只保留由“视频 ID + 切片 ID + 分辨率”组成的复合主键及元数据索引。 网络带宽瓶颈与切片粒度取舍 (30:00) 在视频系统设计中,网络带宽的成本和瓶颈远高于磁盘存储。CDN 边缘内存缓存不仅将 P95 响应延迟从源站 S3 的 500ms 压缩至 50ms 以内,更能通过直接消化绝大多数读请求,将系统回源读写比从极端情况的 1:200 收敛至 1:20 乃至更低。 针对切片长度的选型,各平台基于用户访问模式做出了截然不同的工程取舍。YouTube 采用极短的 2 秒切片配合客户端约 80 秒的水位缓冲(Buffer Health)机制,以小步快跑的 HTTP Range 请求适应用户频繁跳出与拖拽进度条的习惯,避免 90% 以上预拉取流量被浪费;而 Twitch 面对高粘性、长时间停留的直播与录播,采用 30 到 100 秒的长切片进行突发传输,以降低高频网络握手开销。 非事务社区互动与分布式存储选型 (55:00) 视频播放量、点赞和点踩属于非事务型高并发数据,允许偶发微量丢失。系统应通过轻量级活动日志写入 Kafka 进行解耦分流,利用 Redis 原子自增操作支撑超高读写吞吐,再由后台定时异步批量持久化至数据库。对于观看历史等“写后即读”的一致性延迟,可通过客户端本地缓存合并或服务端读时归并增量日志解决。 评论系统更契合 DynamoDB 这一类 NoSQL 存储:以 videoId 为分区键将单视频下的评论聚合在同一物理分片,以分布式雪花算法(Snowflake)生成的 commentId 为排序键,并针对 parentCommentId 建立本地二级索引(LSI)高效支撑嵌套回复。面对顶级评论删除,系统一律采用软删除标记保留上下文,避免级联子回复在前端渲染悬空。 实用推荐系统与轻量直播分发链路 (75:00) 视频搜索依赖语音转录及元数据由 Elasticsearch 基于 BM25 构建倒排索引;推荐引擎则依托用户偏好向量与热度得分进行线性计算,叠加时间衰减机制与协同过滤,最终在 Redis 中预缓存 Top 推荐列表。Scott 强调,工程落地的关键在于用低成本实现 0 到 90 分的商业转化,而非投入高昂研发去追求边际效益极小的学术级精排模型。 直播系统则侧重吞吐与链路解耦。系统通过 Apache Flink 维护 24 小时滚动窗口实时统计热搜榜单;推流经接入网关转码切片后直达 CDN 边缘,服务端在下发切片时附带下一个片段的 URI 指针(Next Pointer),播放端依此直接向 CDN 轮询拉流,彻底隔绝高并发推拉流对核心业务数据库的冲击。 Scott 坦言其推荐系统设计源于学术积累,呼吁工业界同行在生产实践细节上补充指正;同时指出系统设计考核的核心在于贴合业务场景的工程直觉与容量权衡,而非机械套用架构模板。

Source quotes

[20:00] Scott Shi: 非常非常 red flag 的 design [30:00] Scott Shi: 在系统设计中,最珍贵的资源永远是 Network,Network 最 expensive,Storage 不是非常 expensive。 [45:00] Scott Shi: fundamentally bad system design [45:00] Scott Shi: delete_pending [80:00] Scott Shi: What's the best way to load recommendation? [100:00] Scott Shi: 我从来没有做过 recommendation,这都是我上学时候的 knowledge。 [100:40] Scott Shi: 不太 care interview 本身 [100:40] Scott Shi: recommended solution

Original transcript

[0:00] Okay. Okay, this is a different way. You can see what's the feature on YouTube. And then I just look at TikTok. TikTok is a simple way. The way you can see it is a simple way. But these are also some additional features. For example, the main feature is to add the main feature. It will look like the EO's and the video's software. Then the service requirement is highly reliable, and any upload should not be done. And especially in return success, it should not be done. And the other thing should be highly available. Um, maybe there are some cleaning time, maybe it's just a while to see a video. And if it's streaming, it's probably a real-time experience. Bonus part is like most popular video channels, subscription, trending video, TikTok video recommendation, real time live chat. And I'll just say that the details are more complex. I'm not talking about the details of the interview. Because you can watch the details of the interview. I'm just going to go back to the details of the interview. Then we'll talk about CDN. CDN is used in the video streaming. The reason is that it can reduce the amount of the content. There are many benefits. For the CDN, like the original server, it's in the West. There are in Canada, and in China, and in India. And then in the US, And you don't need to visit original server, you can visit the CDN server. So CDN server is a bit of a larger object, like image. Image, video can be stored in CDN. And it will be the benefit of the first to reduce the rate and reduce the bandwidth cost. This region has a few hundred users, but only the first or the first or the first time of the meeting, it will be able to catch the local server close to the server. And the other thing, CDN has some additional features, like time to live, and improve website security. The other thing, CDN can increase availability, and reduce latency. Because it is from the data close to users, it will reduce latency. And then, because you are close to user, it is a very fast page loading experience. So it can be faster. I remember that I read a book about Amazon S3, Denymo DB and CDN. It's about the loading time. Amazon S3 is about 500ms. You read the data, it's like the feedback. It's about 500ms. But CDN is the same as P95 or P90. It's more than the number of people. So it's just for fast response. and the experience will be better. And then, when you use CDN, you can use your URL to cache the place, and add the CDN to it. Like, for example, you used to use CDN, myspace.com image1 And then cdn.myspace.com image1. And then you need to configure the CDN provider. But it's a bit easier to use. It's a feature. And then CDN is actually a... What is this? CDN is... It's a tool that you have a tool, because CDN has a service, it's completely built in CDN. For example, streaming service, like Cloudflour, Cloudflare, the leading CDN company, it actually provides a video streaming API, subscription, captioning and subtitle service. So you can build the streaming feature in CDN. And I'll just briefly do this experiment with Twitch, and the Doughy, and YouTube. Twitch's video is about 30 seconds. When you look Twitch, It will be a M3 U8 version of the video. It will be a compact version of the video. It will be 30 seconds. And a clip of 30 seconds is about 20kb, or rather small. Compact is better. And the "dough" is a slow-down. [5:00] streaming file And the streaming file is a file of the file, and it is 500k per second. It's a streaming file, and it's a file that's a file. It's a file, it's a file, it's a video clip. You can only upload it. YouTube is not the same. YouTube is... It has a encoding format. It looks like encoding format is... It seems like there is a letter. After reading it, it will be recorded for the format and it will be recorded for you. For example, you are from the IP, and then you have time, and then you will return to the encoded file. And on YouTube, I saw YouTube click about 2 seconds. Codex is AV01. I don't know if this is not encoding format. It's just like it's encoding format. And it's a clip of 2 seconds. So if you want to set up a simple thing, like a ddui, you can use Cloudflare API. You have to do a registration. And you can use the list of videos and list all your domain. For example, the "douy.com" domain. You can use the list of videos. And it will return to the results. And then you can stream the video. I just fell over it. You can see the API, no more复杂. You can stream the video. You can just use the resource. First, you have verification, and then you can stream your resources. It's called TUS protocol. It's for reusable file uploads. So this is a file upload protocol. It's a very new protocol. It's been a very new protocol. It's been a few years ago. And this one is not file size, so you can always stream. And it can upload captions and subtitles. So the whole "douy" broadcast website, the most basic things can be used to CDN. And "douy" is used to use CDN. "douy" has used CDN. If we look at "douy" CDN's If you look at the CDN resource, it will be written on a CDN. Thank you. This is a simple way of the process. We can do a DIY more time-wise, with more便利, and can be used to the same component. And there are two questions. And then, I asked CDN local nodes for video. Is there any more? CDN local nodes, it should be made of video content. It's a simple example, the original server is your server, your website. So CDN server is the third server. CDN local nodes, I think it's still a little bit. Local nodes, I think your意思 is that you're in local, you're from original server to the original server, or from CDN local server to the original server? It is also a good one This tool is just to show the data close to user property, so it's not in the US user's way of using the tool. And then, the other thing is, CDN talk DB is also originalized, DB will sync. If you look at this, it is not necessary to use DB. It is just a file management management. CDN latency is a very large potential for 50ms. P99 or P95 in 50ms is a very large potential for you to get a fast number. It's all content is in memory. "Standine CD" is what I do. It is a very hot feature. It is a hot video clip or hot resource. And they don't need to think about database. For example, you need to take the content from original server to the ZDN server, and then存在 memory. And when you request, you can serve. That's why you have to spend disk time. Because if you have disk data, you have 100 megabytes. Overhands are 3 seconds. But you can do memory, disk overhead is a bit less. So CDN actually provides a hot energy source and memory - See you on the? Thank you. We don't see these CDNs. You can see CDNs as a usual solution, but it's not a solution. It's a good thing, it's a good thing. It's a good thing. It's like cache, it's less than reading, less than reading the database, and less than reading the database. [10:00] 然后减少对database load, 同时就是improve user experience, 但是没有CDM, 你也可以实践一个video watching website。我们这块的话, 我这块是copy了Glocking的分析, 因为我觉得这个不是重点。大概有个数量级, 我们就直接看结论就行了, 反正所有的推导都是一样的。他计划就说大概有expect 46k video 的每second然后这样的话是,嗯,就是就是view是大概是46k,然后upload的话230k我们就四手五入变成1000好了,1000个video upload per second那它每秒钟需要处理的实际上是25GB,45时候变成100GB也无所谓per second然后就是有一些数据,然后这样的话,就是有一些visualize,就是面试的时候你会有一些数据去就是跟你的面试官分析嘛,或者你写,写其他人写那个design review的时候,就是你要跟你的peer讨论一些数据。然后他这块expect的他这个upload view ratio是1:200,但是如果你有这个CDN的话,其实你可以减少至少90%的traffic,所以这个可能就变成1:20甚至更低。可能1:4 1:5 跟你的 region 相关,然后也看你的 access pattern所以这个这些就是constance我就暂时略够了,因为我们看到这个后面的话,这个skill的时候,只要你share的好,其实skill不是主要的问题,但是你要有这个skill的这个mindset,然后你要知道怎么样share的,你要怎么样计算这个constance然后特别这种Data还是Matters是吧,如果你是一个Gigabyte per minute和500Gigabyte per minute的话,有时候设计思路是不一样的好,我们就这块的话,看一些,就是跳到这个重点上谢谢大家YouTube总体来说是个complex system,有很多features和service然后这块的话,for separate concerns,如果我们想实践所有的YouTube feature的话,它实际上是四个部分,这是我当时想的时候,就是怎么样把它break down 成四个部分。其中一个部分是video upload,process,view,这是一个主要的部分,就是说白了是我作为一个video产生方producer,我upload的一个video,产生一个 thumbnailThumbnail,然后就是给video加title然后别人可以看我的video 这是一部分然后其次的话是一些 metadata management 比如说 user, user profile, number of view, number of likes, watching history, comments, channel, follow这是一部分这个就是一些在YouTube上面实践的功能然后还有一些streaming part,YouTube是支持streaming的,我不知道什么时候支持,但是它确实支持streaming,然后包括这个streaming part的话,比如说这个YouTube trending video,然后TikTok有Trending Topic,然后同时有实时的弹幕,像所有的这个,现在说的,基本上所有视频的都有实时的弹幕。这是一部分 streaming part,然后最后一部分的话就是 video recommendation嗯就是比如说这个我我登入YouTube的话,YouTube根据我的使用习惯,然后recommend的一些personal video然后是我常见的video这种recommendation。所以如果把这个分成四个部分的话,每个部分单独设计的话,其实这个问题会相对简单一点。如果把这四个混在一起的话,这个问题就非常复杂了。所以就是简单的想法就把它分成四个部分我们先看这个video upload和processing什么是弹幕?弹幕就是Live Chat你可以就是比如说我在直播的时候就别人可以打字幕说那个啊就是对我比如说现在在在在这个讨论system design就可以你就可以打group chat 然后如果如果是弹幕的话就在你的屏幕上飘过一个一行一行字就是弹幕好,我们来看一下,如果是只看video upload 和 view 的部分的话,我是这么写的设计计划,就是这么设计的计划,首先你可以有 uploader,就是你有 upload 的一个东西,然后你可以 talk to video upload service,当你upload的时候要做几件事一方面你需要做的是把这个video metadata存起来然后存到这个SQL里面,因为MetaData来说总体来说不大,这个table不会很大会成到这个 Seql 里面然后另一方面的话你要做的是把这个video的这个compress一下,你需要compress一下,之前可能是一种mp3的格式或者是avi的格式,然后把它转化成另一种你统一的格式。然后你可能还需要,compress的时候你可能还需要把它处理成不同的这种Resolution是吧,不管是1080P,还是360,还是240啊你可能要把它处理成不同的格式 [15:00] 然后存到这个video storage service里面这块的话你一开始可能只存一种格式然后呢你需要sign的说这个video然后这时候当你存完这个video就是存完这个raw video然后你存完这个metadata的时候你可以返回给user说这个video存好了,然后这时候你需要sign一个asynchronizer处理一下这个video这块处理比如说我在Safety的话,你可能有Safety处理,这个video不应该有不适合不适合血腥暴力啊这种是不是得剔除掉然后你是不是得实践出来需要剔除掉尤其需要人工实践然后你这个video如果user没有generatedthumbnail的话你就要generatedthumbnail,thumbnail就是当你看video的时候它有一个picture是thumbnail然后这个现在的话 YouTube 还支持一些 preview那你可能还需要 generate preview 就是在这里一个非常小的一个preview,然后看到这个video在做些什么事情这个位置要具体展示什么呢然后同时的话你这个video还应该放到video search service里面,就在elastic search里面出现。然后这样的话,当你search这个video,才能被合理的search到。比如说你要想新上传的一个video说讲system design的,然后你可以通过这个YouTube的search engine,search到这个system design的这个video这是其中一部分我们就在拿那个YouTube作为例子的话,它实际上是所有的video,当它video upload 成功的时候,它实际上是把它变成了两秒的clips,所以它实际上是首先compress,然后做成两秒的clips,然后把这个两秒的clips存在AMLOS3上然后只有当前仅当的video,uploaded成功,compress成功,chop成功,然后start成功,并且metadata成功以后returnsuccess to user谢谢大家然后然后其次的话你就需要做一些就是后端的处理了有一大堆有一大堆这个post processing 的处理如果你要作用CDNNOT buffer的话,你可能需要从这个MetaData里面去identify the clips,然后从Amazon S3上就是catch这个video,chop是啥?有人问chop是啥?我这块说过,你这个video其实可以是任意藏住的但是我从YouTube这里面看,它其实是把所有的video chop成两秒的clips就是两秒一个片段两秒一个片段当你看video的时候,它实际上是把两秒片段传给你,然后再把两秒片段传给你。我们可以看一下这块有一个例子,就是这个是等一下这个是我有我有个YouTube的例子有个YouTube截图看看这个有个YouTube截图它实际上有个Buffer House79秒这个跟你看的video长度没有关它就是有一个buffer size是79秒当你这个buffer size小于house小于多少个threshold的时候他会读下一个两秒的视频,然后他会读再读下一个两秒视频,保证这个Buffer Health在多少秒和多少秒之间。是这样保证的,就是它实际上是把所有的东西变成两秒一个file然后Ryan问说如果user在上传video中refresh page和network中断,回来可以resume吗?这个的话应该是一种优化吧,这种优化file resume upload的话,像那个ftp啊什么,根据你的protocol应该都可以实现。我这块查了一个最新的protocol,reusable file upload的protocol叫tos。就是非常非常新的一个protocol我看它最新的一个protocol到19年它是17年开始的一个project如果你感兴趣的话可以看一下更多的细节说它有细节,但是这个reuse,resume是肯定你支持,它只要用一个已有的file transfer protocol这个肯定支持的好,这块想问了一个问题,说是Electric Search里面需要怎么存?Electric Search我们就可能这块就不,后面会稍微讲一下,但是现在就不说了,现在暂时不提。后面会稍微讲一下Alexis Surge还是比较复杂的,然后Sycle,S3,Thumbnail之间的Consistency怎么处理?比如上传S4月彻底失败了怎么办那么 SQL 和 Sunnate 需不需要满足 Atomic 需不需要把它三部包装成 Transaction 不能把这个包装成 TransactionS3这个时间是非常非常长的你upload一个video有时候花一个小时啊我记得我之前upload过一个花时间特别久我有点surpriseThumbnail是Asynchronized,更不能包装成一个Transaction。这块其实非常简单。你就有一个state就可以了,我这块简单提了一下,有一个state可以了,这个state可以是New,Uploaded,Available, [20:00] Deleted, pending什么的当你新建一个需要去 upload 的时候,你可以是 new然后当你upload成功以后你可以变成uploaded的,你用这个state来处理这个transaction就可以了。相当于是通过这个State的变化把它变成一个Asynchronized处理的一个一堆这个Transaction,但是你不能把这个upload到ms3,然后metadata和thumbnail变成一个transaction变成一个transaction,这个是这是非常非常就是red flag的design,因为这个transaction非常大,你这个field概率很高。相似的这个red flag就比如说,你做payment的时候,Payment的时候一般来说你做payment的时候是你要先从付款方把钱滑走,然后去接受款方把钱转过去,你不能把这个变成一个transaction,你可以把它变成两个付款的话把钱转走以后就转到你的这个比如说你去Visa就转到Visa这儿嘛然后你这个情况下的话你就说这个我钱已经从付款方转走了这个state就是钱从付款方转走了然后你可以不停的try去把这个钱转给被付的人,就是收款方,然后直到你,如果你一直fill的话,你就可以一直retrain,有一些counter case handling,但是你不能把这个付款方转走的钱和这个收款方收到的钱作为一个transaction,这个效率是非常非常低的。谢谢大家好好,我们接着谈,接着聊计划。Electric Search 我稍微会聊一点,我不是特别熟的,稍微有一些细节,有一些细节不是特别熟的,但是我就是上学的时候学过一些内容,就是这个这个TaxTax 处理这块有学过一些东西好,upload video的话,就是upload video,就是我这块写了一个API,您可能有一个dev key,或者是个user的token也可以video title, video description, text, category id, default language, recording details, video content然后video content就是你这个local的video file的location然后它会建一个web socket 把你的video 用它的file transferreusable file transfer protocol 把你的video upload 分解分解上前上前然后Search Video的话你可以比如说提供Search CoreUser Location和Max Video to Return和Page Token,这两个是跟Pagination相关的,然后Search Changes是比较...比较复杂的地方,就是比如说你可以支持一些meta data search,比如说这个video在20分钟以内然后你可以支持一些title search或一些category search然后我在DataModel会简单讲一下Elasticsearch这一块然后getVideo的话,所有的video其实都是两秒的一个片段嘛,clips的片段,所以你的request的话应该是,就是这个videoid和offset就是决定你get哪一个片段的,比如说这个videoid是,你要看System Design是吧,然后你Offset是10的话就表示第20秒开始的一个Video Clip,可以这样设计。然后这样的话,Tepical shot video的话就是大概150个Clips,然后一个长一点的Video还可以是3600 Clips两个小时的video可以3600个clips这个两秒clips是从YouTube上的observation你可以用twitch的一分半也可以啊,90秒也可以我觉得都make sense,这个只要时间不要太长就可以了。李志文同学问: Video Processing Service 拿到 Message Queue的消息后,应该从 S3 读了 Video Content 再处理吧?对的,这个 Message Queue 里面肯定是一个非常小的 Message, 它实际上就是一个就是一个需要处理的一个action,比如说这个action就是generate thumbnail,action是generate thumbnail,然后给一个emron.ca的地址,然后给一个video的一个title或video一个id所以你这样的话读到Amazon S3 然后再给一个target location 是吧比如说你希望知道它处理以后的Thumbnail generate在哪里你就给一个Target URL,Target Amazon S3 URL所以这个Message Queue里面是非常小的一个Meta Data,它不是不含Video的它实际上就像一个指令集一样,就是一个command line一样,就是说我要对当前这个video进行处理,然后generate thumbnail或generate preview,然后处理完以后把它存在哪里他会告诉你这个video original video在哪里,然后你要存的video在哪里也不可能把video pass 进去,因为卡夫卡这个,我这个卡夫卡的话,嗯,我忘了一些具体细节,反正但是一般的sum,如果sum的话,你不应该大于一个 [25:00] 在白子就是你如果这个message很大的话是很有问题的所以应该就是一些metadata 好然后这块的话还有一些internal API,比如说generate thumbnail,start thumbnail,然后index video,这个就是一些internal的系统内部的API然后这个VideoSJ Storage的话就是常见就是我这块想的设计就是比如说你有一个Video IDVideo ID 然后有个 owner name 然后有个 timestamp 什么时候上传的然后有一个还有个video ID啊这个应该是clip id好前面这个ID是videoID,后面是clipID,然后有个offset,这个是当前video多少秒的时间,然后有个next clip,这个是我在,我记得好像在斗鱼就看到了,就是说他就把,这个clips变成一个link list了,当你看到当前的clips,你就知道下一个clips是什么,就直接读取下一个clips,你就不需要对斗鱼的server进行一个request call了。所以它这个是实际上就是这个Video的这个Iceated Storage的这个schema相对比较简单然后,欣杨问了一个问题,说一个video被上传了以后还能编辑video本身吗?一个video上传了以后还能编辑video本身吗当你编辑video的时候,你实际上是存了一个不同的一个file你实际上是存了一个不同的file就是你比如说video 1080p和720p的video其实是从系统的角度来讲是两个东西是两个资源从心的角度上应该还是两个字元你可以写一些那个metadata来把它联系起来好然后Video Processing Services怎么知道Amazon S3传完了?如果不断的pull video的话会浪费resource,因为pull的时候大部分都是空的。Video Processing Services 怎么知道视频采完了?File Close的时候不就采完了吗?你不需要铺啊,你现在有个process,你会有个stream,到你遇见endofile的时候就传完了呀。如果你fail掉的话你就从下一次restart嘛,因为他这个,我觉得这个video传送这个很多都是file transfer protocol如果你感兴趣的话,你可以看一下File Transfer Protocol,但是就是当你遇见endo file的时候就查完这个file了然后雨泉问如果这样的table的话一个video会有好多row with same ID一个table会有好多人VCMID, 啊, 去有很多人VCMID, 因为你实际上是,你这个unique应该是video id + clip id 是unique的这个是正确的,并且这个里面,因为这是Emerald S3,这个读起来的时候,实际上你有可能需要把这个ID和这个Clip就是ID和Clip需要结合起来,然后把它变成一个可能读取的URL。然后它这块应该有个DataField,就是存这个两秒的VideoData。那PrimaryK是什么?我计划写的不好,我计划应该是PrimaryK应该是视频ID加ClipID谢谢大家谢谢大家应该是这样子比较好,这样的话可以unically identify,可能还需要有不同的resolution,你这个,你比如说你这个resolution240和这个1080P可能是不一样的,可能还要加上个Resolution。不同清晰度呢这样的话比较好谢谢大家好,还有一个问题说,Amazon S3 传完以后,Meta data 变成 Video Processing 定时子。改变Amron S3传完了以后,Metadata状态改变。Video processingService定时查MetaData表确定哪些video需要打标签你就说这个是一种POD Method了,其实没必要,因为当你上传Video的时候,你一定是有一个Live Connection的你这个video upload的 process service 一定是有一个Live Connection的所以当你file传完的时候你是一定知道他在什么时候什么时候传完呢?所以这个应该没必要然后Click ID已经有了Clip ID了,为什么还要放了Offset呢?因为这个Clip ID你是不清楚这个有这个Clip ID的话你其实是不清楚它播放了多少时间呢?有Offset的话你知道它播放了比如说240秒这种。其次的话,其实你看后面的Design的话,我这个Offset没有那么必要,因为有一个Mapper是Map频道,比如说 [30:00] 你是播放视频播放的120秒是哪个Clip然后你的视频播放150秒是哪个Clip然后好问这个table放到Seql里面吗?这个table不放Seql里面,这个table应该放到Amazon SE上。但是你可能有个管理Amazon SE的table可能是要放到Seql里面。但是总体来说这个是focus on storage 那块的就是给一个ID 给一个Primary Key 然后把这个Video data放到里面然后杨阳问说一个video会根据不同的resolution 存多copy吗?应该是的,应该是存多个不同的copy,因为这个我觉得你是可能也能做到说你实时的把一个1080p的video载化成720p,然后播放出来但是这里面所有东西最珍贵的资源其实是network最 expensive 资源其实 network storage 不是非常 expensive一般来说一个系统设计中最贵的东西永远是Network,那你如果,首先你不可能说把一个low resolution 叫做high resolution你可以把High Resolution转化成Low Resolution 这是可以的但是如果你是不管是播放360 240都是传送1080p,然后在local转化的话,这个设计本身是有问题的,因为你这个资源里面最珍贵的资源是这个network把视频进度拖到之前的任何疫苗是怎么做到的这个其实比较简单就是我后面写了一点就是其实是有一个谢谢大家好Video Mapping Service 就是我看看有没有写啊我看有没有在后面写的。实际上我们从这看也可以看到。从这个贴板上看也可以看到任何一个视频实际上是有个Mapper,就是给任何一个视频,你可以把整个视频存到一个Mapper里面。比如说,我现在要看System Design的视频。当我click在进度条里面 任何一下的时候 前灯会把click转化成一个offset这个是很容易做到吧 是吧你前端把这个click转化成offset那转化成offset以后就可以读videoid加offset就读到那个clips了然后就可以相当于是你可以把任何进度桥拖前拖后都是可以做到的对吧因为你就是这个日,比如说你进入条件前百分之百的话,你click一个点,这个点就可以转化成percentage,然后转化成具体的时间,然后就转化成offset,然后就读到那个Exactly, in your clip, sir.然后有人问,Alex说这个s3不是存file的吗?那这个file的table怎么存到s3上?这块我应该改一下,应该是sql加上s3。I'm not last-ray,这个是个sql row,然后这个你generate成PrimaryK的话,你 generate 从 AMLO S3 的 primary key 的话,然后你可以把这个 AMLO S3 的 primary key 变成一个 key data 的一个kdata的一个那个就是存储也可以把这个amlnSEA的这个是存成一个json这种是吧然后存成json的话你就可以加了就是这样的话,这里面任何一个就是你的result了,ID field是UOID,Owner field是Scout,然后这些就变成的result了是吧,然后你这个有个data field就是你的video data,你可以把它变成这样子也可以的。也不是说一定要加一个SQL,这个也是可以存的,因为你反正是file 就可以定义上json file,json file里面的data就是你的video的clips也是可以的好,然后欣王问说,System Design里面需要具体分析Network吗?Video似乎好说都用UDP?这块Video是看你是指哪一个Video,如果是Room的话,这种不需要存的Video,或者是Streaming的话,可能是要用UDP这种,就是Phone call或者是Telephone call的话是用UDP比较好的。然后如果你是YouTube的话,这个其实是其实你是不希望有package loss的,所以你可能需要用TCP来进行transfer的。就是你看YouTube的话你是不expect的你的视频Lost的,因为这样的话,user experience很不好,所以你可能用TCP的然后System Design需要具体分析Network吗?你不需要这么分析Network,但是一般来说你需要在Network上进行优化,因为Network一般来说是最贵的Resource,它是比Database的话还要贵。如果是斗鱼的话打开一个直播就看看当前时间Line我是用timestamp来call人吗?我一会我专门说一下斗鱼啊,我会专门说下streaming,这个有专门session是streaming的。再说一下这个系统非常非常大,我把它分成四个部分了。就是separate concern,分成四个部分了,video upload和processing,YouTube Community, Recommendation System和 Streaming。如果是 Streaming 的话,我们讲到 Streaming 的时候,再问 Streaming 相关的问题。然后ID column [35:00] ID还是Primary可以组合起来的这个ID的话你如果是为了那个就是unicoline identify的话你应该是用videoID加clipID加resolution这样的话是unique的所以应该是这个PrimaryT应该是这三个组合起来的这里说,Clips是一次传回去的,还是看到在request每一个clips只有两个second,所以当你buffer不够的时候,你是两个second clips一次传回去的然后这个系统会不停的 maintain 一个,你看 YouTube 的话,你看那儿的那个 space 的话,这系统会不停的 return maintain 一个 buffer,这个 buffer 大概是80秒左右,我看那块80秒,可能不同的进度播放,这个buffer时间不一样一点好然后说那需要加一个video ID 的 column 这个table不是叫video storage 吗 所以这个ID就应该是video ID我专门写一个叫video id好谢谢大家然后志文说这个meta table有点像GFS群的meta,就是说Amazon S3要user维护S3要user维护metadata,MetaData Table有点像GFS乘file式的Meta我记得Amazon S3存的时候其实是有这个,就是你不仅是有data的,你实际上是可以存metadata的。我记得M1C的时候你是可以存卖Metadata的那对我记得是可以,您可以confirm一下,我记得它是可以存metadata,就是不只是存另外你存的object data,你是可以存metadata的,然后这个metadata应该是非常flexible的metadata。好我就接着聊了就是这块还可能还有很多细节如果如果还是有问题的话可以就是问一下这块需要很多时间去想因为我前天后大概花了有五六个小时research这块然后包括想很多东西所以这个会很多东西需要想的还是然后有人问说这个表会不会有很多肉,藏视频的话3600 clips,还有不同的offside可以在AMLONS3 Partition层类似层 VideoID ClipID Offset形式一个video 3600个 这个clip 不是很多3600个resource不是很多,你这块其实肯定还是要做一种optimization嘛。你clips很大的话,你user看的时候,直接上你这个你的file transfer mode 可能更burst一点,比如说你一个小时的video,假设你想的extreme一点,所有的video都是一个小时一个小时,当你是任何点开一次video的时候,你就相当于一下transfer了一个小时的data,那你这个user有一个小时就不会transfer data了。但是大部分user view video的时候,去看两秒钟就关了,很有可能,这个可能是主要的view pattern,那这样的话,你transfer一个小时的data,首先很慢,其次的话,当你transfer完一个小时的data,你这个user关掉的话你其实90%多的都浪费掉了是吧,就可以想的extreme点,所以这个video一定要在作为一个视频晚站的话,你为了增加你的这个utilization rate然后为了增加Video Utilization Rate,你肯定需要把chop成不同的不同的这个Lens 实际上我们看到不同的Video company 这个Trop Lens 相差挺多的 YouTube 就两秒退止近100秒,差了50倍,差了两个数量级。实际上可能跟他们user调查不一样嘛YouTube可能他们user看两网就关了Twitch的话可能他那个他这个user的年度更大,他可能一看经常要看几分钟,这可能是Twitch他自己的优化。这个Video Clips 肯定要 chop 了,但 chop 多少秒的话是你有一个选择吗?你可以根据自己的 user 的使用习惯和 access pattern 来进行 chop我们就是讨论,然后Electric Search Index的话,实际上这块的话就是,就是当你upload一个video的时候,你其实有很多meta information,比如说这个video title,比如说你从 Video就是你这个author给这个video的进行了label,还有一些就是您可以从这个video里面就是用一些language processingNATURAL LANGUAGE NLP的东西从Video里面先转化成字幕,然后把字幕POST成Bag of words,都是可以的。然后作为Text Processing的话,一般来说你会把这个Words呢,就是转化成Bag of words,你可以想象的就是把一个video变成一个article然后把article变成统计它words,比如说这个比如说这篇article来说,你就可以统计说这个bag出现了15次words 出现了十几次,就变成一个word的一个 [40:00] Vertical. Vertica is a word of the signal So this video can actually be able to turn it into an article or web page. And then you can use inverted index to index video. Inverted index, for example, when I searched the words, It will be found in which resource. If you use inverted index, the words will be found in the design YouTube doc. The top of the off-site will be found in the words. Or the design system will be found in the YouTube video. You can use inverted index. And BM25 is a very long time ago. It is a heuristic function. It's what it is, it's a big thing. One is to do COPS or articles, In this case, we will take a lot of YouTube videos to fix it. And then, the article will create a vector. And this vector will create a vector. And each video will create a vector. For example, I'll give you a example. For example, I'm talking about system design. I'm talking about system design features. This video features what is system design. When you search system design, it matches my video. And there are videos that talk about Trump's blackness today. So your feature is Trump's blackness. John Bolton's blackness. The feature is John Bolton's keyword. John Bolton and Trump. It has a heuristic function to fix it. This function has been released for 40 years, but now it's state of art. the same thing is the same thing. That is politics. And then it will pause your search query, for example, search query is system design. Then it will return to system design and return to you. and give you a relevant video score. And the score is higher, it will be more similar to the connection. Thank you. And then it will return a better relation. And then you can add additional filters, like based on video length and upload time. Text processing is a very interesting one. I can recommend you to text processing or elastic search, or you think you might have a lot of interest in this later, you can search for the text processing. Open class, I was on UI/UC uh I forgot my name, Zai老师. He's talking about text processing. It's very interesting. In text, there are some interesting things. For example, you can download the entire English page. It's only 10 gigabytes. We often say that the data is a very different. The rate is very high, it's a rate of numbers, every two years double or three years double. The data is a rate of numbers. But the tax data is a rate of numbers. I was in the 13th grade, and I said, You can download the English Wikipedia, and download the English articles. and then all the English is Wikipedia download 9GB. I download it, but it's not 10GB. Now it's actually the increase. Now it's about 13 or 14GB. That's a 7 or 8 years ago. So, Texts are very current. Word is very current. But the internet is the current. Multimedia is the current. Video, audio, and audio. Texts are very current. Text processing is a very current. I remember UIUC, Zan老师, has a special course. He talks about text processing. He actually talks about it. Very good. And then we'll see the text, how to index, how to search, which is over. If you're interested, you can search it. If you don't know, it won't be able to search. If you don't know, it won't be able to search. It won't be able to search. If you don't know text processing, it won't be able to search. I've never seen it before, but if you don't know, you can talk to the guest. And the previous question, the video process back of words is use those tags as words. This word, video words can be from title [45:00] 可以来自于label,可以来自于tag,可以来自于任何的这个,可以来自于任何的这个,就是你那个,包括你把video转化成transcript,然后把transcript 转化成bag words,然后我看到Warren贴了一个这个,这个就是我当时上的翟丞祥老师,对翟丞祥老师,这是我当时上的课,就是我是13年上的这门课,就是这门课,这门课其实还挺有趣的,有兴趣的话可以寻一下,就是Text Information System,还是挺有趣的你可以就是非常快的花15分钟写一个非常简单的Search Engine就像Google一样的Search Engine它其实现在现有的Tool都有的你还可以看一下,我记得第一个Assignment还是写一个Search Engine然后对比一下谁的Search Engine,Search的更Accurate一点然后还有一个Competition,还是挺有趣的好,我们接着讲然后这个Video Metadata SQL Table 呢Video Metadata 这块呢是这块设计的时候我就比较简单了就是比较常规吧就是User ID, User,然后TimestampTimestamp就表示有什么时候uploaded,然后Title,Description,Total length然后还有video clip mapping这块就是有个video clip mapping比如说offset是0的时候你对应的哪个UIDvideo clips的UIDupset是1的时候对应哪个view ID所以当你看video拖来拖去的时候当你点一个点的时候它实际上会把你点的那个点转化成offset根据total length然后计算做offset前端会计算做offset然后访问的时候就是video IDclip ID访问那个clip然后还有这个video还有可能有个thumbnail然后这个有一些sharing rule和statestate下面有额外的说明这样的话就是一个video就转化成了一个row所以我们看一下这个video我们就是room out一下这个比较复杂room out一下这个video其实转化成了一个什么呢变成在video metadata里面一个row然后它有一些metadata比如description啊title啊然后什么时候uploaded啊totalance啊然后同时呢转化成了一个一个list of clipslist of real clips然后每一个clip是真正的video data然后它还有一个UID到thumbnail的然后你可能还有一个preview的UID就转化成了这样的一种这么一种格式然后state的话可以变成以下几种state比说new,new的话就说我要upload一个video当你upload成功的时候,当你这个fileupload成功的时候,你就把这个video这个roll里面改成uploaded然后当你process处理完的时候,就是比如说你generate,从somenil generate完然后你generatepreview generate完,然后你验证过这个video没有比较暴力的内容,然后你就可以把它变成available当你delete的时候,你可能需要delete pending,因为你这个delete的话我们注意到这个delete,当你delete的时候你需要delete多个地方是吧你首先得不仅是delete这个video的access你还要从这个search engine里面,从这个elasticsearch里面delete掉所以你这个delete其实是非常复杂的一个过程,你要变成delete pending当你把这个index的search engine全部delete完了以后,就变成delete然后如果没有做过复杂系统我觉得这个newgres里面如果没有做过这个delete的这个process的话你做一次delete会发现很有趣这Delete任何一个系统的User Delete的过程是非常有趣的一个过程现在来说一般来说是不做Hard Delete除非你是其他人有regulation就是法律要求你必须Hard Delete一般是不做Hard Delete因为你Hard Delete的话你会丢失数据所有的系统中就是这种internet的互联网公司最重要的就是数据嘛Data数据所以delete一定是soft delete并且你delete的时候,你一定是实际上是你实际上是要把不同的东西delete你一个user data实际上可能在多个地方存储很多次很多次所以delete的这个process是很有趣的一部分有一些block写的也很好我之前读过一个公司写的delete block写的挺好的我忘了是哪一个了,反正是去年的时候读过一个delete block写的非常好就是他讨论了一下这个delete process有多么复杂什么的然后王兆宇在那边问说可能过于 maybe over optimization can be dedupe videoDdupe factor can be made by the video ID, video title contentDdupe video是一定要做的Ddupe video一定要做但我这话就略过了因为你可以专门写一个就是这个high level section可以专门有个Ddupe videoD2PO也有很多,D2PO也有很多existing research 啊,如果记得那个就是两周前,两周前讲那个就是search engine crawler 里面的时候,就是当时做一想,我就是研究生想做一个news aggregator 嘛,然后那会儿的时候就是有人,我们组有人专门research, [50:00] 除了这个你有色的 YouTube他实际上有一些算法,你可以通过一些算法来 detect 这个news,比如说CNN 报道的这个Trump 被 Joe Bonten 弹劾的news 和这个 Wall Street Journal报道的被John Bolton被弹劾News这个相似性是吧他可以计算一个相似值的它可以把这两个news变成一个相似的值它其实算法也不是那么复杂,你可以把它转换成bag of words 啊什么的,也可以进行计算,但是那个算法可能不是那么准确是吧?它有一些自己的专门算法来计算这个news的相似值。这个video dedupe您可以认为是类似的吗?就是把这两个video计算一下它这个相似值,如果它这个相似值相似值几高,那你就认为是同一个video,然后可以做 dedupe。然后, 静怡说,Sycle和S3是怎么联系起来的?是不是MetaSycle的table里面S3的UIL? 这块。你的video id加clip id 这块可能还得加个resolution 但如果假设没有resolution的话 简单一下的话 video id加clip id然后就可以去 Amazon S3 读了,因为你就是 Amazon S3 的 primary key 就是 video 加 clip ID 。甚至你可以把这个 UID Key 就直接存,就是把你的 Amazon S3 的 URL 直接存在这里也可以。谢谢大家把UIL直接存在这里也可以就是Amazon S3的UIL,我再写一下谢谢直接存在这里也可以啊也是可以的就是啊都可以啊,反正只要把它link过去就可以。好然后这个ClipMapping是可以存在另一个table的,是看你这个Clip是怎么加上去的如果你是一个video直接upload上去的话,比如说你就一次性upload上去,然后把这个video clip分成100份,然后以后就不变的话,这是一个write的时候,你就可以把它存成这种就存到一个field里面就可以但如果是streaming的话,你实际上是不停的append clip,不停的append clip,这样的话,你如果不停的append clip的话,你如果变成这样的设计,你实际上不停的在upload这一个roll你不停的在upload一个road,那就是非常bad system design了。所以如果是streaming的话,你可能要把这个clip变成一个,你把它normalize,存到一个不同的table,你可能是更好的一个设计。我这块假设的话就是你上传一次video,然后把它chop从clip以后就不变了。你就变成immutable,那这样的话就没有反复的upload一个road的这个过程。所以这种情况下的话就是,就把它存在一个column,就是合理的。好,这个Video Upload and Processing 这部分就讲完了,就是讨论,就是这块我说完了,然后大家有什么问题吗?有什么confused的地方或者是觉得哪一块可能不work有人问说被删除的视频除了在metadata里面标记层deleted的话,那storage的数据需要移到archive的sv吗?还是不管,还是只要index没有就可以了?从user访问的角度只要index没有就可以了你把S3赢到的Glacier,应该是最便宜的吧?还有一个更便宜的Glacier,什么的?那这个其实是optimization嘛也是可以做的,就是减少Cost Optimization的话我有一个问题是那个然后有人问说如果只是有index的没有,如果只是有index,没有UIL的话是不是还可以访问?那你如果只有index没有UIL的话,你就可以把kinkin的。或者是你的UIL就可以变成hash的index也可以吧反正这个UIL你设置Domain的时候,你设置你的那个S3的时候,实际上你在那个Domain下肯定都是你的嘛比如说我成立一个System Design设计公司,在这个导门下说的都是我的,所以我可以就hash一下videoide加那个clipsClip ID 然后就变成这个 UIL 也可以谢谢大家Glassia需要至少存6个月所以可能不是最便宜的有一个更便宜的Glassia算是非常便宜的有一个更便宜的这个就不谈恋了就有些细节就是cost的角度来讲这个State是一个不良的系列就是有一个问题是那个我们接着讲下一部分啊, hello下一部分的话就是community部分,我把它定义叫community了,这块就包含user service,channel service,follow service,command service,还有 user history, view history, the popularity然后这块的话,就是 popularity 呢,就是说这块我定义的时候就是in charge of views likes dislike video how likes or dislike or comments然后它会不停的 periodically read all user activity log然后 update likes and views [55:00] 有人说话吗大家Skyl,能听到吗?我发现我一直静音的,怪不得我没听到的,你说好了,不然有人说话的话,我没听到可能,我一直静音,不好意思。没事,我刚才在想,Messico的那个Design的时候,那个State相对来讲也是一个长辨的那样,你说有没有必要把它提出来呢?比如说就是这个里面有各种state 然后把state 然后state 是吧它不是一个长面量你思考一下它实际上如果一个正常的video它变了两次从new 变成uploaded 从uploaded 变成available 这个是无所谓的啊变成deleted pending,deleted pending,deleted,deleted,就变了四次吗?没什么意思就是什么时候真的是update,SIM RAW是extremely bad design了,是你如果是个有线状态机的话,你最多十几个state的变化一个RAW其实无所谓的,但是你这种,你这种,你如果把它变成,比如说你变成Streaming的话,你这个video clips的不停的,不停的upend到clips上的话,那你就不确定了。类似的Design 还有比如说在打Uber的时候 你不停的把GPSupdata user table 里面这肯定是非常run fundamentally run design 对吧 因为你首先不确定这个GPS要upload多少次其次的话,你这个triple可能很长,你要upload几千次就是问题了。但如果它是个有线状态,只是几个state相互之间的话,其实无所谓。好的,谢谢刚才还有人问问题吗?我刚才静音了,所以如果有人问问题,我没有听到。没有的话就继续了好这块的话就是把这个 community 就分成了这个 youtube community 就分成了几个 service user, channel, follow, comments,然后Activity然后这个 popularity 的话就主要like, dislike, and view.为什么专门把 popularity 列出来?因为这个 update 其实是比其他都比较频繁的。你user 的这个 behavior 其实非常少的包括 channel 你up channel 里面你 add 一个 new playlist 啊moo 一个 new playlist follow 这个关系啊 包括 comments 啊其实来说最频繁update是这个views,就是你当你点开一个视频的时候,你view就加1嘛,当你like一个dislike视频的时候然后我看到一些comment的问题,如果是非常trivial的问题,你可以google一下,因为这个里面内容太多了,不可能特别trivial的问题暂时就不回答了,比如说这个MLS API什么样子,google一下就可以了。好然后这个popularity的话,这个popularity因为它有大量的read和read,所以你small chance or data loss 是ok的,比如说你这个views,因为data crash少了100个view其实无所谓或者是你这个like因为crash少了200个like其实无所谓这也不会任何有user受到影响所以计划设计的时候我计划想的是用一个redis来start data然后 asynchronize right back to the dB.这是这个 popularity,然后这个其次的话,说Lightweight的Activity应该是首先GoTo这个UserActivity Kafka的就比如说我看一个视频,scot看视频12345,然后看视频,然后offset是15,就表示我开始看这个视频第30秒是吧?然后或者是scot看那个trump视频,然后表示like Trump被弹劾是吧?这个都是user activity然后当你有这个UserActivity的时候,它其实就是可以把它publish到这个UserActivity Kafka,然后 asynchronous 呢Asynchronously, 这个就是update, history, popularity,同时update这个history和popularity,比如说这个history说我看这个视频,那我就显示我过去看的哪些视频,就要把我观看记录update掉。然后popularity的话说这个视频因为我看了,所以观看数量,view+1,是吧,所以它可以想,相应的被updated这个的话,这个Activity是所有的lightweight的,就是非Transaction,这个可以用相似的概念,就是说这个非Transaction data可以用类似的做法做,就是把所有的user的Activity,变成一个ActivityLog Kafka,然后这个Log Kafka还有不同的有这个Subscription Service,就是下面有几个Service,update很多地方,这个是可以在其他地方也可以做到的,比如说,嗯,比如说说的comment system,比如说LinkedIn的commentLINKING的 LIKE, LINKING的这个这个 [60:00] Emoji都可以这么做实际上我们看到LinkedIn他给那个talk的时候LinkedIn自己说自己99%的data都是non-transactional data都是user activity data也看到user activity data其实是majority的好然后这里面有一个问题是什么呢就是有一个问题就是read after read的可能会有问题什么意思就是比如说我看了一个视频我看了system design 1然后我看了system design 1的时候我的Activity会read到KafkaActivityLog但我不确定什么时候它会read到我ViewHistoryTable那我点了这个视频以后我立马点我的ViewHistory它可能不在那里可能不在那里这个其实我记得YouTube以前是不guarantee这个Consistency所以你立马点了以后它是看不到你最刚看到的那个视频的History的但是其实是如果你有这个要求的话你可以有两种方式解决如果是你在Client端就Cache掉什么意思呢如果我用使用同一个WebServer或者我使用同一个MobileClient我实际上看了以后我再点那个History的话因为我这个Local有Cache的Data所以我就把这个Localache data 碰了过去就是在读的,从database读history我还把local最新见的那个,最新看的那几个merge起来返回,这样的话是可以的但是这个还是有问题啊,就是当你比如说你在手机端,手机一上看,然后去iPad上看的时候你history还是不显示这只是一个就是local的一个优化,就是只有一个device的优化然后另一种的话你可以读last few seconds log这个也是常见的Uber有一个系统叫pigitpigitpigit还是pigit我忘了它实际上就是读的时候它写的是类似的它这个database是类似的你实际上写的时候一个是kafka log然后这个kafka log会沉淀到这个hive里面Hive 是 analytic data存在Hive 里面那你要读data你为了guarantee 你这个data读的是最新data实际上它会从 Kafka 里面读然后再从Hive 里面读analytic data 里面读把这两个data就是 merge 成一个data这样的话最新的update 也有的然后还有类似系统就是我们上周讲的Salesforce 和 CionalaCionala也是类似的应该上周六讲的Salesforce,Seonala也是类似的它也是一个就是Write-ahead log就是所有的最新的Activity都会到这个log里面然后它会有一个back-end process把这个log转化成它自己的structural data就说在Salesforce这种情况下就把Uber data放到Uber的那个partition里面然后把Lift data放到Lift partition里面那如果你只读那个就是structure好的data, sorted好的data,那其实是没有最新data的所以他要读最新的rata-head-log几分钟加上那个sought好的data,然后把它转化成那个result的返回这个是可以做到的好,有人问Alex问channel service是maintain什么playlist吗?channel service有playlist,你可以打开一个YouTube看一下,我当时参照YouTube的话,它有playlist然后你channel还有一些其他的feature比如说你可以写一些comments然后你可以写一些channel description什么的就公共营销号的感觉然后这块的话我省略了很多clude就特别简单比如说user crude我就省略了然后follow on follow这个也省略了channel crude包含playlist home features我也省略了我这块只讲了一个coent,因为我觉得这个comment是稍微有点难度的,其他的没有什么难度就这个comment这块是有点难度的好,当我们看comment的时候,你实际上就有两个,一个是update comment,一个是add commentadd comment的话,你可能有user id,user parent comment,parent comment就是你是回答谁的然后你可能还有reply to user,因为你parent comment,你可能还要reply to其他user然后加comment本身然后这个server会加上creation time当你updatecomment的时候你有videoid,user comment id然后你这个server会加上edit timestamp这样的话保证你这个timestamp是没有被manipulated然后这块comment呢我想的是用dynamoDB跟design slack是很相似的我觉得用dynamoDB相对比较好一点然后就是它这个partition key就是video id所以你一个video下所有comments都是go to同一个partition的所以你读的时候,当你读这个video所有comments的时候,你可能一个读就读出来了然后这个comment id呢是thoughtkit这个是thoughtkit但是我们看到不同的comments其实实践起来是不一样的你像比如说你去Wallstreet Journal看Wallstreet Journal的comments的话,它实际上就是 [65:00] comments 实际上就是根据时间来的,就是你最新流的comments在最上面,所以它这个sought key就可以变成timestamp是吧?那你这样的话就永远guarantee你最新的最上面,pigination就比较好做。但是像YouTube的comments的话,它是跟popularity相关的。你是最popular的或最有增益的comments是Display在最上面的所以这种情况下的话,你可能还需要一个,就是你需要结合一个 popularity table,来决定哪个 comments 最先显示。这个还是,这个 YouTube 的相对来说,这个优化还是有一些额外的优化的实际上你还要做一个local secondary index on parent comments id只要local就可以了 因为这个parent的commentsID是一定是在这个同一个video下的,你所有的comments你有 parent 的 comments 和 child 的 comments你所有的comment一定是在同一个video下的所以你没有没有必要做 global secondary index嗯Local Secondary Index的意思就是所有的index在同一个share里面因为我们这块谈到所有comments同一个video comment在同一个share里面所以你这个local secondary index就可以了然后有人问说那你所有的comments在一个shard上有hospot节点怎么处理,不需要处理,那这个video的comments一般几千条就差不多了,几千条comments很小很小,不是很大然后然后雨前问说为什么用comment ID做SodK 那ID怎么form同时几个comment同时产生但是不同的video对啊,你不同的video的话,你的comment会去到不同的partation上你只有同一个video的comment在你生存中是有意义的,因为你需要同时你的read和write是同时进行,你的read特别是read是同时进行的,因为你读的时候你会读到这个read video 的所有 comment, 假设你 comment 数量不是太大的。这个 comment id 做这个 thought key 呢,有待商榷吧,我实际上是没有用到这个videoID的sought功能,就是你这个UID我没有用到sought功能吗?因为我不是按这个UID来sought的但是在Dynamo里面,你Video ID就是PartitionK +SouthK需要Unique的。如果你不拿这个Comment ID做这个SouthK的话,你需要拿一个另一个可以保证它Unique。用这个设计的话,好处是什么呢?好处是你读的时候还是挺快的,你用Video ID,PartitionK +SouthK很快能读出来。坏处是什么呢?你不能直接用它的thought order,因为它的thought order是按那个 comment id 来 sort 的,如果这个 id 是没有 timestamp 的话,你这个 id 其实非常杂乱的,就是非常乱的。就是top level的comments是非常乱的,但是其实乱点无所谓,因为这块的comments是全部是concurrent的这comments全部concurrent的,什么意思就是你这个comments在top level的时候你是没有dependency的,你的parent ID是0,所以你是concurrent的,所以你显示的auto order其实也无所谓,也可以解释清楚。就是user不会看你comment的顺序,说这个comment顺序这么奇怪,因为你如果没有explicit guarantee是什么order的话,其实显示什么order都无所谓。但是从user experience 角度来讲的话,你可能想显示最popular的comments在最上面,然后less popular comments在下面。然后这个popularity的话就是我们之前讲过因为它是非常大的data,非transactional data,允许data loss,所以可以放到regis上是吧这个table设计就是VideoCacheUID然后它views是这个,likes是这个,dislike是这个当你update一个like的时候,你就很快的把video like+1。因为这个Redis是inMemory,所以它是非常efficient的,它可以轻松的处理每秒钟上上万个这个request 是非常efficient的然后其次Redis也可以partition 你可以根据这个video uid 来进行partition然后其次的话这个like不仅是有这个video ID 有comments 所以in the comments 也可以有like or dislike然后这块的话我这块把 popular comments 是放到这个video上了我这块想的是有一个background process可以有个background process 不停地读到所有的comments然后把同一个video下的comments 读到多少like和dislike然后呢 generate 一个 list 就变成 popular comments所以它比如说 popular comments cover 前五页 是吧就是前五页的 comments 是根据 popularity 来的然后以后的comments就可以根据这个timestamp来,那你是可以这么做到的是吧就可以根据timestamp来,然后这样是可以做到的 然后王赵宇问说: What's the best structure to calculate?popular comments这个其实可以用list来考虑,因为你是个batch process,比如说一小时站在那里, [70:00] It's a... or is 30 minutes generates Then you generate, you go to the Redis popularity table and read all the comments. You read all the comments, first of all the comments. Then you can write likes or dislikes, generate a list and write it. And then when people watch this video, you read popular videos. You read the comments from the 100th. You just do popular comments 100条以后, you can click timestamp. One of the things that you read comments are not going to read a lot. You can say January, the last two years, the last three years of the year, Okay, so I think the algorithm is not important. From system design, any algorithm is not important. It's not important. There are many thoughts. If a video is top 1 of the content, there are several users who can reply to the content. 评论 The comments were deleted from the comments. Can you write the correct direction to ensure that you have to be done? There are several ways to fix this. I don't know how to fix YouTube, but I know in Blender, if you have a reply to the comment, you will see that this comment is deleted. Oh. So it will have this display. You can use different user requirements to fix it. I think this is not a very difficult thing to fix it. Thank you. How? The last thing is the video view and like history. When you use a log, for example, I was a user, I watched video 1, and then I watched video 1, and then I watched video 1, and then video 1, and then video 1, and then video 1, and then video 1. I can see every video, when I fetch clips, I can create a user activity I watched this video The one is the one, the one, the two, the one. And when I like it, I can say I like this video. I can add clip information, which means I saw that I like this video. I will have more insight into machine learning. I can dislike this video, so I said action can become a user activity history. And by the user history table ingest. Asynchronize inject, like Gmail inject, or is it a bit of a solution, a bit of a solution, a bit of a solution, and then write it in DynamoDB. UserActivity and LackHistory can be used in many different places. One is The main thing is to use the personal recommendation machine learning and personal recommendation. This is the time to use. This YouTube community is done. The YouTube community is talking about user service, channel service, follow service, command service, and user activity. We will make user activity two different ways. One is to record history And then the other side is to calculate video popularity. Video popularity. So this is from the user's perspective. The user's perspective is from the user's perspective. The user's perspective is from the user's perspective. The user's perspective is from the user's perspective. Thank you. Partition, it will be put in a partition in a partition. That is the SoutK, so you can check the SoutK, and you can ensure that the SoutK is not the same. The other thing, the comment ID, you can use the Snowflake ID. If you use slow flick ID, the ID is guaranteed unique In the other hand, the time stamp will be used in the ID. So the time stamp will be more larger than the time stamp. The time is more than the time. This is a guarantee. You can put the timestamp in by the ID. You can also put the uniqueness in the ID. Twitter Snowflake is quite a bit late, but Snowflake has its own problem. There are some new ones, I remember the last time. I've talked about LUID, it's also guaranteed time stamp. Thank you. If the community has no problem, the comments has no problem, then we'll talk about recommendation system. Snowflake ID has a problem, you can search Snowflake ID's problem with Snowflake ID. I was just asked for an article, but I forgot about the problem. Snowflake ID has no problem with Snowflake ID. Huh? Thank you. Okay, let's talk about recommendation system. This is YouTube and YouTube. And then, we'll do TikTok. Netflix as well. And the "dough" has no recommendation. It's possible to do it. [75:00] Gracias. Esto es muy difícil. ¿Cómo hacer? Primero, el sistema de la netta En este caso Hay que hacer cosas muy difíciles. Yo no tengo que hacer este tipo de trabajo, en el trabajo de trabajo. No hay que hacer este tipo de conocimiento. En este caso, en este caso, hay que hacer cada video. Hay que hacer un texto. Y esto puede ser automático o manual. Por ejemplo, el texto es un sistema de diseño. News, Stock, Uy千, en el canal de la página web, se llama "Uy千" como un tag. Es como un tag. Es como un tag. ah Esta es la tienda puede ser un autor label puede ser un teléfono, puede ser un teléfono, puede ser un teléfono de YouTube. Yo creo que es un teléfono de Netflix, es un teléfono de Netflix y le pido a un teléfono. y también hacer una评価ación. Esto es para que el machine learning y recomendación se ha hecho más. En YouTube hay algunas cosas que si la gente ve muy少a, la clase de clasificado es muy mal. Por ejemplo, yo he visto muchos de la Bredge Tournament de videos. Pero no se ha pasado de clasificado. Porque en el bridge tournament, el tránsito es muy caliente. no se ha visto clasificado. Así que en primer lugar, cualquier video genera un montón de tags, y el tag es un poco más que se puede hacer. Por ejemplo, el primer es automático genera un montón de tags. Y luego, el primer video es un poco más que más de classification. Por lo que hay un video popular, hay que encontrar un tipo de clasificación. Entonces, el texto puede ser cambiado. Y el usuario de perfil, el usuario de perfil, puede ser que me ha visto y me ha visto el video de un vector. Por ejemplo, si yo veo el video de la paredes 50 horas, mi vector es más alto. Y yo le like a la la la stock, mi vector es más alto. Y en este caso, en este caso, en este caso, por ejemplo, si yo me ha visto el precio de la paredes muy alto. Hay tiempo más, lack, y más, civilization 6, lack, más, ¿no? Y luego ver el ámbro de la ciencia y también es muy interesante, yo vi a muchos de los que se han visto en el libro de Guadalajara, pero no es el libro de Guadalajara. hay muchas cosas que son manuales o sea o hay problemas Ahora, puedes ver el label. Ahora en YouTube muestra la video. El label tiene muchas preguntas, y es muy bien. Por ejemplo, miramos a ver el郭德冈, no muestra el郭德冈. Y miramos a ver el video de Bridge. El label tiene mucho problema. Y en otro caso, puede tener otra servicio, y luego de leer la popular service Y decidir el video popularidad. Y luego puedes hacer un nuevo nuevo contenido de la popular food y le recomiendo. También puedes hacer un colaborativo filtro. Esto es un buen método, también puedes hacer un video recomendación. Voy a un poco a un comentario sobre el colaborativo filtro. Es un método de personal recomendación. Es muy útil. Gracias. Y entonces, cuando mi recomendación, según mi recomendación de usuario, según mi video, según mi categoría de video popularidad, y yo personal recomendación. Y generar y luego puedes存在ar el database. Me refiero a la comida, ¿no? 1, 2, 3. y luego se rank, es verdad, es que no hay que equilibrarse, no hay que una categoría de un tipo de categoría. Y luego se requiere un equilibrio y se rank, y luego se forman en un memoria de la redis. Cuando me fui a la publicación, cuando me fui a YouTube, me dijeron que me dijeron que me ha sido el primer de 100 personas. El video, solo estudiar el video, ¿no? El video es el video 1, el video 2, el video 3, el video 4, y luego estudiar el video de 100. Y luego, no necesito seguir el video, porque el video de este video, El cliente es demasiado, entonces es que es el cliente de la línea de la línea de la línea [80:00] 然后他有新的video,并且他可以streaming的recommendation,就是怎么做streaming recommendation呢?就是你所有的video的这个recommendation呢,它那个relevance你可以有个scal,然后这个scal可以dk,比如说现在的推荐过了15小时后,它这个就dk10%就是在这个relevance的dk10%有新的video过来的时候它的那个relevance更高,然后它就pop了之前了,就把这个queue pop了之前了然后说What's the best way to load recommendation?谢谢大家谢谢大家这个generate list其实它这个list generation应该是generate了好几百个然后你每次的时候你有pagination你比如说你一开始只读60个当你load mode的时候就读60到100个当你漏到最后的时候,没有 recommendation 的时候,可以聊那种方法吗?一种方法就是煮一些不相关的 popular 的可以的,然后一种方法就是不显示了。像我看Google News的话,我有时候看Google自己recommended news,Google News每天大概就显示100个左右,你要超过100个就不显示了。YouTube我还没有一直铺一直铺不知道它到底显示多少个但是它后面的话如果想keep显示的话就可以显示popular就是它就是不停的generate新的也可以嘛就是generate新的也可以的这个我觉得不是一个问题啊好这边的同学们说标签的排列组合可能会造成指数级的复杂度,比如说你看过视频。去从以后100个标签然后每N个标签组合计算topN推荐的视频。零个标签可以是我没看过的标签视频,但也可以是我看过的标签美式视频。怎么会有一百个复杂度?没有啊,你任何,你实际上就是一个vector 层,比如说我看Food,我对Food的偏向是5.4,你对于Food category有一大堆Rank,比如说这个Food更切械,它顶值是10,那就是10,9,8,5.4乘一下不就可以了吗?5.4就是有个运算了,我觉得成就挺好的,成一下这个relevance/scope就可以了吗?然后你这样的话就算出来,对负责category的话这个视频推荐是123456,然后对Civilization 6的这个推荐就是678910对于千项上是8910勾圈是吧,这样子就可以了,肯定是个linear的,不可能是指数级的,没有没有必要指数级的复杂度好,最后简单讲一下 Collaborative filtering,这是一个非常powerful的一个Powerful 的一个 recommendation system,这个collaborative filtering也非常简单,其实这个道理非常简单,您可以search 一下,它有一个专门,这个是从collaborative filtering那个vk page 讲到的它道理非常简单,比如说,你有一大堆user,然后有user是喜欢这个,讨厌这个,喜欢这个,喜欢这个,是吧?然后你有这块有三个user 注意到有三个user然后这三个user behavior 按之前的 behavior 契合度是非常相像的就是都喜欢图片和书籍讨厌video game和电视是吧,它的相像度是非常高的。然后对于其中一个user,对于这个user来说,我们还没有给他看过图片,因为他和下面的user相似度非常非常高。所以我可以看出如果给他推荐图片他大概率也喜欢对吧,对于这个user来说,我还没有给他推荐video game但是它和剩下的几个user相似度非常高,是吧?那我给他推荐Video Game,他大概率不喜欢。那这样的话就是结合和你相似的这个用户特点。比如说,我喜欢看郭德高宇全视频,能够推荐一个苗粉王生的视频,那个相声我可能也很喜欢看。也是类似的嘛,就是很多人看比如说郭德纲、余谦的那个相声视频也很喜欢看苗佛王生的,所以他就点赞了是吧,那这样的话,呃,因为很多用户,呃,因为很多用户,呃,存在大量的用户喜欢郭德纲同时也喜欢苗佛王生,那我还没有看过苗佛王生视频。啊他可能就跟我进行推荐是吧然后或者是我经常觉得这个Trump很傻逼是吧就是vote down Trump的那个policy是吧可能就是可能他会有一定误杀就是说我很讨厌看这个最新的政治新闻是吧,所以他就不过推荐政治新闻也有可能是吧这个有可能有误杀的因为这个User这个Votab,Votab其实非常controversal的你比如说你实际上很喜欢看新闻,但是突然出现一个Trump很傻逼的新闻Trump推荐使用消毒剂杀菌是吧,消毒剂杀COVID-19是吧那你Votab的时候是不喜欢这个视频的还是不喜欢这个内容的其实有很多误杀的这也是正常的好,这块就 [85:00] Personal Recommendation Engine就做完了其实这块如果仔细看的话没有很多 Machine Learning 就是您可以您可以不做那么多 machine learning 做到哦可以不做那么多Machinarling做的有人问我做推荐系统有前途吗?我个人觉得没有前途。我观点比较直观就是如果你想你自己是一个开企业的话比如说我自己我自己开企业,我做YouTube是吧?哦我做 YouTube 我可以很快的就把这个实践一遍然后就是把这个 Collaborative filtering最原始的技术,可能十几年前的一个公式套一下那我这个推荐系统本身就很好了当你做这个推荐系统你要去优化的时候,你做这个recommendation systemoptimization 的时候,你可能需要大量的这个PhD 去优化,是吧,你需要大量的PhD,专门做这个research 优化但你这个优化带来的benefit,是margin benefit,就是非常非常小的一个benefit,是吧,你实际上之前是90%的就是relevant,然后你把它input到95%了这个其实算是很重要,在user数量非常大的时候很重要,但是如果你是,那你的贡献肯定不如从0到90的这部分吗?从0到90就可以快猛操的用什么多少年前已经证明的技术已经搞定了吗?这是这点。同样的东西可以应用在多个方面,比如说,我们上周讲了这个现在很多SQL Server已经开始用PG有很多Hedge Fund trading已经开始用FPGA来优化了那你做FPGA有前途吗?我觉得也是没有前途,因为你这个是非常钻的一方向了,就是你能带来能带来非常小的优化,比如说做FPGA,优化FPGA做Hedge Fund,能带来非常小的优化但是你这个优化从0到95其实已经别人做了,你是从95到97的这一步优化,其实这个有没有那么相关,当你经济不好的时候肯定优先砍的是这一块嘛。当你经济不好肯定优先砍的是这一块嘛。但是这个FPGA就还是另一双,因为这个Hedge Fund里面做Hedge Fund的话,一毫秒的时间差,可能有几百个million的损失,这个可能是另说了和这个business case有关,但是你可以把自己想化成就是你run一个企业的话,你是更在乎从0到95的优化从无到有呢,还是从95到99这块。可以思考一下,甚至到后面优化可能从99到99.5这种优化好,Recommendation system这块有什么额外的问题吗?然后我觉得很多问题想的时候就是您可以把它想的简单一点嘛,比如说有些问题你需要换一个思维想比如说你是你现在是员工但你想你自己是老板的话你想一下或者换一个角度想一下思考一下需要有些思维代入什么的但是很多问题其实还是比较比较,就是思考也还是比较明显的,比如说这就关于读PhD的问题啊,很多人写过关于PhD,我记得我当时犹豫了很久,读不读PhD呢?当然最后没有读的原因是没有申请到,但是最后没有读的原因是没有申请到,毕竟我成绩比较差一点,因为乔科太多了,成绩比较差一点。然后这个,然后但是你思考一下,就是你去做phe优化的话是,就是在一个方向优化的话,优化了最后是带来一个margin的这个implement那你实际上不是一个fundamental的这个fundamental从0到90,你是从90到95,从95到99,甚至从99到99.5,这个优化其实就比较margin一点就比较小一点了嗯谢谢大家好,我们接着看吧,最后是讲 Streaming 这块。其实 Streaming 这块是非常简单的,我开始的时候,这个Streaming 那块怎么设计 我想了 前后犹豫了半天 但我后来讲了一下 其实非常简单Streaming 这块常见的 feature 比如说 training video, training topic, streaming, live chatLamchanger 弹幕 实时弹幕你这个training video 和training topic 如果我们在之前的设计的话是有这个user activity 的你其实加一个flink就可以了,flink就是real-time state for computation on top of Kafka你实际上就是有个rolling window计算一下,你有一个24小时rolling window计算一下 [90:00] 哪一个topic view量更多或者哪个topic like 让更多,或者哪个topic view和like结合起来更多,是吧?或者是哪个video view like结合起来更多一个flink就够了不需要任何额外复杂的东西,实际上就够了。你可能需要这个Data,放到那个Analytic Database里面,你后面做分析,哪个内容更喜欢什么的,哪个内容更容易popular的这种。你可能需要 generate insights,就是analytic的那一部分但如果你只是满足这个Trending Video Topic Feature 的话,包括你这个微博的这个trending topic你就完全做一个flink就可以了你把所有的东西变成一个log 所有东西变成log然后你在上面加一个flink,然后就rolling window generate popularity就可以了,就是把那个 popularityRank一下就可以了,不复杂,可能几半行扣就搞定了然后 Streaming 这款的话 YouTube 也是有 Streaming 的 YouTube Streaming 也是有的有多种方法做,像我们之前说的豆鱼的streaming就做得非常简单,就是不停的就是,你是有一个web socket,然后不停的碰到一个那个不停的把 dataPipe 给你,不停地把 data web socket 传输为你就可以了,这是同一个file。然后这个Twitch streaming 呢,它实际上是不同file,Twitch streaming 其实是不同file,它有不同的设计。然后我这个设计呢是,我记得可能是参照那个斗鱼的和Do有点像,但是我还是分成不同的file,我觉得分成不同的file好一点感觉。然后这块的话如果你是 streaming 按我们之前的设计的话 你需要prefill一些meta data 比如说你这个streaming topic 是谁是哪个user开始streaming的?然后你这个streaming label是什么?需要prefilm一些,比如说你是直播游戏的,还是直播什么直播什么带货的什么是吧然后你还直播什么妹子什么是吧,你就需要有一些prefuel topic,然后你就要件这个thumbnail 是吧让你这个stream searchable,然后呢,你的data呢,是你的那个streaming的那个video data呢,是首先是pipe through一个web socket到server的然后呢,server呢会broadcast,就是server会,如果你要需要存的话,像YouTube直播完了以后会存成video的话,你这个server其实不仅需要broadcast,你还要把它存下来所以现在你的影片 clip如果你不需要存的话,你就直接放到CDN上就可以,就是直接就放到CDN写。然后你当前这个Video Clip呢,你是可以就是你可以生成下一个video clip pointer,但是下一个video clip pointer其实是没有video的。你知道吧,就是比如说我现在直播,现在是7分08秒的直播,我可以生存7分09秒的video clip pointer,就是URI,但是那个URI里面是没有video的。但当我deliver这个7分08秒的video clip的时候,你看到7分08秒的视频,你是有7分09秒的视频的Pointer的豆乙是这么做的,我当时看豆乙的时候,我研究一下豆乙是这么做的所以当你open这个斗鱼的时候,你实际上会get,就是你从那个斗鱼的website里面,你会得到current clip 的这个CDN的地址,然后呢,你所有的subsequent read,比如说我看七分零八秒,我看完七分零八秒的视频,我在看七分零九秒的时候,我就根据上一个视频的next pointer,我就去看七分零九秒的视频了。那我就不需要再去斗鱼的server读了,我需要一直所有的request,以后的request都读的cdn server了。我就不去斗鱼的server读现在在哪。如果我这个connection loss的话,比如说我看斗鱼connection loss的,我想reconnect,那我就可以点下reconnect,我就看到斗鱼就反馈我当前的clip URL。那我就接着下一个读,接着下一个读,接着下一个读。然后当我send这个video live chat的时候,就是实时弹幕的时候,它也会被存储下来。和这个我伸的弹幕的时候它是和Video Clip ID 存下来的,可能还有一个timestamp那当时如果说我是Streamer,我是那个直播的那一人当我直播视频的时候这个实时弹幕是在一个short and thrashcode之间,比如说这个弹幕是5秒钟之前发的。对因为你肯定是先把你的视频直播出去,别人看到你的视频,然后留弹幕所以到我直播视频,比如说现在是7分,我举个极端例子,比如说这个stretch hold的是5分钟,我现在是7分09秒的视频直播,那我这7分09秒传到你那里可能是7分10秒是吧?然后你传回我弹幕是7分12秒7分12秒还在5秒这个stretch hold之间所以就显示给我如果你传回我弹幕的时间是7分19秒已经超过这个stretch hold我就不显示回来了这样的话这个弹幕感觉是有一定的实时性的但是如果我是个视频观看方,是个viewer,我就只是看斗鱼视频的话,我其实看的时候是有几秒钟延迟的 [95:00] 延迟多一点可能延迟少一点对吧,如果延迟多一点的话它这个data就更就是也没有什么额外的好处,可能延迟多一点,可能延迟少一点。当你有延迟的时候,你Live Chat实际上就可以更精确的显示在什么时候发的,是吧?比如说这个我发live chat的时候7:09秒,但我显示的时候也是7:09秒,就显示更精确一点然后说这个CDN server里面存video到file的话从video到file的话,那个video,刚刚讨论的videoupload的processing community怎么联系没有联系啊,你看直播视频的时候,你实际上就看到一大堆CDN传你的file,你没有看到任何你没有看到任何多余community的,多余community是单独的service这两个Service是完全分开的包括这个Video Upload Processing 也是完全分开的我们想一下之前那个video upload processing,它是为了generate什么?为了generate video subsnale,是吧?如果你在直播的时候你自己定义了Thumbnail,你都不需要 generate thumbnail,他还做什么,他还做这个video这个metadata的search是吧,如果你在直播之前已经把这个meta-data search弄好的话,他是不需要做这个search的。然后还做什么做compress 是吧,那你直播的时候也可以做compress,你边直播边传输的时候边compress嘛,只不过是现在就是就是把那个时间长的需要时间长一点的处理全部全部就是稍后做了,你比如说你这个,你还是可以generate video thumbnail 是吧,但你video thumbnail 你就有一定延时吗,比如说你是现在是7分12秒,显示的video thumbnail 是7分09秒的,那你不是有延时吗,还是可以做的,还是都可以做的。是没有冲突的和 video community 也是没有冲突的我就是如果你把这个YouTube斗鱼看成一个问题来处理的话是极其复杂的问题,是非常非常复杂的问题,你想把所有的fasher设计变成非常非常复杂,不要太复杂。但是你如果,我思考了一下,如果把它分成四个问题,separate concern,分成四个问题吧,其实每个问题都不是太复杂,是吧?我们看video upload和processing那这个问题不是太复杂我们看这个 comments user profileConnection,Transaction,不是,Channels什么的,UserActivity,Community这块也不是太复杂,我们单独看Recommendation System也不是太复杂是吧,然后再看Streaming System,我觉得Streaming其实相对来说是最简单的一部分,就是都不太复杂的,这个Streaming 简单也是可以理解的,因为我记得我早些年时候喜欢看那个星际的视频,星际写说有个星际写说叫好黄老先 黄老先我不要穿什么来着我忘了谢谢大家他当时是个星际解说,他是玩游戏的一个职业解说,然后他早时候讲他的故事说,有人特别喜欢,就是有人想他他做一个职业的星际直播视频,只做星际直播。你想如果只做新细直播视频的话,其实它这个技术复杂度一定不会太高,它不是这种职业的这种,它不是专业的程序。如果我们看的话,如果你用这个CDN提供的API的话,如果你用这个CDN线程直播的这个API的话,实际上你就写一些简单的这个简单这个Configuration, Crude, UI 就可以了,其实根本你都不需要backhand的你都不需要backhand的吧,你说的东西都在cdn上,你最多backhand弄个user login就可以了是吧?如果你是不login的user的话,就更简单,连backhand都不需要,你就有个UI就可以了。所以这个直播其实是没有什么技术含量的,我个人觉得直播是没有什么技术安排的,我个人觉得。好,这就是我说要聊的吧,基本上就是把这个问题分成四个方向了。把它分成四个子问题的话,其实每个问题都不复杂。并且你会觉得自己都想动手写一个YouTube,写一个YouTube是吧?自己都想动手写一个YouTube,因为其实每个问题真的都不复杂。OK这就是要说的,然后这里面就可能设计的话把它变成四个子问题的话,每一部分设计都有一些有点有趣的地方。然后还是起见设计中一个separate concern嘛然后可能需要自己做点调研嘛然后这里面有很多knowledge,比如说这个collective filtering,elastic search很多是我上学的时候学过的课啊或什么的 [100:00] 然后大家如果有更好的design的话也可以说一下然后有一些东西我还是没有production经验的比如说这个recommendation system我从来没有做过recommendation这都是我上学时候的knowledge所以可能如果有更多production经验的话或者有更多industry 经验的话可以提供一些细节然后然后我记得我们这里面有人在YouTube工作王赵宇在YouTube工作ciamo谢谢大家好像不在了,那等他有在的话,我可以问问他就是哪一块设计的可以更优化一下如果没有问题的话就到这里吧,反正YouTube还是挺有趣的,我下周的话讲lead code,其实lead code我觉得更简单一点,就是嗯Lead code讲完了以后,我可能就是安排大家互相interview,就是互相design设计一下,因为我觉得这个需要练习一下,就是你练习一下怎么样设计,问一个问题,然后回答一下,然后看到其中的难点和问题。我觉得这个如果就是就是希望大家联系大家,派大家一下,可能分成三个组是吧三个组然后问同样的问题,然后我们看一下,review一下到时候review一下系统设计中,如果你真的去系统设计常见的问题是什么我个人是不太care interview,我care的是怎么样,就是这个思维的,所以这个,所以,毕竟这个,还有很多时候是为了帮助大家就是,就是有人有疴症找工作需要嘛,所以还是可能下下走吧,下下走以后就是把分成几个组,然后问一些interview的问题,然后看一下,我会自己写一个我自己的recommended solution,然后分成三个组是吧,然后有三个被面试的人,然后看他们三个人什么回答的,然后再对比一下,看一下就是有什么不同,哪些地方设计的好一点,哪些地方设计的更有问题一点然后是这样子,然后周六的话我就不讲了,下周的话改成周二和周四啊,就是这样的话我时间好安排一点。最二的话是讲系统设计这个System Design就是这种类似系统设计,周四的话接着讲这个Design Data Intensive Application的这本书。好,就到这里吧,谢谢大家。谢谢大家谢谢大家