Read-Heavy Nature:
Traffic Estimates:
Copy code
100 * 500M = 50B
Queries Per Second (QPS) Calculation:
bash
Copy code
500 million / (30 days * 24 hours * 3600 seconds) ≈ 200 URLs/s
bash
Copy code
100 * 200 URLs/s = 20K/s
Storage Estimates:
Copy code
500 million * 5 years * 12 months = 30 billion
python
Copy code
30 billion * 500 bytes = 15TB
Bandwidth Estimates:
bash
Copy code
200 * 500 bytes = 100KB/s
bash
Copy code
20K * 500 bytes = 10MB/s
Memory Estimates for Caching:
bash
Copy code
20K requests/second * 3600 seconds * 24 hours ≈ 1.7 billion requests/day
python
Copy code
0.2 * 1.7 billion * 500 bytes ≈ 170GB
High-Level Estimates Summary:
Function: createURL
Parameters:
api_dev_key (string): The API developer key of a registered account, used for throttling users based on their allocated quota.
original_url (string): The original URL to be shortened.
custom_alias (string, optional): A custom key for the URL.
user_name (string, optional): A user name to be used in the encoding.
expire_date (string, optional): The expiration date for the shortened URL.
Returns:
On success, returns the shortened URL.
On failure, returns an error code.
Function: deleteURL
Parameters:
api_dev_key (string): The API developer key of a registered account.
url_key (string): The key of the shortened URL to be deleted.
Returns:
On success, returns ‘URL Removed’.
On failure, returns an error code.
Abuse Detection and Prevention: To protect against abuse, such as a malicious user consuming all available URL keys, we can implement rate limiting based on the api_dev_key. Each developer key can be restricted to a certain number of URL creations and redirections within a specified time frame, which can be configured differently for each developer key.
Data Observations:
Database Schema:
We will need two tables:
Database Choice:
Given that we expect to store billions of rows and do not require relationships between objects, a NoSQL database such as DynamoDB, Cassandra, or Riak is ideal. These NoSQL databases are also easier to scale, making them suitable for our needs.
The challenge is to generate a short and unique key for a given URL. For example, the shortened URL "https://tinyurl.com/vzet59pa" has "vzet59pa" as the short key. Here are two potential solutions:
http://example.com?id=design vs. http://example.com%3Fid%3Ddesign) should be treated as identical.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...
Data Partitioning and Replication
To scale our database for storing billions of URLs, we need an effective partitioning scheme to distribute data across different database servers.
a. Range-Based Partitioning:
b. Hash-Based Partitioning:
Cache
We can improve performance by caching frequently accessed URLs using a solution like Memcached, which stores full URLs and their hashes. Application servers can check the cache before querying the backend storage.
Load Balancer (LB)
We can implement a load balancing layer at three key points in our system:
Initially, we could use a simple Round Robin approach to distribute incoming requests equally among backend servers. This method is straightforward to implement and introduces minimal overhead. Additionally, it automatically removes a non-responsive server from the rotation, preventing it from receiving traffic.
However, the Round Robin approach does not account for server load. If a server is overloaded or slow, it will still receive new requests. To address this, we can implement a more advanced load balancer that periodically checks the load on backend servers and adjusts traffic distribution accordingly.
Purging or DB Cleanup
Should entries remain indefinitely, or should they be purged upon expiration? If a user-specified expiration time is reached, how should the link be handled?
Telemetry
To track how many times a short URL has been used, user locations, and other statistics, consider how to store this information. If we update a database row for each view, it may not handle a high volume of concurrent requests for popular URLs efficiently.
Statistics to track include:
Security and Permissions
Can users create private URLs or restrict access to specific users?
We can store the permission level (public/private) with each URL in the database. Additionally, a separate table can store UserIDs that have permission to access a specific URL. If a user without permission tries to access a URL, we can return an HTTP 401 error. In a NoSQL wide-column database like Cassandra, the table storing permissions would use the URL 'Hash' (or KGS generated 'key') as the key. The columns will store the UserIDs of users who have permission to access the URL.
Explain any trade offs you have made and why you made certain tech choices...
Try to discuss as many failure scenarios/bottlenecks as possible.
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?