Checklist

Checklist

Index

IoT2 - Theory - Lecture 6 - Distributed Control Algorithms

  • Slide lez 6
  • Chapter 18 Dhamadhere

Introduction

Midterm Exercises

The algorithms shown in this section are topic of the midterms. A possible exercise is, given process, the time at which they make a request and the time they stay in critical section, shows all the steps until the last process quit the CS.

Every algorithm from this lecture could be in the midterm.

A distributed operating system performs several control functions.

Of these control functions:

  • The mutual exclusion and deadlock handling functions are similar to those perfomed in a conventional OS.
  • Scheduling function performs load balancing to ensure that computational loads in all nodes of the system are comparable
  • The election function elects one among a group of processes as the coordinator for an activity
  • The termination detection function checks whether processes of a distributed computation operating in different nodes of the system have all completed their tasks

To respond speedily and realibily to events occurring in a distributed system, a distributed OS performs a distributed control algorithms. The actions of this algorithms are performed in several nodes of the distributed system.

Distributed control algorithms depend on local states of different nodes, and use interprocess messages to query the states and make decisions. The correctness of the algorithm must be proved to ensure that they arrive at the correct decision.

Overview of Control Functions in a Distributed OS

Parts of a process

The following terminology is used to distinguish between actions of a client and those of a control algorithm:

  • Basic computation: performs the application part of the code
  • Control Computation: partecipate to the implementation of the distributed control algorithm

For example, consider the mutual exclusion problem: multiple process share a common resource, such as access to specific data. At the application level, an instruction grants access to this data. However, to ensure mutual exclusion, a process must coordinate with others requesting access to the critical section (CS) to determine the next process allowed to enter. The part of the process that coordinate the process with others is the control part.

  • The control part of a process , requests access by asking other processes, “Can i enter the critical section?” If a receiving process is not interested in the CS, it responds with something like “OK for me

When the basic part requires a service provided by a control algorithm it make a request to the control part . The control part then communicates with the control parts of other processes and may interact with the kernel to enforce control mechanisms.

While the basic part may become blocked when requesting a resource. the control part of a process never blocks, ensuring it can always respond to relevant events in a timely manner.

Example: basic and control parts of a process

Correctness of distributed control algorithms - Liveness and Safety

Two aspects of correctness are called liveness and saftey:

  • Liveness: the algorithm will eventually perform correct actions, i.e, perform them without indefinite delays
  • Safety: the algorithm will never take the wrong decision

A practical example of these properties: We model each algorithms as set of rules, that are performed only if there is a certain condition

Here is the notation:

<condition> : <action>

Using the notation for the words “eventually leads to”, we define the notion of the correctness as follows:

  • Liveness: For all rules, it means that will eventually be performed if holds.
  • Lack of safety: For some rule, i.e may be eventually perfomed even if condition does not hold.

Ricart-Agrawala Algorithm

The algorithm is fully distributed (no coordinator): all processes partecipate equally in deciding which process should enter a CS next.

The idea of this algorithm is very simple: a process sends a message to all other processes, requesting permission. Before a process can enter the CS, messages must be exchanged.

Mutual exclusion is ensured because at most one process can receive replies at any given time.

Each message is timestamped, allowing requests to be ordered. If a process is already in the CS when it receives a request, it places the request in a queue, ensuring First-Come, First-Served (FCFS) access.

The FCFS ordering guarantees liveness, meaning that all processes will eventually gain access to the CS. Each process maintains its own queue of requests.

Steps of the Algorithm

Ricart-Agrawala - Example 1

In a system with three processes, if P1 is in the critical section (CS) and P2 requests access, P1 cannot grant it immediately. Instead, P1’s control mechanism queues P2’s request as pending. If P3 does not need access, it simply replies “go ahead” to P2’s request.

Later, if P3 also requests access, it sends requests to both P1 and P2. Since P2 is still waiting, it checks timestamps and sees that its request has priority over P3’s. So, P2 queue the request of P3 and keeps waiting. Also P1, who is already in the CS, queue the P3 request after the P2 (because of timestamping).

