Assumptions:
Storage
Network
// Create and delete counters
POST /counters
{
name,
}
DELETE /counters/
// Increment / decrement / reset counter
POST /counters/
{
action, // increment | decrement | reset
value,
}
// Read counter
GET /counters/
For individual counters, our max read concurrency is 0.1 * 10 * 100 = 100 /sec. This is can be handled by redis, provided we shard the cache properly.
We choose redis. Say each instance can handle 100k/sec. On average each counter has 1 write/sec. so we fit 100k counters into each instance, we results in 1000 shards. In reality we probably don't need that number of shards. We should monitor memory and CPU usage to determine the actual number of shards needed.
APIGateway
Update service and queue
CounterService
ReadService
Update flow
Read flow
Redis
Update queue
We use redis as opposed to a DB for its performance, and because eventual consistency is acceptable.
UpdateService, CounterService and ReadService are stateless and can be horizontally scaled.
Redis
UpdateQueue
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?