đź“„ 01.md
/home/palash/git/site-assets/blogs/distributed-systems/01.md
Language: md • Lines: 103
# The birth of Distributed Systems

Think about your everyday life. Almost everything you do is powered by a network of systems.

Want to listen to your favorite song? You open Spotify. Craving a movie or a quick video? You’re on YouTube. Need something delivered? Amazon’s got you covered. Planning dinner? You’re scrolling through Zomato or Blinkit. Staying in touch with friends? WhatsApp video calls or other chat apps are just a tap away.

The internet has revolutionized how we live, but here’s something to ponder: Would the internet still feel so indispensable if the services we rely on weren’t always available, whenever we needed them?

The magic lies in their reliability—these systems are always on, ready to serve you, no matter where you are. It’s seamless. It’s beautiful. But have you ever wondered how they pull this off?

Welcome to the fascinating world of distributed systems—the silent engines behind your favorite apps. In this series, we’ll dive deep into how these systems work and what makes them tick.

## The basics
Behind all these services, we have some computers performing their jobs. Each computer has four workhorses to employ
- CPU, for the raw processing power
- Memory, for temporary memory storage to assist CPU
- Network, the communication channel
- Storage, for long term data retention

For a small system where we deal with a small set of data or small number of user requests, all these components can be part of a single Computer System.

## Hardware Expansion
Every sub-systems in the computer has some limit. So, a computer system's capacity is dependent on the limits of these sub-systems. On the other hand, service demands from the application increases over time.

We can mitigate this problem by increasing the capacity of underlying hardwares. We can employ more powerful CPU, expanded RAM, higher bandwidth. This process of expanding capacity by employing powerful hardwares is known as Vertical Scaling.

```
Vertical Scaling
-----------------

  +--------------------+          +---------------------+         +---------------------+
  |    Server 1        |          |    Server 2         |         |    Server 3         |
  |  (CPU: 1, RAM: 8GB)|  --->    |  (CPU: 4, RAM: 32GB)|  --->   |  (CPU: 8, RAM: 64GB)|
  +--------------------+          +---------------------+         +---------------------+
```

## Multi-Tier architecture
Now Vertical Scaling can go up to some extent and mitigate the issue. However, this system will also reach a limit. The simplest work around is to break down the application based on the task they perform. For example, one can think of a system having three distinguished components - 
1. Presentation Layer - this layer interacts with the user. For example a web app whose primary responsibility is to handle user interaction. For example, your banking website.
2. Logic Layer - this layer is responsible is for all the business logic handling. For example, a banking server can have a layer, which handles all the transactions.
3. Data Layer - this layer is responsible for persisting and querying of data. For example, the account database in a banking system.

```markdown
Three Tier Architecture
------------------------

+-----------------------+     +-----------------------+     +-----------------------+
|   Presentation Layer  | --> |     Logic Layer       | --> |     Data Layer        |
|   (User Interface)    |     |   (Business Logic)    |     |   (Database)          |
+-----------------------+     +-----------------------+     +-----------------------+
```


## Parallel Processing
With Vertical Scaling and Multi-Tier Architecture, we can temporarily serve more requests. But at certain point, physical constraints kick in. We cannot infinitely grow a system with these techniques.

What happens when we reach that limit?

Well, requests start to pile up and system start performing poorly. As a result, throughput of the system decreases and system responds slowly. This is problematic from user perspective. Imagine, you are transferring funds but due to limiting factors in the system you keep on waiting. This results in anxiety and you get frustrated.

To avoid this problem, we add more machines to distribute the work load for parallel processing. This is called Horizontal Scaling.

Thus, Distributed Systems is an architecture where we employ multiple interconnected nodes to achieve parallel processing of requests and evenly distribute work load in multiple machines.


```
Three-Tier Architecture with Parallel Processing
-------------------------------------------------

                    +-------------------------+
                    |  Presentation Layer     |
                    |  (User Interface)       |
                    +-------------------------+
                          /        |         \
                         /         |          \
                        V          V           V
            +--------------------+     +--------------------+     +--------------------+
            |   Logic Layer 1    |     |   Logic Layer 2    |     |   Logic Layer 3    |
            | (Business Logic 1) |     | (Business Logic 2) |     | (Business Logic 3) |
            +--------------------+     +--------------------+     +--------------------+
              /        |        \        /        |        \         /        |        \
             /         |         \      /         |         \       /         |         \
            V          V          V    V          V          V     V          V          V
    +-------------------+   +-------------------+  +-------------------+  +-------------------+
    |   Data Layer 1    |   |   Data Layer 2    |  |   Data Layer 3    |  |   Data Layer 4    |
    |  (Database 1)     |   |  (Database 2)     |  |  (Database 3)     |  |  (Database 4)     |
    +-------------------+   +-------------------+  +-------------------+  +-------------------+
```

## The Problem with Distributed Systems
Now, we can process more requests and theoretically scale infinitely. But, this does not come for free. When we deal with small number of systems, failure rates are ridiculously low. But when we deal with high number of systems, we see how the low probablity of hardware failures also scale up.

Let's take an example. If we deal with 1 system with failure probablity of 1 failure every 1000 days. So, the probablity of that machine failing is 0.001 per day, which is negligible. However, if we employ 1000 such systems, the failure rate becomes 1 failure a day. Now, this is concerning. And in fact, a reality where thousands of systems are interconnected. Hardware failures are more common than you can think.

To maintain service availability and minimal disruption to the service, we have to ensure that these system failures don't interrupt our services. Ensuring service availability, even in case of hardware or software failures, lies with the software system. We employ replication technique to achieve this.

Maintaining availability of business logic layer where the server simply responds to users based on logic and not on underlying data is comparatively easy. For example, if a server performs calculations on two datasets, then it is easy to replace a faulty server with a replica.

However, it is difficult to perform the same operation for a component which deals with underlying data. For example, if we have a server which stores data of user's account and suddenly goes down, we cannot simply replace it with any other server. The server has to correctly show the account data as well. This poses significant challenge.

To handle this scenario, we employ many techniques. This series will throw light on many of these techniques. If possible, I will also share basic simplified implementations of some of the techniques as well.