@klov i think it's as simple as this:
After you have updated a URL mapping, you delete it from memcached/redis.
Let's assume no sane person will try to do concurrent updates.
Still there is possible race condition: one process P1 reads old mapping from database and tries to update cache with it. Concurrently another process P2 updates database with the new mapping and tries to invalidate the cache. Race condition is possible that P2 deletes the key, and P1 after that writes the old mapping to the key. To prevent that, P1 should use "compare and swap" sort of command to avoid the race condition.
Why is there a loop? can you explain your design that can cause a loop?
browsers usually have a redirect limit. If the tinyURL service responds with HTTP 301 + shortURL, browser will redirect up to its limit, then throw 310 ERROR. also too many redirects will increase latency. IMO shortening tinyURL loses its original purpose, so shouldn't be allowed.
@imranmanzoor31 Your suggestion works for avoiding collisions, but it means that you must either perform 1 increment after each addition and store it for next time its called, or perform n increments each time a new url is added.
The first one does sound better than the second but you can still do much better by generating a key that can be greatly distributed among your storage space to avoid collisions most of the times and just perform increments each time you find yourself with a collision. Prime numbers will help you here and if you search a little bit on how the first hash algorithms were done you'll come across with number 31.
Lets say you start with an array of numbers, of size equal to the length of the string to be encoded, and where each number identifies a unique character.
Also lets assume that your maximum number of indexes is m, where m is also a prime number.
You could generate a key by summing the products of each of those numbers by your prime like in S = a*31 + a*31 + a*31 ... + a[n]*31, and then diving S over m for its reminder, R = S%m.
R would be your identifier and only if its already used you would perform increments until you find one available.