When P1 exits the CS, it notifies its control mechanism, which then sends reply messages to both P2 and P3. Since P2 has the oldest request, it enters first, while P3 waits until P2 finishes, ensuring that access follows the correct timestamp order.

Ricart-Agrawala Example 2

Let’s see now the example considering timestamp

  • (a)
    • P0 send a request at time T=4 to P1 and P2
    • P2 send a request to T=8. so it should go after.
    • Since the timestamp of P0 is T=4, so it enter first in the CS
  • (b)
    • P1 receive a request from both P0 and P2, but because P1 is not interested, immediately responds to both P0 and P1.
    • Note: the request is send as soon as it arrives, (i.e at T=4, P1 will send the OK reply to P0)
  • (c)
    • P2 confronts the timestamp and see that the P0 request has a lower timestamp than its own: , so it sends the OK to P0
    • P0 has now received the OK from both P2 and P1, so it can enter the CS and also queue the P2 Requests.
  • (d)
    • Once P0 is finished, it sends a “go ahead” message to P2 (whose request was enqueued).
    • P2 since has received an OK from everyone else, it enters the CS

If for instance in (c), both P1 and P2 want to enter the critical section, at the same time. P1 sends a message to both P0 and P2, with timestamp T=10. P0 enqueed the request (that will be ). P2 also receive the request, but its own request was timestamped T=8, the request is timestamped with T=10, then P1 goes into the local queue of P2.

Note that these timestamps are managed using logical clocks, ensuring that no two process send a message at the exact same time. As a result, a message cannot be sent and received simultaneously.

The problem of this algorithm is the high number of messages. A possible workaround is to reduce the number of messages using the quorum approach

Quorum based algorithm

  • Idea: request access to the critical section to a subset of processes called request set
  • Problem: how to build the request sets, i.e select the processes belonging to each request set
  • Solution: build non-disjoint request sets such that at least one process belongs to two or more request sets.

Let be a set of processes :

  • a Quorum is a subset of
  • A Coterie is a set of quorums

Properties of a coterie:

  • minimality: no quorum is a subset of anther quorum
  • intersection: the intersection of each pair of quorums is non void.

A process must obtain permissions from a subset of processes in the system. is called the request set of .

The algorithm uses the following rules to ensure safety:

  • all process must belongs to atleast one request set
  • for each pair of process, the intersection of their request set must be not null

Note that, the central process, shared across all quorums, ensures that no process gains access to the critical section unless every relevant quorum permits it. Since this process sits at the intersection, it has visibility over all request queues.

This distributed algorithm does not distribute responsibility equally among processes. The central process plays a distinct role, bearing greater responsibility and workload compared to the others.

Maekawa Algorithm

The idea is to find a Coterie, that guarantees equal effort, and equal responsibility for all the processes that take part to the algorithm.

Given processes, to each process a request set is associated, such that the following 4 properties hold:

  1. (non void intersection as before)
  2. Equal effort: where is the number of processes in each request set
  3. Equal responsibility: each , belongs to the same amount of requests set per
  4. Minimize the number of messages: for each , belongs to

Maekawa proved that the optimal solution that minimizes the value can be obtained by the following equation:

From which the value can be derived:

For example, if , , so if we have 3 processes, K=2, so each process has to belongs to two quorums, and each quorums must contain 2 processes. Instead of sending 6 messages and waiting 6 replies, it just send the requests to its own quorum.

For example, , :

Rules of the algorithm

Over this organization, we have to define the rules of the algorithm

3 types of messages: request, reply and release.

When a process wants to access the critical section, it sends a REQUEST message to the other processes of (i.e his quorum).

When a process receives a REQUEST message from , it responds with a REPLY message unless:

  • it is active in the critical section
  • OR has already sent a REPLY messages to another process.

In the latter case, enqueue the request of

To release the critical section, a process sends a RELEASE message to the other members of .

When a process receives a RELEASE message, the first request is dequeued and a REPLY message is sent to the process.

Proof of safety by contradiction

Let, for contradiction, and be two processes active in the critical section at the same time.

