Graph traversal and bidirectional BFS
BFS across servers, searching from both ends (b^d versus 2·b^(d/2) in an idealized tree), stopping correctly, and the primer’s other optimizations.
What you will learn
- Find a shortest path with breadth-first search when every step is a network call.
- Explain why the search grows so fast with each hop.
- Search from both ends, stop correctly, and apply the primer's other optimizations.
Breadth-first search across servers
Edges are unweighted, so breadth-first search finds a shortest path: explore everyone one hop away, then two hops, and so on, remembering each person's predecessor.
In the primer's design, the User Graph Service runs the BFS. For each person it visits, it:
- asks the Lookup Service which Person Server holds that person;
- fetches the person, and their
friend_ids, from that server; - queues the friends it has not seen yet.
Every expansion is therefore a network round trip. The primer marks the repeated lookup as a "potential for optimization".
Why it gets expensive
If everyone had friends and no friends were shared, BFS would reach about people within hops. With and :
Real graphs share many friends, so the true count is lower, but it still grows very fast with each hop.
Searching from both ends
The primer's first suggested optimization: "Do two BFS searches at the same time, one starting from the source, and one from the destination, then merge the two paths." Each side only needs to go about half the distance:
In this idealized tree that is 5,000 times fewer people reached. On real, overlapping graphs the saving is smaller but still large. The visual runs both searches on a random graph and counts the friend lists each one fetches.
Stopping correctly. Expand one whole level at a time, usually on the smaller frontier. When a level reaches people the other search has already seen, finish that level, then take the meeting point with the smallest total distance. Stopping at the very first contact can return a path that is longer than necessary.
The primer's other optimizations
- Cache people, and complete or partial BFS results, in a memory cache such as Redis or Memcached. This helps "people who do multiple searches in succession" and well-connected people.
- Batch compute offline complete or partial traversals and store them in a NoSQL database.
- Reduce machine jumps by batching the friend lookups that live on the same Person Server.
- Start from people with many friends, as they are more likely to shorten the path.
- Limit the search by time or number of hops, then ask the user whether to continue.
- Without the no-graph-database rule, use a graph database or graph query language.
BFS from one side or both
Both searches run for real on a random friendship graph. Each friend list fetched would be a lookup on some person server.
- Degree Search Clients (8k RPS): 1 × Clients & Users
- Search API Gateway: 2 × Application Load Balancer
- Forward BFS Traversal Nodes: 8 × App Compute Server
- Backward BFS Traversal Nodes: 8 × App Compute Server
- Distributed TAO Graph Cache: 5 × Redis In-Memory Cache
- Sharded Graph Database: 2 × Primary Relational DB
- Degree Search Clients (8k RPS) sends requests to Search API Gateway
- Search API Gateway sends requests to Forward BFS Traversal Nodes
- Search API Gateway sends requests to Backward BFS Traversal Nodes
- Forward BFS Traversal Nodes sends requests to Distributed TAO Graph Cache
- Backward BFS Traversal Nodes sends requests to Distributed TAO Graph Cache
- Distributed TAO Graph Cache sends requests to Sharded Graph Database
Key takeaways
- Each person visited costs a lookup and a fetch, and with friends the search reaches about people in hops.
- Searching from both ends reaches about : in the idealized tree with , , 5,000 times fewer.
- Expand whole levels, usually the smaller side; when the two meet, finish the level before choosing the shortest meeting point.
- Cache people and partial results, batch lookups on the same server, and limit the search by time or hops.
Sources
Adapted from The System Design Primer by Donne Martin, licensed under CC BY 4.0. Changes were made.