We have two primary stores, one fr storing videos and the other for storing video metadata. The data stores are detailed below.
Initially, a client requests to read data by connecting to a load balancer, which then forwards this request to a Server. The Server interacts with a Metadata database to access necessary metadata. For reading operations, the Server first attempts to retrieve the s3 url from a CDN; if the required data isn't available there, it proceeds to fetch the data from the metadata to get the S3 chunks.
For write operations, a client sends a write request to the LoadBalancer, which is then directed to a server. This server asks Zookeeper for a write node, receiving a node ID in response. With this ID, the server performs a stateful write operation and confirms the action back to the client.
When a client begins sending a video, the data is routed to a Stateful Node. This node is responsible for storing the raw video data in an S3 store and then sends the raw S3 URL for processing to an AWS SQS. An Encoding Worker retrieves this task from SQS, processes the video into S3 chunks, and updates the Metadata database accordingly.
The read flow updates the 'hotness' of the video and makes the adjustment for the CDN and how long the video should live in the CDN.
flowchart LR B[client] -- Read video/id --> C[LoadBalancer] C[LoadBalancer] -- credentials --> Q[Auth Service] Q[Auth Service] -- signed auth token --> B[Client] C --> D[Server] D[Server] --> Y[Metadata database] D[Server] -- READ | Queries metadata --> F[CDN] D[Server] -- READ | Requests data from S3 --> M[S3 Chunks] D[Server] -- video id not found --> B[client] A[client] -- write video data --> Z[LoadBalancer] --> I[Server] -- request write node --> K[Zookeeper] K[Zookeeper] -- provide node ID for writing --> I[Server] I[Server] -- write data to storage node --> A[client] A[client] <--> Q[Auth Service] A[client] -- stream video content --> U[Stateful Node] U[Stateful Node] -- upload raw data to S3 --> H[Raw S3 Store] U[Stateful Node] -- provide S3 URL for processing --> T[SQS] J[Encoding Worker] <--- T[SQS] J[Encoding Worker] --> M[S3 chucnks] J[Encoding Worker] --> Y[Metadata database]
In a system involving multiple components for handling read and write operations, as well as video processing, the sequence of interactions begins with a client initiating a read request. This request is first received by a LoadBalancer, which then forwards the request to a Server. The Server performs multiple tasks based on this request: it accesses a Metadata Database to retrieve necessary metadata, checks with a CDN (Content Delivery Network) for cached content ("READ | first here"), and accesses S3 Chunks for data not found in the CDN ("READ | go to s3"). It's noted that reads are managed through either the CDN or directly from S3 Chunks, depending on where the requested data resides.
For write operations, the Client sends a write request to the LoadBalancer, which again forwards this request to a Server. This time, the Server requests a write node from Zookeeper, a service that manages the distribution of write operations across nodes. Zookeeper responds with the node ID that should take the write operation. The Server then communicates back to the Client, indicating it can perform a stateful write.
When the Client begins sending a video, it directly interacts with a Stateful Node. This node is responsible for putting the raw video data into an S3 store designated for raw content. It also sends the raw S3 URL for processing to SQS (Simple Queue Service), which queues the video for processing. An Encoding Worker picks up this task from SQS, processes the video into S3 Chunks, and updates the Metadata Database with the new metadata related to the processed video. This series of interactions ensures that read and write operations, along with video processing, are efficiently managed across different components of the system.
sequenceDiagram participant Client as Client participant LoadBalancer as LoadBalancer participant Server as Server participant MetadataDatabase as Metadata Database participant CDN as CDN participant S3Chunks as S3 Chunks participant Zookeeper as Zookeeper participant StatefulNode as Stateful Node participant RawS3Store as Raw S3 Store participant SQS as SQS participant EncodingWorker as Encoding Worker Client->>+LoadBalancer: Read video LoadBalancer->>+Server: Forward read request Server->>+MetadataDatabase: Access Metadata Server->>+CDN: READ | Initial content load Server->>+S3Chunks: READ | Retrieve content from S3 Client->>+LoadBalancer: Write video LoadBalancer->>+Server: Forward write request Server->>+Zookeeper: Request write node assignment Zookeeper-->>+Server: Provide node ID for writing Server->>+Client: Confirm successful data write Client->>+StatefulNode: Begin video transfer StatefulNode->>+RawS3Store: Store video raw data in S3 StatefulNode->>+SQS: Dispatch S3 URL for further processing SQS->>+EncodingWorker: Notify of new processing task EncodingWorker->>+S3Chunks: Save encoded data chunks EncodingWorker->>+MetadataDatabase: Update video metadata
The first clarification is to ensure that whenever we are only polling from the SQS queue when the enqueuing service is ready to take the load. With that in mind, it's pretty obvious to ensure that the encoding service is able to read from the S3 bucket and process the video doing the following steps:
The second thing we would to focus on is our CDN design. To ensure the users have a good experience, we'd like to ensure that we can provide these core functionalities in our service:
The key idea is that we want to trade off write latency/consistency (writes can be really slow) for availability (our system relies on reading from highly available S3 service), latency (most of the 'hot movie chunks' are stored in our store in our CloudFront CDN), and durability - we persist the write in the SQS to make sure that the message is read at least once.
We do have eventual consistency in the system because we don't want to wait until MongoDB finishes replicating the metadata across all nodes before the video is considered available.
Additionally, we trade-off waiting until high resolution is available by allowing to see 140p encoded video which completes faster
1. We have quite a bit of single point of failure - which is our S3 bucket. If S3 is down, we pretty much can't do any reads or writes. The good part is that AWS S3 is highly available and that is not a major concern, but if it is down, it would bring the entire system down.
2. We can be also concerned that in case the authentication service is down, we would completely lose access to writes, but we don't have to completely lose access to reads. We can consider letting users watch the videos, even if they can't sign in.
3. Another point of failure/bottleneck is the availability and deployment of CDN, we would want to ensure CDN is deployed across the entire globe (as well as our database nodes are distributed) to minimize latency worldwide.