From the coterie intersection property: is the process that appartain to both the quorum of and .

should have sent two REPLY messages to both and without anyone releasing the critical section. But this is a contradiction (following the rules of the algorithm).

Problem of the algorithm (deadlock)

The algorithm could lead to a deadlock, when all processes request the access to the critical section at the same time. Each process receives only one of two REPLY messages, so no process can progress and there is a deadlock.

Saunders 1987 proposed a variant of the algorithm deadlock-free that emplys the happened-before (timestamp) relationship.

Token-based Algorithms for Mutual exclusion

Token

A token represents the privilege to use CS; only a process possessing the token can enter the CS.

The token guarantees the safety but not liveness. Liveness is a property of the algorithm rules that uses the token.

The processes have to be organized in a such way that, each request to enter the critical section must arrive from a process with the token.

So an abstract model (overlay network) must be first considered. This logical model is an abstract unidirectional ring model.

The token, is an object (a data structure) containing the queue of the pending requests.

Ring Topology

The edges represents the unidirectional channel that a process uses to comunicate with the following node in the ring

Recall that, with the topology of ring, each process can be reached with a finite number of message.

Algorithms steps

Example

If is active in the critical section, the request of will be inserted in the queue of the token. When exit the critical section, the token will follows the connection and arrive to .

If wants to enter the critical section it just put the request on the ring and it is added to the queue.

The liveness is guaranteed by the abstract view of the system. Since the ring is closed, and the token is passed after a process finishes using the CS, the token will eventually arrive to the process that request the access of the critical section.

Raymond Algorithm

Inverted Tree and token holder

Uses an abstract inverted tree as the system model. An inverted tree differs from a conventional tree because its edges point from each node toward its parent, rather than from the parent to its children.

Why this structure? The tree has a single root, which is the process holding the token. At any moment in the algorithm, the root represents the token-holding process, denoted as .

Each child (that want to enter the CS) send a request to his parent, that propagates the request to his father, until it reaches the root.

Raymond’s algorithm has four key features:

  • invariants that ensure that a request reaches
  • a local queue of requesters in each node
  • features to reduce the number of request messages
  • provisions to ensure liveness

Raymond Algorithm - Steps of the Algorithm

In step 3, after a process completes execution of a CS, it means that is the root of the tree. it has its own local queue. And image that make a request to enter the CS. When exit it, if its local queue is non empty, this means that there is atleast a pending request. extract the first id from the queue and send it to the token with this id. ( in this example), and becomes the holder. But the holder must be always the root of the tree, so in order to satisfy this requirements, upon sending, changes the direction of this edge. becomes a child of . If has other requests (as in the next example), if will send a request message with his own id to .

Example of Raymond Algorithm

  • is the holder and is in critical section, with and in its queue (meaning they have both made requests).
  • (a) Let’s analyze the request coming from .
    • has in its own queue, this means that has itself made a request to enter the critical section.
    • Recall that doesn’t propagate the id but its own id.
    • Why? Because only knows his immediate childs, it doesn’t know who is
  • (b) Once quits the critical, becomes the new root of this tree, inverting the edge.
    • will then check its own queue, extract and propagate the token to and invert the edge .
    • Since is the only process in its queue, it enters the critical section
  • (b) To guarantee the liveness, must receive the token in a finite number of step. When sends the token to and change the edge, it also send a request for itself that is enqueued in .
  • When sends the token to , because there is another request, it also send a request to with its own id. And so , after he finished and extract first id from its queue, will send the token to once it has finished the actions in the CS.
  • The same does for and same to , that finally receives the access to the critical section.

Token-based centralized algorithm

In this centralized approach, we have a specific process called coordinator that handles the token. The coordinator keeps track of the requests submitted (but not yet served) and requests served.

Each process stores a vector clock in which timestamps of the requests are reported. (See previous lesson: time in a distributed system)

When a process wants to enter the CS, it submits a request to the coordinator. The coordinator inserts the request in a list of pending requests. When the request become eligible, the coordinator sends the token to that enters the CS.

