Seminar 10: Implementation of two-phase commit protocol in python
Goal: To study and practice the implementation of two-phase commit protocol in python for distributed applications.
Background: The states of the replicas of an application should remain to be identical at the end of the processing of each request. Replica consistency is necessary to ensure the consistent copies of the same data in every replica. It means the degree in which the data becomes visible to every node in the system (same order and value). The consistency depends on the context/application, e.g., weak vs sequential.
ACID properties of transactions: to guarantee data validity despite errors, power failures, and other mishaps.
- (A)tomicity guarantees that partial failures are not possible
- Committed successfully
- Rolled back (as if they never happened)
- Transactions either succeed and their changes are committed, or transactions fail without any side effect on the data store
- If a transaction updates data on multiple nodes, this implies
- Either all nodes must commit, or all must abort
- If any node crashes, all must abort
- (C)onsistency guarantees application-level invariants to be preserved
- “C” in ACID has nothing to do with consistency models – “Correctness”
- Data is in a consistent state when a transaction starts and when it ends.
- (I)solation guarantees that the concurrent execution of transaction does not cause any race condition
- The intermediate state of a transaction is invisible to other transactions. As a result, transactions that run concurrently appear to be serialized.
- (D)urability guarantees that once the data store commit the transactions, the changes persisted
- After a transaction successfully completes, changes to data persist and are not undone, even in the event of a system failure.
Two-phase commit protocol (2PC)
- The two-phase commit protocol (2PC) is a type of atomic commitment protocol (ACP). It is a distributed algorithm that coordinates all the processes that participate in a distributed atomic transaction on whether to commit or abort (roll back) the transaction. The protocal works in the following manner: The client who initiated the computation acts as coordinator; processes required to commit are the participants. There are two phases for this protocol.
- Commit request (or voting) phase:
- Coordinator sends a query VOTE-REQUEST to participants (also called a pre-write) and waits until it has received a reply from all participants
- When participant receives VOTE-REQUEST it returns either VOTE-COMMIT or VOTE-ABORT to coordinator. If it sends VOTE-ABORT, it aborts its local computation
- Commit (or completion) phase:
- Success -- VOTE-COMMIT:
- Coordinator collects all votes; if all are VOTE-COMMIT, it sends GLOBAL-COMMIT to all participants.
- Each participant completes the operation, and releases all the locks and resources held during the transaction.
- Each participant sends an acknowledgement to the coordinator.
- The coordinator completes the transaction when all acknowledgements have been received.
- Failure -- VOTE-ABORT:
- The coordinator sends a GLOBAL-ABORT(rollback) message to all the participants.
- Each participant undoes the transaction using the undo log, and releases the resources and locks held during the transaction.
- Each participant sends an acknowledgement to the coordinator.
- The coordinator undoes the transaction when all acknowledgements have been received.
- Success -- VOTE-COMMIT:
Exercise: We will get acquainted with the Two-phase commit protocol (2PC) in python. We assume reliable communication (no messages are loss), a process node “C” acting as client commits a value to the whole system of nodes through the “coordinator” node. The message passing is based on UDP through sockets. User Datagram Protocol (UDP) is a communications protocol that is primarily used to establish low-latency and loss-tolerating connections between applications on the internet. The code for the above implementation is given here for you (code). In the 2PC.txt:
- #System defines the name of each process in the system and defines the coordinator. From the file format example, P1, P2 and P3 are participants, and P4 is coordinator.
- #State provides a consistency history of states, meaning the different values the system had committed as a whole from start to latest. For instance, first committed value is 4 and current (latest) value is 9.
Working Pipeline
$ python main.py
UDP Sending message:
def send_list(destination_id): ip = "127.0.0.1" port = 10000+destination_id s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0) string = "list_all;" s.sendto(string.encode('utf-8'), (ip, port))
Datagram Protocol: The class where you actually implement the protocol parsing and handling will usually be descended from twisted.internet.protocol.DatagramProtocol. The DatagramProtocol class receives datagrams and can send them out over the network. Received datagrams include the address they were sent from. When sending datagrams the destination address must be specified.
from twisted.internet.protocol import DatagramProtocol from twisted.internet import reactor class Client(DatagramProtocol): def datagramReceived(self, datagram: bytes, addr): # message passing datagram = datagram.decode('utf-8') self.process_datagram(datagram) ## message writing reactor.listenUDP(10000+coordinator, Client(coordinator, 'localhost', "P"+str(id), copy.deepcopy(states), copy.deepcopy(systems), -1)) reactor.run()
Task: Based on the exercise, Please implement the Two-phase commit protocol (2PC) with the following commands:
- $ Set-value X -- This command sends a new value “X” to the system (to be committed)
- If X = 20, the state should be [4,5,6,7,8,9,20]
- $ Rollback N --This command rolls back to previous values based on a number N of positions. For instance, following our previous example, “Rollback 2” should take the system back to value 7. For simplicity, all values after the rolled back value are forgotten by the system. In this example, all values after 7 are loss.
- If N=2, the state should be [4,5,6,7] or only [7]
- Handling errors: Notice that errors should be handled by providing a message warning through console. For instance, $ Rollback 25 -> “The system cannot reverse to that long state”
- $ Time-failure PX time -- It makes a specific process “PX” unavailable in the system for a period of “time” in seconds. This means that the process cannot be reached nor respond to any external request. After the time is over, the process becomes again available and continues its normal operations. For instance, $ Time-failure P2 120
Deliverables: please contain the source python file, and also the screenshot of results in terminals. Then put all the file in a single zip.
Link:
- https://en.wikipedia.org/wiki/ACID
- https://en.wikipedia.org/wiki/Two-phase_commit_protocol
- https://en.wikipedia.org/wiki/User_Datagram_Protocol
- https://wiki.python.org/moin/UdpCommunication
- https://twistedmatrix.com/documents/15.1.0/core/howto/udp.html#datagramprotocol
NOTE: Please watch the video or ask us through Slack if something is not clear for you. We usually don't change the points after the deadline.