@startuml skinparam defaultTextAlignment center skinparam shadowing false skinparam sequence { MessageAlign center ParticipantBackgroundColor Orange ParticipantBorderThickness 1 } participant "node 1\nnode id: A" as A participant "node 2\n(Target)\nnode id: B" as B participant "node 3\n(Source)\nnode id: C" as C participant "node 4\nnode id: D" as D note over A Role: **Master** ConfigEpoch: **2** CurrentEpoch: **2** Owner of slot 1200: C C's configEpoch is 0 end note / note over B Role: **Master** ConfigEpoch: **1** CurrentEpoch: **2** Owner of slot 1200: C C's configEpoch is 0 end note / note over C Role: **Master** ConfigEpoch: **0** CurrentEpoch: **2** Owner of slot 1200: C end note C <- : migrateslots 1200 C -> B: Transfer data for slot 1200 C -> B: End of data transfer B -> B: Bumping epoch and starting to own slot 1200 note over B Role: **Master** ConfigEpoch: **3** CurrentEpoch: **3** Owner of slot 1200: B C's configEpoch is 0 end note B --> C: PING C -> C: Purge 1200 note over C Role: **Master** ConfigEpoch: **0** CurrentEpoch: **3** Owner of slot 1200: B end note == Scale out by adding shard == D <-: Start redis note over D Role: **Master** ConfigEpoch: **0** CurrentEpoch: **0** end note D <-: CLUSTER MEET D -> C: MEET C -> C: Resolve configEpoch collision note over C Role: **Master** ConfigEpoch: **4** CurrentEpoch: **4** Owner of slot 1200: B end note C --> D: PONG note over D Role: **Master** ConfigEpoch: **0** CurrentEpoch: **4** end note C -> A: PING (My configEpoch is 4) note over A Role: **Master** ConfigEpoch: **2** CurrentEpoch: **4** Owner of slot 1200: C (**owner is updated only** **when someone claims to own it**) C's configEpoch is 4 end note A --> C: PONG B -> A: CLUSTER PING\n(My configEpoch is 3, I own 1200) A --> B: UPDATE\n(C has higher configEpoch and owns 1200) B -> B: Purge 1200 note over B Role: **Master** ConfigEpoch: **3** CurrentEpoch: **4** Owner of slot 1200: C C's configEpoch is 4 end note == No node owns slot 1200 == @enduml