On exiting the CS, send the token back to the coordinator.

Coordinator

Data structure:

  • : stores the list of the requests submitted but not yet served
  • : the vector of length equal to the number of process. Position V[i] stores the number of request already served for process

Rules:

  • requests the token
  • when request is eligible and the coordinator has the token, sends it to

Client

Data Structure:

  • : timestamp vector clock Rules:
  • Token Request: and sends VC to the coordinator
  • Token reception: enters CS
  • CS exit: sends token to the coordinator

Example

  • Let the process be Coordinator, ,
  • increases and send the request to the coordinator What if P2’s request arrives before P1’s? Since we are using vector clocks, P1 sends its request with a timestamp of (1,0), but the first request to reach the coordinator is from P2, with a vector clock of (1,1).

The coordinator then compares this vector clock with its request list, which tracks already satisfied requests. By doing so, it determines that P2 has requested access, but there is a pending request from P1 that has not yet been served. Because P2’s message arrived first, the coordinator knows that a request from P1 must have been sent earlier.

As a result, P2’s request is not yet eligible for execution. Since the communication is reliable, eventually P1 request will arrive, containing the vector (1,0) and becomes eligible. Once the request has been served and the token is passed back to the coordinator, it’s the turn of P2.

Another interesting scenario arises when P1 and P2 do not communicate with each other. In this case, P2 cannot update its own vector clock with requests made by P1. When P2 wants to request access to the critical section, it simply increments its own position in the vector clock, resulting in (0,1).

If this request (0,1) arrives at the coordinator, the coordinator’s request list initially contains (0,0). Now, with the arrival of (0,1) from P2, the request becomes eligible because, at this point, no other process has requested access to the critical section.

However, if we later compare P1’s request (1,0) with P2’s request (0,1), we see that neither vector dominates the other. As discussed in the lecture on vector clocks, this means that no message has been exchanged between P1 and P2 regarding their requests. Therefore, these two requests are considered concurrent, and the coordinator can sort them as he wants.

Safety is guaranteed by the token. Liveness is guaranteed by the happened-before relationship and by the presence of the token.

This is an example of algorithm based on the use of the vector clock. An extention to this algorithm, also token-based but completely distributed is the Suzuki-Kasami algorithm.

Token-based distributed algorithm - Suzuki-Kasami Algorithm

The needed data structures are stored into the token, that is passed to each process. When a process wants to enter the CS and does not hold the token, sends a broadcast message. The process that holds the token, if not in the CS, replies with the token, while if it is active in the CS releases the token after exited.

Data structure of the process :

  • : vector of length , where stores the sequence number of the last request submitted by process

Data structure into the token:

  • : vector of length where stores the sequence numer of the last fulfilled request of process
  • : queue of pending requests

Suzuki-Kasami Example 1 with 3 processes

For example, if we consider three processes, requested the CS, and doesn’t want yet to enter it, so is the first to receive it. It increases by 1. After he finished to use the CS, he increased by 1. The queue is empty since no other process made a request.

Note: in this example i omitted it, but also and got their own (reqlist) vector, which is equal to , because first send a request in broadcast to get the token. Inside the token we also have a queue of pending requests, so each time a process request to access the critical section and this is not immedietaly served, this request is enqueued. So for example, if in Q i have process p2, it means that it has submitted to enter the critical section but this request has not been served.

Say that make a request: firsts send a msg in broadcast

At this point, say that is still in the CS. is added to the queue:

Say that, finishes. So it increases his to 1 (sorry for the error in the slides!). It check the Queue, see that wants the token, so it releases it to

Upon the exit of the critical section by , it will update , so that the vector becomes .

Note that these two structures that in previous algorithm were mantained by a coordinator, are now shared between processes inside a token.

Suzuki-Kasami rules

Rules for process : token request, token request from with timestamp t and exit cs

Token Request

  • - increase its own counter
  • For each send (Request, , ]) - all processes receive the request

Token Request from with timestamp t ( is the process that has sent the request to enter the CS)

  • if holds the token AND it is not in CS AND , send the token

