List the key functional requirements for the system (Ask the AI for hints if stuck)...
List the key non-functional requirements (performance, scalability, reliability, etc.)...
For such system, I can think the task creation or delte frequency is low, while the task execution frequence and concurrency is high.
A task representation can be like below:
1 record consumes just 1KB data, if there are total 10k tasks, then I only need 10MB storage.
A task execution record can be like:
Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
For task:
create_task
params:
response:
delete_task
params:
For task execution:
create_task_executions:
params:
response:
get_task_execution:
params:
update_task_execution:
user
tasks
executions
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
The system contains the following components:
To create, delete or get task record.
To create task execution, or update task execution state.
Based on task's scheduling policy, create the specific executions.
Monitor the executions to be executed in near future, and push the message into the queue.
Execute the schedule task executions, and update the execution status.
Decouple the scheduler and execution workers, make them can scale independently.
And the following are external components which may not be maintained by us:
Notify the task's owner that the task execution state.
The real process to run the task, it may be a k8s job, or some async job system.
To clarrify the system's running process, let's summarize what happends for a user submitted scheduling task:
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
To achieve minimal delay in the system, I will apply cache with database for the task service and execution service:
Execution service is the possible bottleneck, let me introduce it in detail:
The API `create_executions` with until may be invoked frequently by the Execution monitor.
It will store a task's record inside database, if new executions are created, then the task record's last_schedule_time will be updated, then the cache item is removed. If no new executions need to be created, then the task record will be write into the cache if it doesn't exist.
And the execution's record will also be written into the cache after it's updated, so that the query will be efficient.
Execution monitor is a stateless process, and it will check to-be-executed executions in the near future periodically. I can deploy multiple instances for high reliability, and each of them works independently. And they use row-level locking in the database to avoid duplicate execution messages. If an execution state is already SCHEDULED, nothing will happen.
Its logic is as follows:
```
// find all to-be-executed executions in the near future
// randomize the executions
// iterate every execution
// lock the execution row
// if the execution state is already SCHEDULED, abort
// create the execution message
// update the execution state
// commit the DB update
```
This is row-level locking, so the execution creation can run with high concurrency.
The scheduler is very similar to the execution monitor for high performance and reliability. It will check the task record row and lock it to call `create_task_executions`.
The number of current-to-be-executed tasks in the system may not be stable; at times, it may be very small, while at other times, very large.
I can create a monitor service to monitor current tasks to be schedule and executions to be executed in near future, then create a auto-scale policy on this, then to optimize our system's cost.
The system's execution data is massive, for example 10 0k rows every day, but the execution records will not be used for scheduling after the execution finished. We can move the finished execution data every week or month to the archive storage for lower cost and higher performance of the DB.