System Design Examples
System Design Examples
***********************************************************************************
*********************
-> user location will go to location service and then mapped to correct shared
where a filtering logic will show 10 nearest driver to rider
-> each shard has 1M/10 = 100K users (filter 10 pointes nearest to (x,y))
-> indexing at position in db will increase req timeouts for drivers so we will use
CQRS
-> driver location will be stored in db in normal fashion ; there will be one more
db that will query everything in every 5 seconds from that db and put it in a db
with indexing
-> that will be done with help of indexing worker process
=> drawback : delay between driver location updation and user reading ; number of
indexing as it is expensive
note : polling
-> rider connect with driver gateway socket and ask matching service to fetch and
book one out of 10 nearest cab
-> matching service ack the rider
-> then after an interval rider keep on asking if cab is booked and matching
service either responds no / driver details
***********************************************************************************
***********************************************************************************
*********************
=> when the user will open the app and click on one of his friend, then all the
messages sent by user and recieved by user should be fetched with pagination
note : db design
-> from_uid ; to_uid ; message ; sent_at_time
=> each query will be run on uuids of sender and reciever => indexing at uuids will
increase the query speed
2) number of request
-> number of fetch per minute : (total open chats * number of times fetch gets
called in a minute) => 1000000 * (60/5)
-> number of fetch per second : 200k select per second
=> it is very bad performance
*) scalable reads
i)
-> it happens because we are pulling/fetching the messages every 5 seconds
-> instead of that we can use web sockets to directly push the message to the user
***********************************************************************************
***********************************************************************************
*********************
note : problem
-> extraction of new url and fetching new url is synchronous
-> fetching of content and storing is synchronous
=> using queues at both the places will make it async and efficient
=> url extractor and indexing service will be subscribed to content queue
-> get url -> fetch content -> push queue -> indexer
-> get url -> fetch content -> extract new urls -> push queue -> get url
***********************************************************************************
***********************************************************************************
*********************
=> new bid -> bid service -> it sends get request to db to get current top price
=> bid service checks if price right now is higher : if yes update price in db and
send congratulate ; if no then send sorry
note : solution
-> bidder bids a price ; bidding service fetch current high
-> if current high > bidder price then return sorry
-> else execute this query : update bids set price = bidder_price where / if price
= current high
-> if 1 row affected : still price is same then send congrats
-> if 0 row affected : someone else changed the price in error concurrency window
then send sorry
=> this will also cause issue if 3$ writes first in db then it will win : puttin a
price < bidder_price will resolve
=> alternate solution : one bid at a time but that will also make our system slow
-> writes
-> 100k items * 1000 users * 5 bids per user => 500,000,000 writes per day / 24
hours
=> 8k writes per second = ~ a single node / instance of db can handle
-> reads
-> every bid require read from db : 1000 users * 5 bids = 5k reads (db reads)
-> we need to read a new resp msg in res queue : 8k messages read (res queue reads)
***********************************************************************************
***********************************************************************************
*********************
note :
-> new urls per month: 500 M
-> how long to keep urls in db : 5 years
-> total urls : 500 * 5 * 12 => 30 B
-> read write ratio : 100:1
=> redis db replicas (key value store) => 3 redis repicas can easily handle it (1
replica can do 100K reads per second)
-> but redis is limited by ram ; if ram is 64 GB then also we will need 50
instances of redis even to store data
=> dynamo db (300K read per second) (but price scales with cost : very expensive
with large scale system)
=> cache
-> get url/xyz => check if shortened url identifier is already in the cache =>
return
-> caching distribution and strategy : read aside cacheing
-> if 1% of total db storage (30TB) => 30 GB (managable)
-> but 300 K peak reads can not be handled by single machine ; if we distribute
cache along 4 machines then it will come under 100 k rps (manageable) (cache
sharding)
***********************************************************************************
***********************************************************************************
*********************
note : estimates
-> number of users : 100M active users
-> number of coupons to give away : 10M coupons
-> how long will it take us : 10 minutes
note : issues
-> concurrency : if two user check for coupon and only one coupon left but both
users will get a coupon because for both row_count = 10M - 1
-> scalability
note : concurrency
-> serialization of events using a queue
-> all the uuid req will go to queue and then serializer will pick one by one ;
check rows in db and return the resp in resp queue => coupon service
-> if multiple consumer (serializer) => then it will fall into same problem of
concurrency
***********************************************************************************
***********************************************************************************
*********************
note :
-> new tweets per second : 10K
-> read write ratio : 30:1
-> number of avg and max follower a user can have : 100 followers / 1M followers
note : tweeting
-> user -> post /tweet -> news feed service -> db (tweet table (uid, tweet, ts) +
follower table (s_id, t_id) (s follows t means s can see tweets of t but vice
versa is not true)
-> followers / users -> get /tweet?limit=10 (each minute) -> news feed
note : solution
-> instead of replicas we can shard database : each shard will have a piece of 30TB
of data
=> 30 shards => 10K reads per shard + 1 TB data each shard
=> 12 shards => 25K reads per shard + 3 TB for each shard
=> pros : less costly ; cons : complexity
note :
-> if a user has lot of followers
=> 10K tweets per second * 100 followers => 1000k writes to timelines per second
=> if 1M followers then 1M*10K writes to timelines (db writes)
note : so for vip, we can not use the feed optimization that's why we can make a
simple cache db to optimize the writes from that
-> a user fetches feeds of followers it follows and then the followers who are vips
from differenct cache
note :
-> user select event (venue) to book ticket x number of tickets -> go to payment
portal -> fetch the ticket
note : db structure
-> events table : venue ; name ; date ; max_tickets
-> tickets : event_id, user_id, num_tickets
note : estimates
-> store tickets for 5 years => 1 year forward and 4 year backward
=> max venue size * total venue * 365 * 5 = 200 B rows (uid: string, vid: string)
~ 1 record/row = 50 bytes => 10 TB data
=> we can do db sharding on the basis of veneues : each db : 1 TB data
***********************************************************************************
***********************************************************************************
**********************