Exit CS:

  • (request fulfilled)
  • For each not in , is enqueued in Q if (there is a pending request).
  • If Q is not empty, dequeue and send to it the token
  • If Q is empty, hold the token.

Suzuki-Kasami - Example 2

  • P0 holds the token (red circle). The vector L=last, and R=req. At this time the queue is empty.
  • There is a pending request made from P0, if so it means that it can enter the critical section and P0 holds the token. During the execution of the critical section, p1 and p2 sends request to enter the CS:

  • Note that p1 and p2 sends a msg to all process, so they ALL update req.
  • P0 exit the critical section

  • Insert last two requests (1,2) in the set
  • scan its own request here (req) and all the time, the request is equal to — this is interpreted as there is a pending request from p1 (req) but has not be fullfilled ()
  • For p3 and p4 there are no pending requests.
  • After this, P0 scan the and send the token to P1.

During the execution of the CS, other request arrives

  • When the critical section is terminated, the queue is updated
  • Note that P2 was already in the queue so is not inserted there again, only 0 and 3 are added
  • After this the token is sent to 2

Safety and liveness

Safatey is guaranteed by the token Liveness is guaranteed by the queue of pending request and the presence of the token

Leader election

Even though centralized algorithms are not always the most efficient choice, they are often useful because they reduce the number of messages exchanged (more efficient). When using a coordinator-based algorithm, all participating processes must also implement a leader election algorithm to ensure that a new coordinator can be selected in case the current one fails.

As long as there is a leader election algorithm, where all process partecipate to the decision in case of failure, the leader election approach is viable.

This means that every process must include the logic required to assume the coordinator role if necessary. This concept is also present in Zookeeper, a Hadoop module designed for distributed coordination, which implements a leader election algorithm to ensure a new coordinator is chosen in case of failure.

To determine the coordinator, we need a clear rule. Election algorithms are based on some definition of priority. For example, the coordinator is the process with the higher id (or any other kind of priority).

Bully Algorithm

The election algorithm starts at the moment a process verify that the coordinator is inactive. If a process sends a request and the coordinator does not respond in a time interval , assumes that the coordinator is no longer active.

A process will sends the message of election only to processes with id higher than itself and waits for a time for a reply. If does not get any response, it assumes that all processes are down, elects itself as coordinator, starts a copy of the coordinator and send a message to all processes with lower priority than its own informing them that it is the new coordinator.

If it receives a response, it waits to receive a message informing it which process with higher priority than its own has been elected coordinator.

Bully Algorithm - Example

  • starts the elections, it send a message only to and (that we assume is down, hence the X). will not be involved in the election, their id is lower. (You see now why it’s called bully, is trying to elect itself).
  • and receive a msg from , they send a OK response to , so they know for sure that will never be the new coordinator (bro is never gonna make it) and stop his election.
  • Now, and starts the election, (see (c)), but wins (since it sends OK to , stopping his election)

What happens if in the future returns active? has the highest process id in the system, so it immediately sends a new election msg to verify it is the highest process id and so becomes the new coordinator.

Election Algorithms for Ring Topology

Consider a unidirectional ring topology. Processes have a unique ID and are logically organized in a ring. Every process knows its neighbors and the coordinator is the process with the highest ID.

The ELECTION message is sent to each successor until a live node is found. Each process adds its own ID to the message. The message returns to the process that initiated the election which chooses the coordinator as the process with the highest ID. So it send a message communicating the new coordinator.

There may be multiple elections in the case of system partitioning. We assume that the ring is split due to the failure, meaning different sections of the system might attempt to elect their own coordinators. However, having multiple coordinators in different sections would result in an inconsistent state, which is not allowed in every distributed systems

Here’s a simple example

Variant: Highest Id

Each process sends its own identifier along the ring. When a process receives an identifier, it compares it with its own:

  • If the values are different, circulates the received identifier along the ring only if greater than its own, otherwise it replaces it with its own
  • If the values are equal, declares itself the leader

After steps, the leader will receive its own id, and when it receives its own id, he will know it’s the new coordinator.