Requirements:
- We have a list of users.
- For every user let us say, there are 2 types of rewards applicable.
- For each type there is a list of the rewards that need to be given out to the specific user.
- Every reward has a specific expiry, after which that reward, if not delivered, has to be dropped from the list of rewards.
Whenever we get a request, we have to reserve a reward for the user. Users can then claim the rewards later. While claiming, we just search for a reward from the list of rewards reserved for the users and deliver it.
Approach 1 We are thinking to store the data in the following format:
user_id
type_1
reward_1
reward_2
reward_3
type_2
reward_4
reward_5
reward_6
Here the number of keys would be limited and data representation is cleaner.
Challenges:
- How to expire the reward from the list of rewards. If I am using Redis, then in that case I cannot set a TTL on the rewards as TTL only works for the key, which is user_id in this case.
- Also, since we cannot expire the deals automatically, we will first have to remove all the expired rewards from the list, while delivering the reward, and then select one reward from the remaining non-expired rewards.
- When we deliver a reward, we have to remove that reward from the list. So every time we deliver a reward, we have to get the list and then push back the updated list, the original list -1 (the reward that was just claimed), to Redis to update the existing data.
- All these operations add to the overall latency of the delivery.
Approach 2 Another approach was making the reward a part of the key itself:
user_id:type_1:reward_1
user_id:type_1:reward_2
user_id:type_1:reward_3
user_id:type_2:reward_4
.
.
Here I can set the TTL for each reward.
Challenges:
- The number of keys would increase drastically.
- While actually delivering the reward, we only know the
user
and thetype
and not the actual reward. So we basically have to scan for all the rewards present for theuser
and thetype
and then get a list of all the rewards and then deliver one of the available rewards to the user. This increases the latency. The scan complexity isO(N)
.
What is the best way of structuring such data? How do we work on retrieving and updating the data with minimum latency? How do work on removing the expired records?