andrewlee302 / mit-6.824 Goto Github PK
View Code? Open in Web Editor NEWImplementation of MIT 6.824: Distributed Systems
Implementation of MIT 6.824: Distributed Systems
In such case with one client emits several concurrent put/append requests to P/B (S1/S2). Primary and backup do check whether the uuid of the request has been processed locally.
The basic logics are as follows:
// Client
for {
ok := RPC(primary, op)
if ok {
return
} else {
update(&primary)
}
}
// Primay
mutex.Lock()
defer mutex.Unlock()
if op.uuid existed in seen {
return value
} else {
ok := B.Remote(op)
if ok {
Local(op)
seen[op.uuid] = true
} else {
return err
}
}
// Backup
mutex.Lock()
defer mutex.Unlock()
if op.uuid existed in seen {
return value
} else {
Local(op)
}
action | status after action |
---|---|
req1 S2 succ reply fail | S1<1,nil> S2<1,54> |
req2 S2 succ | S1<1,nil> S2<1,53> |
req2 S1 succ | S1<1,53> S2<1,53> |
req1 S2 No Action | S1<1,53> S2<1,53> |
req1 S1 <1,54> | S1<1,54> S2<1,53> |
action | status after action |
---|---|
req1 S2 succ reply fail | S1<1, nil> S2<1, x> |
req2 S2 succ | S1<1, nil> S2<1, xy> |
req2 S1 succ | S1<1, y> S2<1, xy> |
req1 S2 No Action | S1<1, y> S2<1, xy> |
req1 S1 <1,54> | S1<1, yx> S2<1, xy> |
So primary and backup do have different values of Key 1 at the end in two cases. If primary gets down and the backup is promoted to the primary, then the GET requests in the two times have different values. The root cause is that a PUT/APPEND op in P/B is not binding together. So the adjacent retrying executions may be interrupted by another PUT/APPEND op.
seen
map, for filtering duplication request if being promoted to primary.action | translate action | status after action |
---|---|---|
req1 S2 succ reply fail | Put<1, x> | S1<1, nil> S2<1, x> |
req2 S2 succ | Put<1, y> | S1<1, nil> S2<1, y> |
req2 S1 succ | Put<1, y> | S1<1, y> S2<1, y> |
req1 S2 succ reply succ | Put<1, yx> | S1<1, y> S2<1, yx> |
req1 S1 <1,54> | Put<1, yx> | S1<1, yx> S2<1, yx> |
// Client
for {
ok := RPC(primary, op)
if ok {
return
} else {
update(&primary)
}
}
// Primay
seen map[string]bool
versions map[string]int64
last_dataset map[string]{Seq:int64,Value:string}
PutAppend (op) {
mutex.Lock()
defer mutex.Unlock()
if op.uuid existed in seen {
return value
}
version := versions[op.key]
if backupHost != "" {
var reply FrowardReply
ok := B.Remote(op, version, &reply)
if ok {
versions[key] = reply.version
last_dataset[key] = dataset[key]
Local(op)
seen[op.uuid] = true
} else {
return err
}
} else {
versions[key] = version + 1
last_dataset[key] = dataset[key]
Local(op)
seen[op.uuid] = true
}
}
}
// Backup
seen map[string]bool
versions map[string]int64
last_dataset map[string]{Seq:int64,Value:string}
BackupOp (op, version) {
mutex.Lock()
defer mutex.Unlock()
backup_version := versions[key]
// assert(backup_version == version or backup_version == version + 1)
if version == 0 {
// reset to null value
dataset[key] = ""
} else if backup_version = version + 1 {
dataset[key] = last_dataset[key]
}
last_dataset[key] = dataset[key]
versions[key] = version + 1
LocalOp(op)
seen[op.uuid] = true
}
If the primary is down and the backup will be promoted to the primary, then the previous failed request with the reply failure have no access to the new primary (as backup previously), because it has been tagged with being processed. So we can delete the tag if we found the value is overridden in the backup. The new version of Backup part is as follows.
// Backup
seen map[string]bool
versions map[string]int64
last_dataset map[string]{Seq:int64,Value:string}
BackupOp (op, version) {
mutex.Lock()
defer mutex.Unlock()
backup_version := versions[key]
// assert(backup_version == version or backup_version == version + 1)
if version == 0 {
// reset to null value
dataset[key] = ""
} else if backup_version = version + 1 {
wait_ack_uuid_set.add(last_procede_uuid[key])
dataset[key] = last_dataset[key].Value
delete(seen, last_dataset[key].Seq)
}
last_dataset[key] = {Seq:op.uuid, Value:dataset[key]}
versions[key] = version + 1
LocalOp(op)
seen[op.uuid] = true
}
It also has bugs. We should notice that if connection P->B is interrupted but the Backup receive the rpc request, it doesn't mean Primary observe the error after the ending of the rpc call. Primary could get the error info at the moment the net.UnixConn.File() is closed by syscall.Shutdown(). So the rpc call itself will be executed at the random moment. Then the old rpc request in the backup will be done after the normal request, consequently incurring the normal value is override by the old one.
The assumption that p/b won't crash is kept in the discussion below.
Consider the local op in primary won't be executed until get the OK from the remote op in the backup. If GET op can be executed in the backup side, then it will occur that a PUT/APPEND op has modified in the backup side, and the RPC reply failure will induce the inconsistency between P/B. So the results of GET op from two sides are different temporarily, which doesn't satisfy the strong consistency. But the eventually consistent can be satisfied at all.
If we want to implement the strong consistency, maybe we need keep more information and more operations, such write cache and commit operation.
How to do practically?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.