System Design Mock Interview: Design Facebook Messenger

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
how do you design a real-time messaging app that can support millions of users [Music] in this video we'll be talking about how to design and build an application like facebook messenger whatsapp discord or slack we'll be talking about the high-level architecture of these systems as well as some specific features like how to build real-time messaging group messaging image and video uploads as well as push notifications now we'll be talking about some best practices as well along the way about how to build and scale a reliable system now before we dive into some specific features and components of our system let's talk a little bit about some of the high level features and goals that we want to implement along the way now i think some important product goals that we want to support obviously are real-time messaging from one individual to another as well as group messaging that can support multiple users we want to support maybe something like an online status to show whether a user is currently online or offline as well as supporting image and video uploads in addition to text messages and we also may want to support some extra bells and whistles like read receipts or push notifications so we'll get to those if we have time and then we also want to keep in mind some technical goals and constraints here so thinking about how to build a low latency system to support real-time messaging and what applications or technologies we need to sort of choose to make that happen we also want to build something that can support a really high volume of requests so you know millions of users potentially writing messages at the same time we also want to make sure of course that our system is highly reliable and available and we also want to make sure that our messaging system is secure and doesn't you know result in users being sent messages they shouldn't receive all right great so now that we've laid out some of the features we want to support let's talk about the overall architecture of this app and specifically let's talk about how we're going to send messages from one user to another so you know let's let's pretend we have two users here and we want to send a message between them so the reason we need to use a chat server application in this case is because on the internet it's actually really hard to establish a direct connection from one user to another and to make that connection reliable and in addition we also want to support things like storing and retrieving message histories later so we need to have our chat server here in order to sort of establish and broker this connection and to sort of store these messages so they can be retrieved from different devices later in time so i'm going to go ahead and draw in our chat api server and then we also need to sort of establish a connection from users to this chat server now let's think about what happens when user a sends a message to user b what we want to happen is the user sends a message to the server and the server relays that message instantly to the user that it's intended for however this kind of breaks the model of how http uh requests work on the internet because they can't actually be server initiated they have to be client initiated so something about this isn't going to work and we're going to have to come up with something else now i've got a few options in mind so i'm going to talk about those and discuss their trade-offs the first one we can do is something called http polling and in this model instead of just sending one request to the server we're going to sort of repeatedly ask the server if there's any new information available and so most of the time the server is going to reply with no there's no new information available and then once in a while it'll say hey yeah i received a new message for you and it will reply with that for a variety of reasons this is probably not the right solution for this problem because it means we're going to be sending a lot of unnecessary requests to our server and it also means that we're going to have a pretty high latency so we're only going to be able to receive messages when we ask for them not when they're actually received by the server now the second option we have is something called long polling and in this model we're still using sort of a traditional http request but instead of resolving immediately with the result we're actually going to have the server hold on to the request and wait until data is available before it replies with the result so in this way we sort of maintain an open connection with the server at all times and then once data is sent back we immediately request a new connection and then we keep that open until data is available now this is a little bit better because it solves our latency problems somewhat and we don't have to create all these unnecessary requests all the time however we have to maintain this open connection and if there's lots of data coming from the server it means we still have to initiate a new request to get the next piece of data so while it's good for some systems like notifications and things like that it's probably not the best for a real-time chat application like we're trying to build here so the third option we have is something called websockets and this is the solution i'm going to recommend because it was sort of designed for this application now in websockets we still maintain an open connection with the server but instead of being just a one-way connection it's actually a full duplex connection so now we can send up data to the the server and the server can push down data to us and this connection is maintained and kept open for the duration of the session so this architecture presents some unique challenges for us because there's some practical limitations to how many open connections a server can have at one time websockets is built on the tcp protocol which has about 16 bits for the port number this means there's a real limitation of about 65 000 connections that any one server can have open at a time so instead of having one api server we're obviously going to need to have a lot of servers to handle all of these websocket connections and we're going to need a load balancer or gateway sitting in front of them to help balance these connections and route them to the correct server so i'm going to go ahead and replace this with a load balancer and i'm going to draw in some api servers here instead all right great so i'm just sort of visualizing this with um you know about three servers but if we're trying to support millions or hundreds of millions of users and we can only support thousands of requests per server that means we're going to have hundreds or thousands of these servers serving requests and keeping these connections open so our system is going to have to reach a pretty massive scale here and in addition we now have a new problem because before we were able to sort of send a message from one user to another via our chat api server however now we have a distributed system and we need to be able to communicate from one api server to another and in fact we've actually created sort of another messaging problem here because these api servers need to know how to talk to each other so one model we could adopt here one design pattern we can use is something like a pub sub message queue and so that fits nicely into this problem because it's sort of a natural solution for a messaging problem between servers in a distributed system so i'm going to go ahead and draw in a message service here which is going to sort of implement this message queue and the idea here is that each api server will publish messages into this centralized queue and subscribe to updates for the users that it's connected to that way when a new message comes in it can be added to the queue and any service that's sort of listening for messages for that user can then receive that update and forward the message onto the user so that's how that would work now we still need to think about how we're going to store and persist these messages in our database and how to sort of model this relationship between messages and users so let's go ahead and draw in a database here and think about how that's going to work now when we think about what kind of database to choose for application let's think back to the beginning where we set out our requirements for the system so we know we want to support a really large volume of requests and store a lot of messages and we also care a lot about the availability and uptime of our service so we want to pick a database that's going to fit these requirements and we know from things like the cap theorem that there's going to be these sort of universal trade-offs between principles like consistency availability and ability to partition or shard our database and so we want to focus on this ability to shard and partition and keep our database available rather than things like consistency which are less important in a messaging application than they would be in something like a financial application so with that in mind i think i would choose something like a nosql database that has sort of built-in replication and sharding abilities so something like cassandra or hbase would be great for this application all right so now let's talk about how we're going to store and model this data in our database we know we're going to need a few key tables and features like users messages and then we're also going to probably need this concept of conversations which will be groups of users who are supposed to receive messages so i'm going to go ahead and draw those tables in so starting with the users table we're going to have a unique id for this user we're also going to have something like a username or a name for them to display and then we're probably also going to want to have something like a last active timestamp and the idea here is this this would allow us to support features like online status or being able to see when a user was last online and this would just be a simple time stamp that would be the date of their last activity all right so next we're going to need a messages table and again this is going to have a unique id but it's also going to store a reference to the user who made the message and we're also going to have a reference or an id for the conversation that it belongs to we'll talk more about that in a moment but then obviously at the end we're also going to need the text of the message as well and if we want to support something like media uploads like images or videos we also want to store something like a media url here in our database as well this won't be the actual data but it'll be the url where the user can access this data to download it all right so next we're going to need this conversations table that i was talking about and the idea here is that this would simply just be an id and perhaps something like a name so in the case of an application like slack or discord this could be the channel name uh of of the conversation so that's sort of an optional string that we could store here all right great so the last thing we need is a way to query and understand which users are part of a conversation and which conversations a user is part of so for that i'm going to add one more table here that i'm going to call conversation users and it's just going to store this sort of mapping from a conversation id to our user id so the idea is that there'd be a row here for every user in a conversation and we'd be able to sort of index these in order to do a queries like we were just talking about okay great so now that we've talked about how we're going to store data in our database let's revisit our overall architecture for a moment and think about how we can make the system more scalable and more performant so in particular one thing i'm thinking about is the cost of going to our database and retrieving messages from it repeatedly so one thing i'd like to add here is some sort of caching service or caching layer which would be like a read through cache that we can store in memory so that we don't always have to go to our database and and fetch messages from it directly so i'm just going to draw that in here now another thing we talked about but didn't really discuss very much is how we're going to store media so images and videos um and how we can upload those to the correct place now we're not going to store those in our database but instead we're going to choose some sort of other storage platform like an object storage service like amazon s3 so i'm going to go ahead and draw that in up here and the idea is that when our api receives a request to upload some sort of content we'll actually just forward it on to this object storage system and then we'll store the url of that object alongside our message as we discussed before on the user side when you receive a message that contains some sort of media you'll then go and fetch that url separately in order to download it now in order to make that more efficient we'll also want to add some sort of caching here and in this case we would use something like a cdn and the idea is that the user would request the resource from the cdn and if it's cached already that's great and if it's not the the cdn would request that object from the object storage service in case there's a cache miss all right great now the last thing we want to add here is some sort of way to notify users who are offline about messages they may have missed so in this case we might want to have some sort of notification service here that's also going to be contacted by our message service in the event that the user is offline so in this case our message service will contact our notification service and our notification service will forward that notification onto the user but probably via some sort of third party api for ios devices or android devices or perhaps even through some sort of mail service all right we've covered a lot of ground and we've talked about everything from choosing the right network protocol for our clients to building a distributed messaging queue system in our back end and picking the right database and data model to store all these messages i think with that we've covered uh pretty much everything we need to talk about and while we could go more in depth on each of these topics i think hopefully you have the big picture and the overview of how we would build this application and have learned some of the important technical decisions and trade-offs that we need to be thinking about when we implement something like this you
Info
Channel: Exponent
Views: 79,104
Rating: 4.8425016 out of 5
Keywords:
Id: uzeJb7ZjoQ4
Channel Id: undefined
Length: 14min 50sec (890 seconds)
Published: Mon Jan 11 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.