Skip to Content
Course content
Click on the "Edit" button in the top corner of the screen to edit your slide content.

Let's imagine we're building a system for a global e-commerce site. We've got multiple servers across different regions handling orders. Naturally, the first thing I'd do is give every order an ID so we can track it. My instinct—and yours probably—is to use an integer.

The problem with counting

I'll start with a simple Order class. I'll use a static counter to simulate how a database might auto-increment an ID.

public class Order
{
    private static int _globalCounter = 0;
    public int OrderId { get; }
    public string Product { get; set; }

    public Order(string product)
    {
        OrderId = ++_globalCounter;
        Product = product;
    }
}

// Simulation: Two different servers handling orders
var serverA_Order = new Order("Mechanical Keyboard");
var serverB_Order = new Order("Gaming Mouse");

This works fine on one server. But remember, we're distributed. If Server A and Server B both start up at the same time, they both start their counters at 0. Suddenly, I have two different orders with OrderId = 1. That's a nightmare for a database admin and a disaster for the customer who gets the wrong package. I can't rely on a central authority to hand out numbers in real-time without creating a massive bottleneck.

Something more random

I need an identifier that is unique not just on this machine, but across every machine in the world, without needing to check in with a central server first. I've seen people try to solve this by concatenating the server name, the date, and a random number into a string. It's messy, it's slow, and it's still technically possible to have a collision.

This is where I reach for the Guid type. Let's swap out that int and see what happens.

public class Order
{
    public Guid OrderId { get; }
    public string Product { get; set; }

    public Order(string product)
    {
        OrderId = Guid.NewGuid();
        Product = product;
    }
}

var order1 = new Order("Mechanical Keyboard");
var order2 = new Order("Gaming Mouse");

Console.WriteLine($"Order 1 ID: {order1.OrderId}");
Console.WriteLine($"Order 2 ID: {order2.OrderId}");

When I run this, I don't get "1" and "2". I get something like f47ac10b-58cc-4372-a567-0e02b2c3d479. It's long, it's ugly, but it's a Globally Unique Identifier. The Guid.NewGuid() method generates a 128-bit integer that is, for all practical purposes, unique across the entire universe.

Wait, how unique is this actually?

I used to be skeptical about this. I wondered, "What if two servers generate the same Guid at the exact same nanosecond?"

Here is the reality: the probability of a collision is so astronomically low that you can effectively treat it as zero. You are more likely to be hit by a meteorite while winning the lottery than you are to generate a duplicate Guid in a standard application. It's designed specifically so that I can generate an ID on a laptop in Tokyo and you can generate one on a server in London, and we can be confident they won't clash when they hit the same database.

One thing I noticed while experimenting is that Guid is a value type (a struct), not a class. It's efficient, but it does have a few quirks. For instance, if I want to represent a "null" or empty Guid, I can't use null (unless I make it Guid?). Instead, there's a special constant:

Guid emptyId = Guid.Empty;
Console.WriteLine(emptyId); // Outputs: 00000000-0000-0000-0000-000000000000

I usually use Guid.Empty when I need a placeholder before a real ID has been assigned. It's a clean way to signal that the identifier hasn't been initialized yet.




📋 Practical Task

Build a Distributed Session Manager

Create a program that simulates a user login system for a distributed web app. You need to ensure that every user session is tracked with a unique identifier that cannot collide across different servers.

  • Create a UserSession class that stores a Username (string) and a SessionId (Guid).
  • The SessionId should be automatically generated using Guid.NewGuid() when the UserSession is instantiated.
  • In your Main method, create a List<UserSession>.
  • Add three different users to the list.
  • Loop through the list and print the username and their unique Session ID to the console.
  • To prove you understand the "empty" state, create one UserSession where the ID is manually set to Guid.Empty, and print it to show the difference between a generated ID and an empty one.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.