Functional Requirements in Distributed Systems
Functional Requirements in Distributed Systems
Functional Requirements
1. The player can connect to the game servers and see who is connected to each
server.
2. The player can join their friends and exchange messages.
3. Players engaged in parkour against the clock can do so wherever they are in
the world, even if the clocks on their computers are not synchronized.
4. Specific actions where multiple players compete to retrieve the same object
are correctly resolved by the game, and, subsequently, each player sees the
same outcome.
5. Modifications made to an in-game object by the players are seen in the
correct order by all nearby players.
1. Players experience that their actions (clicks) receive a reaction from the
game within 150 milliseconds. This lag is not only limited but also stable.
2. Players can access the game services every time they try.
3. Each machine used by the gaming platform is utilized more than 50%, each
day.
4. The gaming platform consumes at most 1 MWh of electricity per day.
• Naming: We expect that components of the same computer system find each
other, by identifier or name, and can communicate easily.
• Clock Synchronization: We also expect that the system provides a clock
and implicitly that the clock is synchronized for all system components; in
other words, acting 'at the same time' (synchronously) is trivial for
components in a computer system.
Distributed systems counter all these intuitions. Because the machines hosting
components of the system are physically distributed, the laws of physics have an
important impact: the real-world time it takes for information to get from one
component to another can be orders of magnitude higher than it normally takes in
the computers and smartphones we are used to. This real-world information delay
changes everything. Components in distributed systems cannot easily name or
communicate with other components. Distributed systems cannot easily achieve
clock synchronization, consensus, or consistency. Instead, all these functions
require specialized approaches in distributed systems.
The ability to communicate is essential for systems. Even single machines are
constructed around the movement of data, from input devices, to memory and
persistent storage, to output devices. Although computers are increasingly
complex, this communication is well-understood. We include in the typical
functional requirements, and modern systems already meet these requirements, that
messages arrive correctly at the receiver, that there is an upper limit on the amount
of time it takes to read or write a message, and that developers know how much
data can be safely exchanged between applications at any point in time. In a
distributed system, none of this is true without additional effort.
How a protocol is defined depends on the technology that underlays it. For
protocols that directly use the network’s transport layer, they need to define data
fields as a sequence of bits or bytes. Defining a protocol on this level, however, has
multiple disadvantages. It is labor intensive, the binary messages are challenging
to debug, and it is difficult to achieve backward compatibility.
When a protocol defines data fields on the level of bits and bytes, adding or
changing what data can be sent while still supporting older implementations is
difficult. For these and other reasons, distributed systems often define their
protocols on a higher layer of abstraction.
Instead of defining fields with specified bit or byte lengths, plain-text protocols are
typically line-based, meaning every message ends with a new line character (“\n”).
The advantages of such protocols are that they are easy to debug by both humans
and computers, and that they offer increased flexibility due to variable-length
fields. Text-based protocols can easily be changed into binary protocols without
losing their advantages, by compressing the data before it is sent over the network.
• Transient communication only maintains the message while the sender and
the receiver are online, and only if no transmission error occurs. This model is
the easiest to implement and matches well with the typical Internet-router based
on store-and-forward or cut-through technology. An example here is that real-
time games may occasionally drop updates and use local correction
mechanisms. This allows in many cases the use of relatively simple designs, but
for some game genres can lead to the perception of lag or choppy movement of
the avatars and objects.
• Persistent communication requires the communication environment to store
the message until it is received. This is convenient for the programmer, but
much more complex to guarantee by the distributed system. Worse, this leads
typically to lower scalability than approaches based on transient communication
due to the higher latency of the message broker storing incoming messages on a
persistent storage device as well as potential limits of the number of messages
that can be persisted at the same time. An example of the use of a persistent
communication system appears in the email system. Emails are sent and
received using SMTP and IMAP respectively. SMTP copies email from a client
or server to another server, and IMAP copies email from a server to a client.
The client can copy the email from their server repeatedly because the email is
persisted on the server.
Depending on whether the sender and/or the receiver has to wait (is blocked) in the
process of transmitting or receiving, we distinguish between asynchronous
communication and synchronous communication:
Implementation
Functionally, RPC wants to maintain the illusion that a program would call a local
implementation of the service. Since now caller and callee reside on different
machines, they need to agree on a definition of what the procedure is: its name and
parameters. This information is often encoded in an interface written in an
Interface Definition Language (IDL).
In order for local programs to be able to call the service, a stub is created that
implements the interface but, instead of doing function execution locally, encodes
the name and the argument values in a message that is forwarded to the callee.
Since this is a mechanical, deterministic process, the stub can be compiled
automatically by a stub generator.
On the server side, the message is received and the arguments need to be
unmarshalled from the message so that the function can be invoked on behalf of
the client. This is again performed by an automatically generated stub, on this side
of the system also often referred to as a skeleton (server stub in the image below)
Compiled by: Ararsa Lemmessa (Eng.) Rift Valley
University
The dynamics of this operation are as follows. When the client calls the procedure
on the local stub, the client stub marshals both the procedure name and the
provided arguments into a message. This message is then sent to a server that
contains the requested procedure. Upon receipt, the receiving stub unmarshals the
message and calls the corresponding procedure with the provided arguments. The
returned value is then sent back to the client, using the same approach. RPC uses
transient synchronous communication to create an interface that is as close as
possible to regular procedure calls
Since the late-1950s, the programming language community has proposed and
developed programming models that consider objects, rather than merely
operations and procedures for program control. Object-oriented programming
languages, such as Java (and Kotlin), Python, and C++, remain among the most
popular programming languages. It is thus meaningful to ask the question: Can
RPC be extended to (remote) objects?
The messages that are sent between machines, be they sent as plain messages, or as
the underlying technology of RPC, show distinct patterns over time depending on
the properties of the system that uses them. Below we describe some of the most
prevalent communication patterns.
Communication in Practice
Naming schemes (schema) are the rules by which names are given to individual
entities. There are an infinite number of ways in which to ascribe names to entities.
In this section, we identify and discuss three categories of naming schema:
• Simple naming,
• Hierarchical naming, and
• Attribute-based naming.
Simple Naming: Focusing on uniquely identifying one entity among many is the
simplest way to name entities in a distributed system. Such a name contains no
information about the entity’s location or role.
Advantages: The main advantage of this approach is simplicity. The effort required
to assign a name is low—the only requirement is that the name is not already
taken. Various approaches can simplify even this verification step, at the cost of a
(very low) probability the name may cause a collision with another chosen name.
Disadvantages: A simple name shifts the complexity of locating it to the naming
service.
Addressing the downside of simple naming, distributed systems can use rich
names. Such names not only uniquely identify an entity, but also contain additional
information, for example, about
Namespaces are commonly used in practice. Examples include file systems, the
DNS, and package imports in Java and other languages. These names consist of a
concatenation of words separated by a special character such as “.” or “/”. The tree
structure forms a name hierarchy, which combines well with, but is not the same
as, a hierarchical name resolution approach. When a hierarchical naming scheme is
combined with hierarchical name resolution, a machine is typically responsible for
all names in one part of the hierarchy. For example, when using DNS to look up
the name [Link] we first contact one of the DNS root servers. These
forward us to the “et” servers, which forward us to the “com” servers, which in
turn know where to find “[Link]”.
Figure 1 illustrates how a player in the example might find a game of Minecraft
located in an EU datacenter. In step 1, the game client on the player's computer
automates this, by querying the naming service to
"search((R=“EU”)(G=“Minecraft”))". Because the entries in attribute-based
naming are key-value pairs, searches are easy to make, and also partial searches
can result in matches. In step 2, the naming service returns the information that
"server 42" is a server matching
Once every entity in the system has a name, we would like to use those names to
address our messages. Networking approaches assume that we know, for each
entity, on which machine it is currently running. In distributed systems, we want to
break free of this limitation. Modern datacenter architectures often run systems
inside virtual machines that can be moved from one physical machine to the next
in seconds. Even if instances of entities are not moved, they may fail or be shut
down, while new instances of the same service are started on other machines.
Naming services address such complexity in distributed systems.
In step 3, user D sends a new message to the publish-subscribe system. The system
analyzes this message and decides it fits the subscription made by user A.
Consequently, in step 4, user A will receive the new message.
Consensus focuses on any value, so unlike the clock not only numerical. More
importantly, the value subject to consensus does not need to change as clocks do;
in fact, it may not even change at all. Consensus may focus on a single value but,
by reaching consensus repeatedly, can also enable a total ordering of events but
such an approach is expensive in time and resources.
Consistency focuses on any value from the many included in a dataset, creating a
flexible order. Consistency protocols in distributed systems define the kind of
order that can be achieved, for example, total order, and, more loosely, when the
order will be achieved, for example, after each operation, after some guaranteed
maximum number of operations, or eventually. Using consistency protocols to
order events in a form weaker than total ordering, and even some discrepancies
between how different components see the values in the database, are useful for
different classes of applications because they can often be achieved much quicker
and with much more scalable techniques.
Compiled by: Ararsa Lemmessa (Eng.) Rift Valley
University
2.4 Consensus
Consider a distributed key-value store that uses replication. Users submit read and
write operations to whichever process is closest to them, reducing latency. To give
the user the illusion of a single system, the processes must agree on the order to
perform the queries, and especially keep the results of writing (changing) data and
reading data in the correct order. Using clock synchronization techniques could
work for this, but the cost of having each machine in the distributed system ask
each other about whether the operations they received lead to some other order, for
each operation, is prohibitively expensive in both resources and time. Another
class of techniques needs to focus on the consensus problem.
In a distributed system,
Theoretical computer science has considered for many decades the problem of
reaching consensus. When machine failures can occur, reaching consensus is
surprisingly difficult. If the delay of transmitting a message between machines is
left unbound, it is proved that, even when using reliable networks, no distributed
consensus protocol is guaranteed to complete. The proof itself is known as the FLP
proof, after the acronym of the family names of its creators. It can be found in the
aptly named article “Impossibility of Distributed Consensus with One Faulty
Process” [1].
Consider that the claim is not true: There exists a consistency protocol, a
distributed algorithm that always reaches consensus in bounded time. For the
algorithm to be correct, all machines that decide on a value must decide on the
same value. This prevents the algorithm from simply letting the machines guess a
value. Instead, they need to communicate to decide which value to choose.
Many protocols have been proposed to achieve consensus, with various degrees of
capability under various forms of failures, messaging delays they tolerate, etc.
Among the protocols that are used in practice, Paxos, multi-Paxos, and more
recently Raft seem to be very popular. For example, etcd is a distributed database
built on top of the Raft consensus algorithm. Its API is similar to that of Apache
ZooKeeper (a widely-used open-source coordination service), allowing users to
store data in a hierarchical data-structure. Etcd is used by Kubernetes and several
other widely-used systems to keep track of shared state.
We sketch here the operation of the Raft approach to reach consensus. Raft is a
consensus algorithm specifically designed to be easy to understand. Compared to
other consensus algorithms, it has a smaller state space (the number of
configurations the system can have), and fewer parts.
Figure 3. Raft overview.
1. Raft first elects a leader ("leader election" in Figure 3). The other machines
become followers. Once a leader has been elected, the algorithm can start
accepting new log entries (data operations).
2. The log (data) is replicated across all the machines in the system ("log
replication" in the figure).
3. Users send new entries only to the leader.
4. The leader asks every follower to confirm. If most followers confirm, the log
is updated (performs the operation).
We describe three key parts of Raft. These do not form the entirety of Raft, which
is indicative that even a consensus protocol designed to be easy to understand still
has many aspects to cover.
The Raft leader election: Having a leader simplifies decision-making. The leader
decides on the values. The other machines are followers, accepting all decisions
from the leader. Easy enough. But how do we elect a leader? All machines must
agree on who the leader is—leader election requires reaching consensus, and must
have safety and liveness properties.
In Raft, machines can try to become the new leader by starting an election. Doing
so changes their role to candidate. Leaders are appointed until they fail, and
followers only start an election if they believe the current leader to have failed. A
new leader is elected if a candidate receives the majority of votes. With one
exception, which we discuss in the section on safety below, followers always vote
in favor of the candidate.
Raft uses terms to guarantee that voting is only done for the current election, even
when messages can be delayed. The term is a counter shared between all machines.
It is incremented with each election. A machine can only vote once for every term.
If the election completes without selecting a new leader, the next candidate
increments the term number and starts a new election. This gives machines a new
vote, guaranteeing liveness. It also allows distinguishing old from new votes by
looking at the term number, guaranteeing safety.
Log replication: In Raft, users only submit new entries to the leader, and log
entries only move from the leader to the followers. Users that contact a follower
are redirected to the leader.
Compiled by: Ararsa Lemmessa (Eng.) Rift Valley
University
Figure 4. Log replication in Raft. The crown marks the leader.
New entries are decided, or “chosen,” once they are accepted by a majority of
machines. As Figure 4 illustrates, this happens in a single round-trip: (a) The leader
propagates the entries to the followers and, (b) counts the votes and accepts the
entry only if a majority in the system voted positively.
Safety in Raft: Electing a leader and then replicating new entries is not enough to
guarantee safety. For example, it is possible that a follower misses one or multiple
log entries from the leader, the leader fails, the follower becomes a candidate and
becomes the new leader, and finally overwrites these missed log entries.
(Sequences of events that can cause problems are a staple of consensus-protocol
analysis.) Raft solves this problem by setting restrictions on which machines may
be elected leader. Specifically, machines vote “yes” for a candidate only if that
candidate’s log is at least as up-to-date as theirs. This means two things must hold:
When machines vote according to these rules, it cannot occur that an elected leader
overwrites chosen (voted upon) log entries. It turns out this is sufficient to
guarantee safety; additional information can be found in the original article.
Compiled by: Ararsa Lemmessa (Eng.) Rift Valley
University
2.5 Consistency in Distributed Systems
The Data Store
The essence of any discussion about consistency is the abstract notion of the data
store. Data stores can differ when servicing diverse applications, types of
operations, and kinds of transactions, but essentially a data store:
Many applications only have a single primary user. You are likely the only one
accessing your email, for business or leisure. You may have a private Dropbox
folder, which you may want to access at home, on the train, wherever you stay
long enough to want to store new photos, etc. Many mobile-first users recognize
these and similar applications. Figure 1 depicts the data store for the single primary
user. Here, the user can connect from one location (or device), write new
information - a new email, a new Dropbox file, then disconnect. After moving to a
new location (or device), and reconnecting, the user should be able to resume the
email and access the latest version of the file.
Other applications have multiple users, writing together information to the same
shared document, changing together the state of an online game, making together
transactions affecting many shared accounts in a large data management system,
etc. Here, the data store again has to manage the data-updates, and deliver correct
results when users query (read).
The strictest forms of consistency are so costly to maintain that, in practice, there
may be some tolerance for a bit of inconsistency after all. The CAP theorem
suggests availability may suffer under these strict models, and, the PACELCA
framework further suggests also performance is a trade-off with how strict the
consistency model can be.
(1) in operation-centric consistency models, a single client can access a single data
object,
(2) in transaction-centric consistency models, multiple clients can access any of the
multiple data objects, and
Several important models emerged in the past four decades, and more may
continue to emerge:
Sequential consistency: All replicas see the same order of operations as all other
replicas. This is desirable, but of course prohibitively expensive.
Causal consistency weakens the promises, but also the needs to operate, of
sequential consistency: As for sequential consistency, causally related operations
must still be observed in the same order by all replicas. However, for other
operations that are not causally related, different replicas may see a different order
of operations and thus of outcomes. Important cases of causal consistency, with
important applications, include:
One of the earliest consistency techniques in games is the dead reckoning. The
technique addresses the key problem that information arriving over the network
may be stale by the moment of arrival due to network latency. The main intuition
behind this technique is that many values in the game follow a predictable
trajectory, so updates to these values over time can largely be predicted. Thus, as a
latency-hiding technique, dead reckoning uses a predictive technique, which
estimates the next value and, without new information arriving over the network
from the other nodes in the distributed system, updates the value to match the
prediction.
Although players are not extremely sensitive to accurate updates, and as long as
the updated values seem to follow an intuitive trajectory will experience the game
as smooth, they are sensitive to jumps in values. Thus, when the locally predicted
values and the values arriving over the network diverge, dead reckoning cannot
simply replace the local value with the newly arrived; such an
The interplay between the two techniques, the predictive and the convergence,
makes dead reckoning an eventually consistent technique, with continuous updates
and managed inconsistency.
Advantages: Although using two internal techniques may seem complex, dead
reckoning is a simple technique with excellent properties when used in distributed
systems. It is also mature, with many decades of practical experience already
available.
If the local game engine keeps receiving new information, dead reckoning ensures
a state of smooth inconsistency, which the players experience positively.
Lock-step Consistency
Toward the end of 1997, multiplayer gaming was already commonplace, and
games like Age of Empires were launched with much acclaim and sold to millions.
The technical conditions were much improved over the humble beginnings of such
games, around the 1960s for small-scale online games and through the 1970s for
large-scale games with hundreds of concurrent players (for example, in the
PLATO metaverse). Players could connect with the main servers through high-
speed networks... of 28.8 Kbps, with connections established over dial-up (phone)
lines with modems. So, following a true Jevons' paradox, gaming companies
developing real-time strategy games focused on scaling up, from a few tens of
units to hundreds, per player.
One more ingredient is needed to have a game where the state of every unit -
location, appearance, activity, etc. - appears consistent across all players: the state
needs to be the same at the same moment because players are engaged in a
synchronous contest against each other. So, the missing ingredient is a
synchronized clock linked to the consistency process.
Lock-step consistency occurs when simulations progress at the same rate and
achieve the same status at the end (or start) of each step (time tick).
One approach to achieve lock-step consistency is for all the computers in the
distributed system running the game to synchronize their game clocks. Players
would input their commands to their local game engines, which the local game
engine communicates over the network to all other game engines. Then, every
game engine updates the local status based on the received input, either
A main benefit of this approach is that the approach trades-off communication for
local computation: the communication part is reduced only to necessary updates,
such as player inputs, and the game engines recompute the state of the game using
dead reckoning and the inputs. The network bandwidth is therefore sufficient for a
game like Age of Empires with 1,500 moving units.
First, we partition the virtual world into areas so that the game engine can select
only those of interest for each player. Second, the game engine updates areas
judiciously. Some areas do not receive updates because no player is interested in
them. Areas interesting for only one player are updated on that player's machine.
Each area that is interesting for two or more players is updated with lock-step or
communication-only consistency protocols, depending on the computation and
communication capabilities of the players interested in the area.
Conit-based Consistency
Although lock-step consistency is useful, in games where many changes occur that
do not fit local predictors, so for which dead-reckoning and other computationally
efficient techniques are difficult to find, it is better when scaling the virtual world
to allow for some inconsistency to occur. In particular, games such as Minecraft
could benefit from this.
Any conit-based consistency protocol uses at least one conit to capture the
inconsistency in the system along the three dimensions. Time elapsed and data-
changing operations lead to updates to the conit state, typically increasing
inconsistency values along one or more dimensions. At runtime, when the limit of
inconsistency set by the system operators is exceeded, the system triggers a
consistency-enforcing protocol and the conit is reset to (near-)zero inconsistency
across all dimensions.
Conits provide a versatile base for consistency approaches. Still, they so far have
not been much used in practice for two main reasons: First, not many applications
exist that would tolerate significant amounts of inconsistency. Second, setting the
thresholds after which consistency must be enforced is error-prone and application-
dependent.
We study in this section what replication is and what are the main concerns for the
designer when using replication. One of the main such concerns, consistency of
data across the replica, relates to an important functional requirement and will be
the focus of the next sections in this module.
What is Replication?
Like resource sharing, replication can occur (i) in time, where multiple replicas
(instances) co-exist on the same machine (node), simultaneously, or (ii) in space,
where multiple instances exist on multiple machines. Figure 1 illustrates how data
or services could be replicated in time or in space. For example, data replication in
space (Figure 1, bottom-left quadrant) places copies of the data from Node 1 on
several other nodes, here, Node 2 through n. As another example, service
replication in time (Figure 1, top-right quadrant) launches copies of the service on
the same node, Node 1.
Replication can increase performance. When more replicas can service users, if
each can deliver roughly the performance of the source replica, the service
effectively increases its performance linearly with the number of replicas; in such
cases, replication also increases the scalability of the system. For example, grid and
cloud computing systems replicate their servers, thus allowing the system to scale
to many users with similar needs.
When replicating in space, because the many nodes are unlikely to all be affected
by the same performance issue when completing a share of the workload, the entire
system delivers relatively stable performance; in this case, replication also
decreases performance variability.
Geographical replication, where nodes can be placed close-to-users, can lead to
important performance gains, guided by the laws of physics, particularly the speed
of light.
Replication can lead to higher reliability and to what practice considers high
availability: in a system with more replicas, more of them need to fail before the
entire system becomes unavailable, relative to a system with only one replica. The
danger of a single point of failure (see also the discussion about scheduler
architectures, in Module 4) is alleviated.
When multiple replicas can perform the same service concurrently, their local state
may become different, a consequence of the different operations performed by
each replica. In this situation, if the application cannot tolerate the inconsistency,
the distributed system must enforce a consistency protocol to resolve the
inconsistency, either immediately, at some point in time but with specific
guarantees, or eventually. As explained during the introduction, the CAP theorem
indicates consistency is one of the properties of distributed systems that cannot be
easily achieved, and in particular it presents trade-offs with availability (and
performance, as we will learn at the end of this module). So, this approach may
offset and even negate some of the benefits discussed earlier in this section.
Replication Approaches
Replica-server location: Like any data or compute task, replicas require physical
or virtual machines on which to run. Thus, the problem of placing these machines,
such that their locations provide the best possible service to the system and a good
trade-off with other considerations, is important. This problem is particularly
important for distributed systems with a highly decentralized administration, for
which decisions taken by the largely autonomous nodes can even interfere with
each other, and for distributed systems with highly volatile clients and particularly
those with high churn, where the presence of clients in one place or another can be
difficult to predict.
An interesting problem is how should new replica locations emerge. When replica-
servers are permanent, for example, as game operators run their shared sites, or
web operators mirror the websites, all that is needed is to add a statically
configured machine. However, to prevent resource waste, it would be better to
allow replica-servers to be added or removed as needed, related to (anticipated)
load. (This is the essential case of many modern IT operations, which underlies the
need for cloud and serverless computing.) In such a situation, derived from
traditional systems considerations, who should trigger adding or removing a
replica-server, the distributed system or the client? A traditional answer is both,
which means that the designer must (1) consider whether to allow the replica-
server system to be elastic, adding and removing replicas as needed, and (2) enable
both system- and client-initiated elasticity.
Replica placement: Various techniques can help with placing replicas on available
replica-servers.
What to update? Replicas need to achieve a consistent state, but how they do so
can differ by system and, in dynamic systems, even by replica itself (e.g., as in [3]
for an online gaming application). Two main classes of approaches exist: (i)
updating from the result computed by one replica (the coordinating-replica), and
(ii) updating from the stream of input operations that, applied identically, will lead
to the same outcome and thus a consistent state across all replicas. (Note (i)
corresponds to the passive replication described at the start of this section, whereas
(ii) corresponds to active replication.)
When to perform updates? With synchronous updates, all replicas perform the
same update, which has the advantage that the system will be in a consistent state
at the end of each update, but also the drawbacks of waiting for the slowest part of
the system to complete the operation and of having to update each replica even if
this is not immediately necessary.
With asynchronous updates, the source informs the other replicas of the changes,
and often just that a new operation has been performed or that enough time has
elapsed since the last update. Then, replicas mark their local data as (possibly)
outdated. Each replica can decide if and when to perform the update, lazily.
With pull-based protocols, clients ask for updates. Different approaches exist:
clients could poll the system to check for updates, but if the frequency is polling is
too high the system can get overloaded, and if it is too low (i) the client may get
stale information from its state, or (ii) the client may have to wait for a relatively
long time before obtaining the updated information from the system, leading to low
performance.
As is common in distributed systems, a hybrid approach could work better. Leases,
where push-based protocols are used while the lease is active, and pull-based
protocols are used outside the scope of the lease, are such a hybrid approach.
References:
[1] The BBC, Microsoft says services have recovered after widespread outage,
Jan 2022.
[2] Sacheendra Talluri, (2021) Empirical Characterization of User Reports about
Cloud Failures. 2021.
[3] More on Consistency and Replication
Compiled by: Ararsa Lemmessa (Eng.) Rift Valley
University
Naming schemas in distributed systems provide a method for entities to identify and set up communication channels with one another, ensuring connectivity and coordination. The schemas include Simple Naming, which uniquely identifies entities without location context; Hierarchical Naming, which assigns names based on a hierarchy that suggests organizational structure; and Attribute-based Naming, where names include descriptive attributes. These schemas enable systems to scale effectively, manage entity states, and maintain communication consistency across diverse environments .
Request-Reply involves a straightforward one-to-one communication where a sender requests and a receiver responds. Publish-Subscribe allows multiple machines to subscribe to updates from others, suitable for disseminating updates to interested parties, like in gaming. Pipeline employs producers and consumers, enabling easy scaling and load balancing by adding machines. Broadcast sends messages to all entities, useful for bootstrapping and conveying global states but can lead to network congestion. Flooding is similar but repeats broadcasts among receivers, suited for fast dissemination but requires mechanisms to prevent overload. Multicast bridges these, sending messages to a defined group, such as teammates in a game, rather than everyone or one specific receiver .
Passive replication differs from active replication in that it relies on a primary replica to process tasks and broadcast updates to secondary replicas, thereby reducing computational demands on the receivers. Conversely, active replication involves all replicas receiving and processing the input stream of tasks independently, minimizing the need for extensive network communication. The choice between these approaches often hinges on the available resources—passive replication is favored when computing resources are limited, while active replication is preferred for minimizing network load and enhancing fault tolerance .
Dead reckoning in online gaming is used to mitigate the effects of network delays by predicting the trajectory of in-game entities based on recent activity. The technique allows games to simulate future positions of objects assuming constant velocity or direction, reducing reliance on immediate network updates. When discrepancies occur between predicted and actual states, dead reckoning adjusts gradually rather than abruptly to prevent jarring state changes that disrupt the user's experience. This predictive method ensures continuity and smoothness in gameplay, essential for user immersion .
Asynchronous updates in distributed systems allow replicas to update at different times, accommodating variance in workload and network latency, thereby offering improved performance and scalability. However, this can lead to temporary inconsistencies until all replicas are updated, unlike synchronous updates where all changes finalize simultaneously, ensuring consistency at the cost of performance. Synchronous updates require waiting for all nodes to complete the update process, thus potentially introducing delays if any node is slow. The choice between asynchronous and synchronous updates affects the balancing of consistency, system throughput, and latency .
Replica placement in large-scale distributed systems involves strategic considerations such as server location, population density, and network connectivity. Proper placement ensures optimal access and load distribution, reducing latency and enhancing reliability. However, trade-offs include costs associated with maintaining additional replicas and potential overcomplication of network resources. While close placement enhances accessibility, it can increase operational costs and resource redundancy. Thus, balancing these factors is crucial for maintaining efficiency and ensuring high availability in distributed architectures .
Gossip-based communication provides a less resource-intensive alternative to flooding by involving periodic, random exchanges of information between neighbors rather than inundating the entire network with data. This method allows information to spread incrementally and probabilistically across the network without taxing bandwidth resources. Unlike flooding, where every node rebroadcasts to all neighbors, gossip limits the spread to selected interactions, effectively reducing the overall network load while maintaining high probability of wide-scope dissemination .
Naming Services are crucial in managing the dynamics of virtual machine instances in datacenters, as they allow systems to move seamlessly between machines without losing connectivity. These services maintain mappings between entity names and their physical or virtual locations, which are essential as entities can quickly migrate or scale across different servers due to workload demands. They enable communication continuity by ensuring message routing and connection establishment adhere to current operation conditions of entities, thereby providing resilience against sudden changes in the system's physical architecture .
RMI extends the capabilities of RPC by introducing the notion of remote objects, which are based in object-oriented programming languages like Java and Python. Unlike RPC, which deals only with remote procedure calls, RMI allows method invocation on remote objects, supporting the complexities of remote-object state management. This involves having the object located on the server with its methods, while the client interacts with a proxy that acts as a client stub. On the server side, a skeleton receives and executes the method call on the appropriate object. This system introduces additional complexity due to maintaining and managing the state of remote objects .
CRDTs address inconsistency issues in distributed systems by ensuring that replicas of data types can be reconciled correctly through only allowing monotonic operations, such as additions. These data types allow merging operations across all replicas to achieve a consistent end state, regardless of the execution order. This guarantees eventual consistency without central coordination. However, CRDTs impose constraints like disallowing non-monotonic operations (e.g., deletions or modifications) since these could lead to divergent states that cannot be reconciled through simple union operations .