shorten URL
assume one user shorten URL twice a day.
assume we have
redirect URL
assume one user redirect shortened URL 10 times a day.
shortenURL(user_id, original_url)
shortenURL(user_id, original_url, customized_url)
redirectURL(user_id, short_url)
We should have a database that maps from short_url to original_url.
The schema looks like
All the requests will first go through load balancer to evenly distribute the workload among services. We can also add a rate limiter there to restrict user requests to mitigate abuse.
The shortenURLService is handling the request of shortening the URL. It stores the shortened URL to original long URL mapping in the database. The database will push the frequently accessed URLs in the cache.
The redirectURLService is handling the request of redirecting to original URL. It looks up the cache first and then check database if cache is missing this data to get the original URL. It then redirect users to the original URL.
To shorten the URL, a request will first go through rate limiter to make sure that not a high burst of requests go to the service. It can go through the load balancer to be served by a server. If a customized short url is not provided, it generates the unused short URL and stores the mapping from short URL to long URL in the database. Then server returns short URL to user.
If a customized short url is provided, the server should first check if the short url exists. We can utilize bloom filter functionality to check if a short URL exists. If it exists, the server returns error. If it doesn't exist, the server stores the mapping in the database and returns success.
To redirect the URL, the request also goes through rate limiter and then load balancer to be served by a server. The server checks the cache (then database if needed) to get the mapping original URL. If it exists, then redirect. If it doesn't exist, then return 404 NOT FOUND.
How should we shorten the url and also make sure the url is unique?
And we also need to make sure that users cannot see the pattern.
We can use base64 encoding to encode the original long URL. That way a long URL is shortened and will always be translated to the same shortened URL.
We also need to check if a customized URL is already used. We can use bloom filter. For bloom filter, we have multiple hash functions and we maintain an array. We calculate hash values using those hash functions and mark those hash values in the array. For a given URL, we also check the corresponding hash values, if all of them are marked, then it's very likely that the URL is already used. Otherwise, we can use this URL. Using bloom filter can guarantee that a URL wasn't being used before.
For quick access and getting low latency, we should use cache.
For database, we can use no-sql database - key value store. The database should be partitioned where the partition key is shortened url. The database should also be replicated, following primary and secondary replication strategy. The write is written to primary. And read operation can be done through both primary and secondary nodes.
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?