Lab 4 Part 3: Transactions
CSE 452 Fall 2024
Last “Content” Section of the Quarter! ╰(*°▽°*)╯
Distributed Systems in a nutshell
So, how do we finish this quarter?
Goal of Lab 4 Part 3
The number of design decisions on this lab is astronomical - we can’t possibly hope to cover every design issue you can run into, but here are some of the more important points.
The Good News
The Bad News
Two-phase Commit refresher
Lab 4 Part 3: Hints
All ShardStoreServer nodes tag their transaction-handling messages with their configuration number.
Servers reject any prepare requests coming from different configurations, causing the transaction to abort.
Servers delay reconfigurations when there are outstanding locks for keys (i.e., there are transactions pending in the previous configuration).
Transactions
interface Transaction extends KVStoreCommand {
Set<String> readSet();
Set<String> writeSet();
Set<String> keySet(); // union of readSet and writeSet
KVStoreResult run(Map<String, String> db);
}
Operations
MultiGet(set of keys): Get values for list of keys -> MultiGetResult(set of key-value pairs)
MultiPut(map of (key, value)): Put corresponding value into each key -> MultiPutOK
Swap(foo, bar): Swap old value of foo so it is new value of bar, and vice versa -> SwapOK
Two-Phase Commit (100m)
What if we treat these commands down into a series of Gets and Puts?
Prepare Phase
Commit Phase
Note that you can combine 2+3, and 4+5.
Roles for groups
What are the two roles a group can have and how they related to 2PC?
Two-Phase Commit (10,000m)
In the Prepare Phase the coordinator gathers information about the state of the keys in the transaction.
In the Commit Phase the coordinator tells everyone what to update their state to
Two-Phase Commit (One Approach)
There are many ways to do two-phase commit. We will talk about one!
The code for this part of the lab can become complex; it is nice if you can handle MultiGet, MultiPut, and Swap the same way…
What if we treat each command as a series of Gets and Puts?
R2
R1
R3
R{1,2,3} are replica groups. Each is a set of ShardStoreServers, each with a Paxos subnode.
Client
keys={a}
keys={b,c}
keys={d,e}
State: {b:x}
State: {d:y}
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
Swap(keys={b,d})
Client sends a request to the Coordinator. Coordinator is the max({replica group ids involved in this transaction}). In this case, R3 (for key=d) and R2 (key=b) are involved, max(3,2) = 3. So replica group 3 is coordinator.
State: {b:x}
State: {d:y}
Step 1
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
Coordinator sends Prepare messages to all participants in the transaction. Participant should lock keys involved in transaction.
Prepare(command=MultiGet(keys={b,d})
Prepare(command=MultiGet(keys={b,d})
State: {b:x}
State: {d:y}
Step 2 (Prepare Phase)
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
State: {b:x}
State: {d:y}
Step 3 (Prepare Phase)
Each replica group responds with PrepareOK �(including the information on what it’s responding to and current state of the keys it has for that transaction)
PrepareOK(MultiGetResult(b: x))
PrepareOK(MultiGetResult(d: y))
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
Coordinator combines info from PrepareOk’s and runs transaction on the state
(performing a swap in this case)
Phase 1 results:
{b:x} + {d:y} = {b:x, d:y}
Result after transaction:
{b:y, d:x}
State: {b:x}
State: {d:y}
Step 3.5
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
Coordinator sends Commit to Participants with what values should be in the keys.
Participants update only the keys they’re responsible for.
Commit(MultiPut({b:y, d:x})
Commit(MultiPut({b:y, d:x})
Result after transaction:
{b:y, d:x}
Step 4
State: {b:y}
State: {d:x}
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
Result after transaction:
{b:y, d:x}
Step 5
CommitOK()
CommitOK()
State: {d:x}
State: {b:y}
R2
R1
R3
Client
keys={a}
keys={b,c}
keys={d,e}
Coordinator responds with appropriate response
Reply(SwapOk)
State: {b:x}
State: {d:y}
Step 6
Transaction Success and Failure
Transaction Failures
Preserving Transaction Atomicity within Configurations
How is Transaction atomicity maintained within Configurations?
All this is in the spec:
Two-Phase Commit (One Approach)
Goal: Allows all participants to arrive at same conclusion.
Important Design Tips
Transactions and Configurations
Should transactions happen atomically in one configuration, or are they allowed to span multiple configurations?
The Messy Cases
The Messy Cases
Safe to ignore messages with outdated config???
R2
R1
R3
keys={a} config = 2
keys={b,c}
Config = 3
keys={d,e}
R3 in reconfig, receives a Prepare Request from R1
State: {b:x}
State: {d:y}
Prepare, config = 2
keys={a} config = 3
PrepareNotOk, config = 3
Deadlocked? Abort!
The Danger Zone - Pitfalls
Tips
Coordinator-as-a-Leader Designs
Deadlock or cyclic waiting: the problem
G1
G2
G3
G4
keys={k1}
keys={k2}
keys={k3}
keys={k4}
Write(k4, k2, k1)
Write(k3, k2, k1)
Deadlock solution: abort (the 2PC way)
Deadlock solution: lock ordering (the 332 and 451 way)
Aborts
Potential workflow for part 3
Tackling the entire two-phase commit process at once can be difficult, so one suggestion of what order to get things done is
Note: Sending to everyone (involved) would require getting AbortOks from everyone (involved) if an abort happens
Note: 3. is the bulk of the work because you need these messages and also timers to retry as necessary (for Prepares, Commits, Aborts) [can delay timers until unreliable tests]
What are the two roles a group can have in the 2PC protocol?
What are the two roles a group can have in the 2PC protocol?
Coordinator or Participant
How does each type of server learn that a transaction succeeded/failed?
How does each type of server learn that a transaction succeeded/failed?
What should the coordinator and participants do in the case of a failed transaction?
What should the coordinator and participants do in the case of a failed transaction?
Should transactions happen entirely in one configuration, or are they allowed to span multiple configurations?
Should transactions happen entirely in one configuration, or are they allowed to span multiple configurations?
One configuration!
How do we ensure a transaction completes entirely in one configuration?
How do we ensure a transaction completes entirely in one configuration?
Participants reject prepare requests from other configurations
What should the coordinator do when it receives a new configuration during a transaction?
What should the coordinator do when it receives a new configuration during a transaction?
Delay reconfiguration until outstanding transactions are completed
What should the coordinator do when it discovers a participant isn’t in the same configuration?
How can we differentiate the same transaction occurring across multiple configurations? (transactions may need to be retried if we terminate it due to configuration mismatch).
Suppose we are a participant that just underwent reconfiguration, can we safely ignore transaction messages from an outdated configuration?
Suppose we are a participant that just underwent reconfiguration, can we safely ignore transaction messages from an outdated configuration?
No, should reply prepareNotOK–this transaction may be blocking coordinator’s reconfiguration