Skip to content

Commit

Permalink
Add support for receiving PSYNC command from replica
Browse files Browse the repository at this point in the history
  • Loading branch information
rohitpaulk committed Feb 1, 2024
1 parent e3f6c40 commit d93c7ac
Showing 1 changed file with 38 additions and 32 deletions.
70 changes: 38 additions & 32 deletions course-definition.yml
Original file line number Diff line number Diff line change
Expand Up @@ -919,52 +919,58 @@ stages:
name: "Receive handshake (2/3)"
difficulty: easy
description_md: |
When replicas connect to masters, they use the `PSYNC` command to send their old master replication ID and the offsets they processed so far. This way the master can send just the incremental part needed. However if there is not enough backlog in the master buffers, or if the replica is referring to an history (replication ID) which is no longer known, then a full resynchronization happens: in this case the replica will get a full copy of the dataset, from scratch.
In this stage, you'll add support for receiving the `PSYNC` command from the replica.
In this stage you'll add support for the [PSYNC](https://redis.io/commands/psync/) command on the Master redis server.
You will receive the `PSYNC` command with `?` and `-1` arguments. (Which correspond to a Nil replication ID because the replica just started, and a 0 offset)
The master would then need to do a fullsync, because based on the ID and offset, it will not be possible to send the incremental changes required.
So, the Master will return `FULLRESYNC <REPL_ID> 0`
### Handshake (continued from previous stage)
The client will send you the PSYNC command as a RESP array, which looks something like this :
As a recap, there are three parts to the handshake:
```
*3,$5,PSYNC,$1,?,$2,-1,
```
- The master receives a `PING` from the replica (Previous stages)
- The master receives `REPLCONF` twice from the replica (Previous stage)
- The master receives `PSYNC` from the replica (**This stage**)
### Tests
In this stage, you'll add support for receiving the `PSYNC` command from the replica.
The tester will execute your program like this:
The replica will send you the `PSYNC` command with two arguments:
```
./spawn_redis_server.sh --port <PORT>
```
- The first argument is `?`
- This is replication ID of the master, it is `?` because this is the first time the replica is connecting to the master.
- The second argument is `-1`
- This is the replication offset, it is `-1` because this is the first time the replica is connecting to the master.
It'll then send the `PING`, expecting a `PONG` back.
The final command you receive will look something like this:
```bash
$ redis-cli ping
```
*3\r\n$5\r\nPSYNC\r\n$1\r\n?\r\n$2\r\n-1\r\n
```
It'll then send the `REPLCONF` command with listening-port and <PORT> as arguments.
(That's `["PSYNC", "?", "-1"]` encoded as a RESP Array)
```bash
$ redis-cli replconf listening-port <PORT>
```
The master will respond with `+FULLRESYNC <REPL_ID> 0\r\n` ("FULLRESYNC <REPL_ID> 0" encoded as a RESP Simple String).
It'll expect to receive `OK` back. The command should be sent as a simple string, like this :
`+OK\r\n`
- `FULLRESYNC` means that the master cannot perform incremental replication with the replica, and will thus start a "full" resynchronization.
- `<REPL_ID>` is the replication ID of the master. You've already set this in the "Replication ID & Offset" stage.
- As an example, you can hardcode `8371b4fb1155b71f4a04d3e1bc3e18c4a990aeeb` as the replication ID.
- `0` is the replication offset of the master. You've already set this in the "Replication ID & Offset" stage.
It'll then send the `PSYNC` command with ? and -1 as arguments.
### Tests
```bash
$ redis-cli psync ? -1
The tester will execute your program like this:
```
./spawn_redis_server.sh --port <PORT>
```
It'll expect to receive `FULLRESYNC <REPL_ID> 0` back. The command should be sent as a simple string, like this :
`+FULLRESYNC <ID> 0\r\n`
Note : The ID will not be checked, you can send your master's replication ID.
It'll then send the following commands:
1. `PING` (expecting `+PONG\r\n` back)
2. `REPLCONF listening-port <PORT>` (expecting `+OK\r\n` back)
3. `REPLCONF capa eof capa psync2` (expecting `+OK\r\n` back)
4. `PSYNC ? -1` (expecting `+FULLRESYNC <REPL_ID> 0\r\n` back)
**Notes**:
- In the response, `<REPL_ID>` needs to be replaced with the replication ID of the master which you've initialized in previous stages.
marketing_md: |
In this stage, you'll add support for accepting PSYNC, and starting a FULLRESYNC.
Expand Down Expand Up @@ -1072,7 +1078,7 @@ stages:
Subsequently it will expect a RDB file sent to it from the master.
It'll then send write commands to the master, from another client.
It'll then send write commands to the master, from another client.
```bash
$ redis-cli SET foo 1
Expand Down Expand Up @@ -1111,7 +1117,7 @@ stages:
$ redis-cli SET myKey "Hello"
```
It'll then expect the commands to be propagated to the replica, and the replica to parse them, and apply them against its DB.
It'll then expect the commands to be propagated to the replica, and the replica to parse them, and apply them against its DB.
It will send `GET` requests to the replica from another client.
```bash
Expand Down Expand Up @@ -1150,7 +1156,7 @@ stages:
$ redis-cli SET mykey "Hello"
```
It'll then expect the commands to be propagated to all the replicas, and the replicas to parse them, and apply them against its DB.
It'll then expect the commands to be propagated to all the replicas, and the replicas to parse them, and apply them against its DB.
It will send `GET` requests to the replicas from another client.
```bash
Expand Down

0 comments on commit d93c7ac

Please sign in to comment.