liveBook · Manning

Cluster sharding

As explained in Akka in Action, Second Edition

akka-cluster-sharding is the Akka library module that provides clustered sharding functionality.

Cluster sharding distributes stateful actors across an Akka cluster. Each sharded actor is an entity, grouped into logical shards and located automatically from its ID. A partition key routes messages to the entity and lets the cluster spread memory and work across nodes while keeping at most one instance of an entity active in the cluster. section 8.1 section 9.1

Entities relocate as nodes join, leave, or fail. This isolates actors on healthy nodes from failures elsewhere and restores capacity by moving affected entities to healthy members. Relocation restarts an entity, however, so in-memory state is lost unless a durable mechanism such as Akka Persistence preserves it. section 9.1

A minimal sharded entity needs the following pieces:

  • An EntityTypeKey identifying the entity type. The type key and entity ID together distinguish an entity, allowing different entity types to reuse the same ID. section 9.1.2
  • A behavior constructed from the EntityContext entity ID. EntityContext supplies the type key and ID, rather than normal ActorContext facilities such as logging, spawning, scheduling, or watch. section 9.1.2
  • A ClusterSharding instance initialized with an Entity definition, producing a shard region that accepts ShardingEnvelope messages. section 9.1.2
  • Cluster configuration, including a cluster actor provider, remote host and port, seed nodes, and serialization bindings for the example protocol. section 9.1.3

Shipping containers

Model each shipping container as an entity whose ID is the container ID. Its behavior starts with no cargo, accepts AddCargo, and replies to GetCargos. Initialize sharding with the container type key, then send ShardingEnvelope(containerId, AddCargo(cargo)) to the shard region. No ActorRef is required and no entity must be spawned manually: sending to a missing entity creates it automatically. The client uses an EntityRef-like API while sharding selects and manages the entity location. section 9.1.2 section 9.1.3

Listing 9.1 Container behavior with containerId and TypeKey
object Container {
 
  val typeKey =
    EntityTypeKey[Container.Command]("container-type-key")       #1
 
    sealed trait Command
    final case class AddCargo(cargo: Cargo) extends Command      #2
      with CborSerializable                                      #2
    final case class GetCargos(replyTo: ActorRef[List[Cargo]])   #2
      extends Command with CborSerializable                      #2
 
  def apply(containerId: String): Behavior[Command] = {          #3
    ready(List())
  }
 
  def ready(cargos: List[Cargo]): Behavior[Command] = {          #4
    Behaviors.receiveMessage[Command] {
      case AddCargo(cargo) =>
        ready(cargo +: cargos)
      case GetCargos(replyTo) =>
        replyTo ! cargos 
        Behaviors.same
    }
  }
}

The container behavior shows the essential entity ingredients: a typed key, serializable commands, an ID-based constructor, and state carried forward by the behavior. section 9.1.2

Avoid bypassing sharding by sending directly to an entity ActorRef unless that trade-off is understood. Direct messages are not registered as activity by passivation, the mechanism that adds or removes entities from memory according to activity. Use the shard region for normal entity communication. section 9.1.3

Sharding fits workloads with many independently addressed actors. A wallet service, for example, can distribute millions of wallets across nodes by ID and add nodes as demand grows. Pairing sharding with persistence makes balances durable through process or infrastructure failures. section 12.1.1

Sharding can create as many entities as demand requires. This differs from ShardedDaemonProcess, which distributes behaviors too but requires its instance count up front and does not provide a shard-region proxy for direct entity messaging. section 10.3.3

How Akka in Action, Second Edition covers it

How deep it goes
Explains entity identity, initialization, routing, relocation, configuration, and passivation caveats; defers durable recovery to Akka Persistence.
Examples
Uses a shipping-container entity that adds and queries cargo, plus an event-sourced wallet handling funds reservations and balances.
What it assumes
Assumes typed actors and cluster setup while introducing sharded entities, type keys, IDs, shard regions, and envelopes from a concrete example.
What you can do after
Apply it via Akka Cluster Sharding to initialize ID-addressed entities and send routed messages without manually spawning actors.
How it connects
Connects cluster sharding with Akka Cluster, Akka Persistence, passivation, EntityTypeKey, ShardedDaemonProcess, and the receptionist.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Akka in Action, Second Edition. The section links point to the parts of the book it draws on.