我们刚刚发布了一个新的 ScyllaDB 示例应用程序,一个视频流应用程序。该项目可在 GitHub 上获取。该博客介绍了视频流应用程序的功能和技术堆栈,并详细介绍了数据建模过程。
Video 流媒体应用功能
该应用程序采用简约设计,具有最基本的视频流应用程序功能:
- 列出所有视频,按创建日期排序(主页)
- 列出您开始观看的视频
- 观看视频
- 从上次停下的地方继续观看视频
- 在每个视频缩略图下显示进度条
技术堆栈
- 编程语言:TypeScript
- 数据库:ScyllaDB
- 框架:NextJS(页面路由器)
- 组件库:Material_UI
使用 ScyllaDB 实现低延迟视频流应用
ScyllaDB 是一款低延迟、高性能的 NoSQL 数据库,与 Apache Cassandra 和 DynamoDB 兼容。它非常适合处理视频流应用程序的大规模数据存储和检索要求。 ScyllaDB 具有所有流行编程语言的驱动程序,并且如本示例应用程序所示,它与 NextJS 等现代 Web 开发框架很好地集成。
视频流服务中的低延迟对于提供无缝的用户体验至关重要。为了为高性能奠定基础,您需要设计一个适合您需求的数据模型。让我们继续使用示例数据建模过程来看看它是什么样子的。
视频流应用数据建模
在 ScyllaDB 大学数据建模课程中,我们教导 NoSQL 数据建模应始终首先从您的应用程序和查询开始。然后,您可以逆向工作并根据要在应用程序中运行的查询创建架构。此过程可确保您创建适合您的查询并满足您的要求的数据模型。
考虑到这一点,让我们回顾一下我们的视频流应用程序在每个页面加载时需要运行的查询!
页面:继续观看
在此页面上,您可以列出他们已开始观看的所有视频。此视图包括视频缩略图和缩略图下的进度条。
查询:获取观看进度
从 watch_history 中选择 video_id,进度,其中 user_id = ?限制 9;
架构:观看历史表
创建表 watch_history (
user_id 文本,
video_id 文本,
进度 int,
watch_at 时间戳,
主键(用户 ID)
);
对于此查询,将 user_id
定义为分区键是有意义的,因为这是我们用来查询观看历史记录表的过滤器。请记住,如果有查询需要过滤 user_id
之外的其他列,则稍后可能需要更新此架构。但就目前而言,此架构对于定义的查询来说是正确的。
除了进度值之外,应用程序还需要获取每个视频的实际元数据(例如标题和缩略图)。为此,必须查询“video”表。
查询:获取视频元数据
从视频中选择 * WHERE id IN ?;
请注意我们如何使用“IN
”运算符而不是“=
”,因为我们需要获取视频列表,而不仅仅是单个视频。
架构:视频表
创建表视频 (
标识文本,
content_type 文本,
标题文字,
网址文本,
缩略图文本,
创建时间时间戳,
持续时间整数,
主键(id)
);
对于视频表,我们将 id
定义为分区键,因为这是我们在查询中使用的唯一过滤器。
页面:观看视频
如果您点击任何“观看”按钮,他们将被重定向到带有视频播放器的页面,可以在其中开始和暂停视频。
查询:获取视频内容
从视频中选择*,其中 id = ?;
这是一个与“继续观看”页面上运行的查询非常相似的查询。因此,相同的架构也适用于此查询。
架构:视频表
创建表视频 (
标识文本,
content_type 文本,
标题文字,
网址文本,
缩略图文本,
创建时间时间戳,
持续时间整数,
主键(id)
);
页面:最新视频
最后,让我们分解一下“最近的视频”页面,它是应用程序的主页。我们最后分析这一页是因为从数据建模的角度来看,它是最复杂的一页。此页面列出了数据库中可用的十个最近上传的视频,按视频创建日期排序。
我们必须分两步获取这些视频:首先获取时间戳,然后获取实际的视频内容。
查询:获取最近十个视频的时间戳
从最近的视频中选择 id、top10(created_at) 作为日期;
您可能会注意到,我们使用了一个名为 top10()
的自定义函数。这不是 ScyllaDB 中的标准函数。这是我们创建的 UDF(用户定义函数)来解决这个数据建模问题。此函数返回表中最新 created_at
时间戳的数组。 在以下位置创建新的 UDF ScyllaDB 可以成为解决您独特的数据建模挑战的好方法。
这些时间戳值可用于查询我们想要在页面上显示的实际视频内容。
查询:获取这些视频的元数据
从最近的视频中选择 * 在哪里创建的?限制 10;
架构:最近的视频
创建物化视图recent_videos_view AS
从streaming.video中选择*
其中created_at不为空
主键(created_at,id);
在最近视频的物化视图中,created_at
列是主键,因为我们在第一个查询中按该列进行过滤以获取最新的时间戳值。请注意,在某些情况下,这可能会导致-node-check/”>热分区。
此外,用户界面还在每个视频的缩略图下方显示一个小进度条,指示您观看该视频的进度。要获取每个视频的此值,应用必须查询观看历史记录
表。
查询:获取每个视频的观看进度
从 watch_history 中选择进度,其中 user_id = ? AND video_id = ?;
架构:观看历史记录
创建表 watch_history (
user_id 文本,
video_id 文本,
进度 int,
watch_at 时间戳,
主键(用户 ID、视频 ID)
);
您可能已经注意到,观看历史记录表已在之前的查询中用于获取数据。现在,必须稍微修改架构以适应此查询。让我们添加 video_id
作为聚类键。这样,获取监视进度的查询将正确工作。
就是这样。现在,让我们看看最终的数据库架构!
最终数据库架构
如果不存在则创建密钥空间使用复制进行流传输= { 'class': 'NetworkTopologyStrategy', 'replication_factor': '3' };
创建表streaming.video (
标识文本,
content_type 文本,
标题文字,
网址文本,
缩略图文本,
创建时间时间戳,
持续时间整数,
主键(id)
);
创建表streaming.watch_history (
user_id 文本,
video_id 文本,
进度 int,
watch_at 时间戳,
主键(用户 ID、视频 ID)
);
创建表streaming.recent_videos(
标识文本,
content_type 文本,
标题文字,
网址文本,
缩略图文本,
创建时间时间戳,
持续时间整数,
主键(创建时间)
);
最近视频页面的用户定义函数
这个UDF使用 Lua,但您也可以使用 Wasm 在 ScyllaDB 中创建 UDF。创建函数时请确保在 scylla.yaml 配置文件中启用 UDF(位置:/etc/scylla/scylla.yaml):
克隆存储库并开始!
开始…
克隆存储库:git clone https://github.com/scylladb/video-streaming
安装依赖项:npm install
修改配置文件:
APP_BASE_URL="http://localhost:8000"
SCYLLA_HOSTS="172.17.0.2"
SCYLLA_USER="scylla"
SCYLLA_PASSWD="xxxxx"
SCYLLA_KEYSPACE="流式传输"
SCYLLA_DATACENTER="datacenter1"
迁移数据库并插入示例数据:npm run migrate
运行服务器:npm run dev
总结
我们希望您喜欢我们的视频流应用程序,它可以帮助您使用 ScyllaDB 构建低延迟和高性能的应用程序。如果您想继续学习,请查看 ScyllaDB 大学,我们在 数据建模、ScyllaDB 驱动程序 >,还有更多!如果您对视频流示例应用程序或 ScyllaDB 有疑问,请访问我们的论坛,让我们讨论!
更多 ScyllaDB 示例应用程序:
相关资源: