-> The users can create easily a CDN providing its origin servers and define authentication and authorization restrictions.
-> The CDN servers are distributed across the glob serving content from most nearest geographical edge server.
-> The edge server will cache the content from origin server to be used for further requests.
-> Monitoring tool of the solution will dictate if the edge servers from a location should be scale up or down.
-> The CDN should authenticate and authorize the clients requests
-> Updating content at origin should allow the users to propagate and invalidate cache
-> The system should be highly available since are used by customers.
-> The system should be reliable and provide fast updates of the cache in the edge servers.
-> The system allows a eventual consistency model since the changes are propagated at the edges.
-> Reliability is one of the key non functional requirements since the system should be fault tolerant and monitored.
-> Security should be enforced so that only authenticated and authorized clients can retrieve the data.
Let's suppose that we have 100K customers with each having 5 origin servers each containing 1K items, each origin server holds 10Gb of data. ~10 MB per file.
Daily active users updating or creating these data are 100 K each doing 5 requests per day.
500 K requests of cache invalidation/day ~5 req/s.
Cache invalidation data are 100 bytes each holding information like: customerId (8), timestamp, path or regex expression (50). => 50Gb data daily.
10 million daily unique clients around the globe are requesting these data, each client do 100 requests with the probability of requesting 20% of the saved content -> 20% from a total of 500 000 000 items => 100 million items /day each item has 1MB => 100TB data/day stored in edge cache=> 1000 000 000 MB /day
with a bandwidth of 10GB/s.
100TB of items per day can be handled with 100 edge servers around the globe each handling 1TB of data.
-> POST /api/create-cdn with requests data
{
"customerId": uuid,
"cdn _name": string(100),
"regions": [string, string]
"HTTP_origin": link_url
}
with the response data, where resource_available represents the GET by Id url, the domain is the Front end domian.
{
"id" : uuid
"resource_available": link,
"domain" : string
}
-> GET /api/cache?server_id=uuid
returns a list of all resource cache in this server.
-> POST /api/cache/invalidate
{
"pattern": string,
"user_id: uuid,
"cdn_id": uuid -> the id of the CDN resource targeting.
} - response 200 OK.
-> PUT /api/content
{
"user_id": uuid,
"content_id": uuid,
"cdn_id": uuid
} -> 200 OK will invalidate the old cache for the content already cached
Metadata of the created cdn for customers can be stored in an SQL database
Index on content (content_id, region) to be able to easily spot the edge_server.
invalidated_cache pattern will be stored on the each edge server being propagated after publish an invalidated cache item.
For this kind of job I will choose multiple kind of databases: SQL strong consistency for content metadata and where is cached like POSTGRESQL, and No-Sql key-value : Redis for invalidate cache action.
-> Load balancer will be used to distribute the trafic between multiple instance of the same type, can use geo location
-> Route manager can be handled along with a Geo location server to determine and assign the edge server
->Upload service will be used to create an CDN and distribute for the content for edge server
->Invalidate cache will be used to publish an invalidation of the cache using a resource url pattern: cache here is used data stored in edge servers
-> queue service will be used to spreah cache invalidation towards edge servers
-> Cache service will be used to store route information and which server handle for a region different content. The cache items will be cached using a TTL duration for items in cache.
Explain how the request flows from end to end in your high level design. Also you could draw a sequence diagram using the diagramming tool to enhance your explanation...
Sharding: Use of an hierarchical servers for regions. Each region will have 1 master Route Manager and depending on how many requests for region will come, will create other Route Managers or shards for a region. The route manager can use Consistent hashing to decide which is the edge server that will handle the request for content. The edge server will search in memory where will have saved all the data, or retrieve it from origin.
Lazy loading for propagating cache invalidation: When a cache invalidation will come the pattern of the url will be published to servers in all regions instead of trying to delete all the content saved in all data. When a new request comes from the clients it checks if the url matches one of invalidated patterns, then it deletes the content, and retrive a new copy from origin.
LRU cache in edge servers: The edge servers will be managing the content served using an expiration policy and also Least Recently Used pattern to managed the content saved.
Lots of tradeoffs made using a combination for database: SQL and No SQL used only for cache invalidations. Replication of SQL server should be made to obtain high availability.
Route manager replications for and sharding between different regions. Resilient and fallback strategies should be developed to replace
Queue I will choose Kafka to publish new content or cache invalidation since it provides the best performance and cache invalidations can be replayed.
The solution provides High availability and extensibility since the number of edge server can grow and each region can be split in sub-regions and attached other edge server with other route managers.
Database outage of the routing data.
Cache with routing data can be overwhelmed when multiple items expire from cache leading to a caching stampede problem.
Get metrics of each edge server, and develop capacity planning strategies