Count concurrent requests.
The request could either increase or decrease the count.
Give back live results for the count.
High availability
Low latency
Eventual consistency (To ensure high availability and low latency, the system will choose eventually consistency approach, the actual count could be delayed by 2 or 3 seconds)
security
Assume 1B daily concurrent requests.
Then write QPS is 1B / 100k = 10k QPS.
Peak write QPS is 10k * 2 = 20k QPS.
Assume 10B daily read request to read the count.
The read QPS is 10B / 100k = 100k QPS.
Peak read QPS is 100k * 2 = 200k QPS.
POST writeCounter(string id, int count)
return success / error
GET getCount(string id)
return the current count
In my system, I used Redis Cache, Document DB and NoSQL DB.
From the capacity estimation, we know that the system have high peak read QPS (20k) and high peak write QPS (200k).
To ensure the low latency, I choose to use Redis Cache to store the count info for each
id. The Redis cache will ensure fast read and write.
The Document DB will store the snapshot of the aggregated info. The snapshot info is simple and fast to store because there is no query or calculation required.
The NoSQL DB will be used as the source of truth. The Snapshot counter service will read Snapshot from Document DB and aggregate the snapshot to calculate the accurate results of the count. Finally store the accurate result to the NoSQL DB.
In conclusion, the Redis cache will store a live and estimated count for low latency and high availability. The NoSQL DB will store the accurate count for the source of truth.
See Diagram
See Diagram
Counter aggregate service:
The service is used to aggregate the count requests. The service use map reduce patterns to aggregate the count. The service could be sharded by id. So the same id will go to the same pod. The count will be aggregated by either 1 minutes, 5 minutes or 10 minutes or 1 hour (configurable, depends on the requirement). The aggregated count will be published to the message queue. The message queue is used to buffer the traffic in case the peak traffic is very high.
In my system, I used Redis Cache, Document DB and NoSQL DB.
From the capacity estimation, we know that the system have high peak read QPS (20k) and high peak write QPS (200k).
To ensure the low latency, I choose to use Redis Cache to store the count info for each
id. The Redis cache will ensure fast read and write.
The Document DB will store the snapshot of the aggregated info. The snapshot info is simple and fast to store because there is no query or calculation required.
The NoSQL DB will be used as the source of truth. The Snapshot counter service will read Snapshot from Document DB and aggregate the snapshot to calculate the accurate results of the count. Finally store the accurate result to the NoSQL DB.
In conclusion, the Redis cache will store a live and estimated count for low latency and high availability. The NoSQL DB will store the accurate count for the source of truth.
To store the source of truth, I choose to use NoSQL DB instead of SQL DB. I reason I use NoSQL DB is that the data is key-value based, it is not structured data. Another reason is that NoSQL DB has high performance for both read and write.
Our non-functional requirements for the proposed twitter system design are scalability, fault tolerance, availability, and low latency. Let’s discuss how the proposed system fulfills these requirements:
What are some future improvements you would make? How would you mitigate the failure scenario(s) you described above?