801 DCexp 3
801 DCexp 3
B801
Experiment No: 3
● Multiple nodes must collaborate and synchronize their actions. Group communication helps them
exchange information and stay updated.
● Different nodes can create data that needs to be shared. Group communication helps quickly send
this information to everyone involved, reducing delays and keeping data consistent.
● Group communication protocols enhance reliability by allowing messages to be replicated or
acknowledged across multiple nodes. This ensures robust communication, even during failures or
network issues.
● As distributed systems expand, effective scaling is crucial. Group communication mechanisms can
manage more nodes and messages without sacrificing performance, keeping the system efficient
and responsive.
Types of Group Communication in a Distributed System
1. Unicast Communication
Unicast communication is the point-to-point transmission of data between two nodes in a network. In
the context of distributed systems:
● Unicast is when a sender sends a message to a specific recipient, using their unique network
address.
● Each message targets one recipient, creating a direct connection between the sender and the
receiver.
● You commonly see unicast in client-server setups, where a client makes requests and receives
responses, as well as in direct connections between peers.
● This method makes good use of network resources, is easy to implement, and keeps latency low
because messages go straight to the right person.
● Unicast isn’t efficient for sending messages to many recipients at once, as it requires separate
messages for each one, leading to more work.
2. Multicast Communication
Multicast communication involves sending a single message from one sender to multiple receivers
simultaneously within a network. It is particularly useful in distributed systems where broadcasting
information to a group of nodes is necessary:
● Multicast lets a sender share a message with a specific group of people who want it.
● This way, the sender can reach many people at once, which is more efficient than sending separate
messages.
● This approach is often used to send updates to subscribers or in collaborative applications where
real-time sharing of changes is needed.
● By sending data just once to a group, multicast saves bandwidth, simplifies communication, and
can easily handle a larger number of recipients.
● Managing group membership is necessary to ensure reliable message delivery, and multicast can
run into issues if there are network problems that affect everyone in the group.
3. Broadcast Communication
Broadcast communication involves sending a message from one sender to all nodes in the network,
ensuring that every node receives the message:
Broadcast is when a sender sends a message to every node in the network without targeting specific
recipients.
● Messages are delivered to all nodes at once using a special address designed for this purpose.
● It’s often used for network management tasks, like sending status updates, or for emergency alerts
that need to reach everyone quickly.
● Broadcast ensures that every node receives the message without needing to specify who the
recipients are, making it efficient for sharing information widely.
● It can cause network congestion in larger networks and raises security concerns since anyone on
the network can access the broadcast message, which might lead to unauthorized access.
1-M (Unicast to Multicast): This is the most common scenario. A central server (or any single
process) distributes information to multiple clients or replicas. Examples include:
● Distributing stock market updates.
● Sending notifications to subscribers.
● Updating replicated databases.
N-1 (Multicast to Unicast): Less common as a primary communication model, but can be used in
specific patterns. For instance:
● Multiple sensors sending data to a single aggregator.
● Clients sending requests to a central server. While the response might be 1-M, the initial
request is N-1.
M-N (Multicast to Multicast): The most general and complex case. Every member of a group can
send messages to every other member. Examples:
● Collaborative applications (e.g., shared document editing).
● Distributed consensus protocols (e.g., Paxos, Raft).
● Peer-to-peer systems.
ordering guarantees in distributed systems
Concept: All processes in the system agree on a single, global order for all messages. It's like
having a single line where everyone waits their turn. If process A receives message m1
before m2, then all other processes that receive m1 and m2 must also receive them in that
same order.
Diagram:
Mechanisms:
Challenges:
Concept: Messages from a single sender are delivered in the order they were sent. However,
there are no guarantees about the order of messages from different senders. Imagine
multiple lines at a ticket counter. Each line is served in order, but the order in which people
from different lines get tickets might be arbitrary.
Diagram:
Mechanisms: Each sender maintains a sequence number for its own messages. Receivers use these
sequence numbers to ensure FIFO order from each sender.
Advantages: Simpler to implement than total ordering.
Disadvantages: Doesn't provide a global view of message order, which can lead to inconsistencies in
some applications.
Use Cases:
Mechanisms:
● Vector Clocks: Capture causal relationships. Each process has a vector of counters.
When a process sends a message, it increments its own counter and includes the
vector clock in the message. The receiver updates its own clock by taking the
maximum of each element.
● Matrix Clocks: An extension of vector clocks for more complex causal relationships.
Use Cases:
● Distributed simulations.
● Collaborative editing.
● Distributed databases where the order of operations matters.
## Implementation:
import time
import threading
@dataclass
class Transaction:
transaction_id: int
sender: str
amount: float
timestamp: float
sequence_number: int
class TransactionNode:
self.node_id = node_id
self.sequence_number = 0
self.transaction_queue = PriorityQueue()
self.processed_transactions = []
self.lock = threading.Lock()
with self.lock:
self.sequence_number += 1
return Transaction(
transaction_id=self.sequence_number,
sender=self.node_id,
amount=amount,
timestamp=time.time(),
sequence_number=self.sequence_number
with self.lock:
self.transaction_queue.put(transaction)
self.balance -= transaction.amount
self.processed_transactions.append(
f"(Balance: ${self.balance:.2f})"
class TransactionSystem:
def __init__(self):
self.global_sequence = 0
self.lock = threading.Lock()
self.nodes[node_id] = TransactionNode(node_id)
with self.lock:
self.global_sequence += 1
transaction = self.nodes[sender_id].create_transaction(amount)
transaction.sequence_number = self.global_sequence
node.process_transaction(transaction)
def main():
system = TransactionSystem()
system.add_node("user1")
system.add_node("user2")
system.add_node("user3")
print("-" * 50)
# Submit transactions
transactions = [
("user1", 100.0),
("user2", 150.0),
("user1", 200.0),
("user3", 300.0)
system.submit_transaction(sender, amount)
print(log)
if __name__ == "__main__":
main()
social_media_consistent.py - Consistent Ordering Implementation
import time
import threading
@dataclass
class Post:
post_id: int
user_id: str
content: str
timestamp: float
class SocialMediaUser:
self.user_id = user_id
self.post_queue = Queue()
self.feed = []
self.post_count = 0
self.lock = threading.Lock()
with self.lock:
self.post_count += 1
return Post(
post_id=self.post_count,
user_id=self.user_id,
content=content,
timestamp=time.time()
self.post_queue.put(post)
self.feed.append(
f"{post.user_id}: {post.content}"
class ConsistentSocialNetwork:
def __init__(self):
self.users[user_id] = SocialMediaUser(user_id)
post = self.users[user_id].create_post(content)
user.receive_post(post)
def main():
network = ConsistentSocialNetwork()
# Add users
network.add_user("alice")
network.add_user("bob")
network.add_user("charlie")
print("-" * 50)
# Simulate posts
posts = [
network.publish_post(user_id, content)
# Print feeds
print(f"\n{user_id}'s Feed:")
print(post)
if __name__ == "__main__":
main()
social_media_causal_demo.py
from dataclasses import dataclass
import time
from typing import List, Dict, Optional
@dataclass
class SocialPost:
post_id: int
user_id: str
content: str
timestamp: float
parent_id: Optional[int] = None
post_type: str = 'post' # 'post', 'comment', or 'reaction'
class User:
def __init__(self, user_id: str):
self.user_id = user_id
self.feed = []
self.post_count = 0
def receive_post(self, post: SocialPost):
self.feed.append(post)
def display_feed(self):
# Sort posts by timestamp
sorted_posts = sorted(self.feed, key=lambda x: x.timestamp)
# Display posts with proper indentation
for post in sorted_posts:
timestamp = time.strftime('%H:%M:%S', time.localtime(post.timestamp))
if post.post_type == 'post':
print(f"[{timestamp}] {post.user_id}: {post.content}")
elif post.post_type == 'comment':
print(f" [{timestamp}] {post.user_id} replied: {post.content}")
else: # reaction
print(f" [{timestamp}] {post.user_id} reacted: {post.content}")
class SocialNetwork:
def __init__(self):
self.users: Dict[str, User] = {}
self.global_post_count = 0
😊
# Create a post
post_id = network.create_post("Alice", "Hello everyone! How's your day going? ")
☕
# Create comments
network.create_post("Bob", "Great! Having coffee ", "comment", post_id)
network.create_post("Charlie", "Just finished a meeting!", "comment", post_id)
❤️
# Create reactions
network.create_post("David", " ", "reaction", post_id)
# Alice responds to comments
network.create_post("Alice", "Coffee sounds perfect right now!", "comment", post_id)
# Print each user's feed
print("\nDisplaying user feeds:")
print("-" * 60)
for user_id, user in network.users.items():
print(f"\n{user_id}'s Feed:")
user.display_feed()
print("-" * 30)
if __name__ == "__main__":
run_demo()
Conclusion:The implementation demonstrates how different ordering mechanisms (Absolute,
Consistent, and Causal) ensure proper message sequencing in distributed systems, with Absolute
ordering guaranteeing global sequence, Consistent ordering ensuring same view for all users, and
Causal ordering maintaining logical dependencies between related messages.