Design Considerations of Yelp
Discover how to design a highly scalable proximity service like Yelp by addressing core challenges such as searching and data partitioning. Implement dynamic segmentation and QuadTrees for efficient spatial indexing. Evaluate the final System Design against non-functional requirements like availability and performance.
We'll cover the following...
Introduction
The previous lesson covered the system architecture, core components, and overall workflow, which raised several open design questions. For example, how should the system retrieve nearby places, and how should it rank them by popularity? This lesson addresses these design concerns. The following table summarizes the objectives of this lesson.
Summary of the Lesson
Section/Sub-section | Purpose |
Searching | This process divides the world into segments to optimize the search, so that all nearby sites in a given location and radius can be identified. |
Storing Indexes | We index the places to improve query performance and estimate the storage required for all of the indexes. |
Searching Using Segments | We search all the desired places by combining the segments. |
Dynamic Segments | We solve the static segment limitations using dynamic segments. |
Searching Using a QuadTree | We explore the searching functionality using a QuadTree. |
Space Estimations for a QuadTree | We estimate the storage required for a QuadTree. |
Data Partitioning | We look into the options we can use to partition data. |
Ensuring Availability | We look into how we’ll ensure the availability of the system. |
Inserting a New Place | We look into how we’ll insert the place in a QuadTree. |
Ranking Popular Places | We rank the places of the system. |
Evaluation | We evaluate how our system fulfills the non-functional requirements. |
Searching
Using Google Maps, we were able to connect segments and overcome the scalability challenge to efficiently process a large graph. The graph of the world had numerous nodes and vertices, and traversing them was time-consuming. Therefore, we divided the whole world into smaller segments/subgraphs to process and query them simultaneously. The segmentation helps improve the system’s scalability.
Each segment will be of the size
How will we find nearby places if we create a table for storing all places?
We can store all the places in a table and uniquely identify a segment by having a segment_ID. We can index each segment in the database. Now, we have limited the number of segments we need to search, so the query will be optimized and return results quickly.
Improve data fetching
We use a key-value store for quick access to places in the segments. The key is the segment_ID, while the value contains the list of places in that segment. Let’s estimate how much space we need to store the indexes.
We can usually store a few MBs in the value of the key-value store. If we assume that each segment has 500 places then it will take up
The total area of the Earth is around 200 million square miles, and the land surface area is about 60 million square miles. If we assume our radius is 10 miles, we’ll have 6 million segments. An 8-byte identifier will identify each segment.
Let’s calculate how much memory we need.
| Total Area of the Earth (Million Square Miles) | 60 |
| Search Radius (Miles) | 10 |
| Number of Segments (Millions) | f6 |
| Segment_ID (Bytes) | 8 |
| Place_ID (Bytes) | 8 |
| Number of Places (Millions) | 500 |
| Total Space (GB) | f4.048 |
Search using segments
A user may select a radius to search for places that aren’t in a single segment. So, we need to combine multiple segments by connecting the segments to find locations within the specified radius—say, 5 miles.
First, we constrain the number of segments. This reduces the graph size and enables the search process to be optimized. Then, we identify all relevant locations, compute the distance to the search point, and display it to the user.
Can you identify a problem with the current approach?
Dynamic segments
We solve the problem of uneven distribution of places in a segment by dynamically sizing the segments. We do this by focusing on the number of places. We split a segment into four more segments if the number of places reaches a certain limit. We assume 500 places as our limit. While using this approach, we need to decide on the following questions:
How will we map the segments?
How will we connect to other segments?
We use a
Search using a QuadTree
We start at the root node and continue visiting nodes to find the desired segment. We check every node to see if it has more child nodes. If a node has no more children, then we stop our search because that node is the required one. We also connect each child node to its neighbors using a doubly linked list. All child nodes of all parent nodes are connected via a doubly linked list. This list allows us to find the neighboring segments when we need to move forward or backward, as per our requirements. After identifying the segments, we have the required PlaceID values of the places, and we can search our ...