Redis Keyspace Notifications with Docker
Published: 2023-12-16 08:45:16

**Redis Keyspace Notifications** is a pub-sub mechanism in **Redis** that allows us to track and listen to changes occurring within Redis.

While reading about this topic from various sources, I saw the installation and usage on **Windows**, but I couldn't find information on using it with **Docker**. Therefore, in this article, I wanted to address this aspect.

Some sources that I have read;

- [Source 1](https://redis.io/docs/manual/keyspace-notifications/)
- [Source 2](https://borakasmer.medium.com/redis-keyspace-notifications-on-c-988014f0d62c)
- [Source 3](https://dev.to/sayganov/redis-keyspace-notifications-with-a-c-example-2ahp)

First, let's proceed with the Docker installation.

We can run docker-compose file you can see below.

```yaml
version: '3.4'

services:
  redis:
    container_name: redis
    tty: true
    command: sh -cx "redis-server --daemonize yes && redis-cli config set notify-keyspace-events KEA && sleep infinity"
    image: redis
    ports:
      - 6379:6379
    volumes:
      - /opt/app_data/redis/:/data
  
  redisInsight:
    image: 'redislabs/redisinsight:latest'
    ports:
      - 8001:8001
```

If we will explain the key points of the above **YAML**file for us:

We are running two separate containers. One is for the management panel (**Redis Insight**), and the other is for the Redis server (**Redis**).

The crucial part is the '**command**' section.

The command consists of three parts;

- **redis-server**
Initiates the Redis server. With the '**daemonize**' option, Redis detaches itself from the terminal, allowing it to continue running in the background.

- **redis-cli config set notify-keyspace-events KEA**
Using the '**redis-cli**' terminal program, we can send commands to the **Redis**server and read the responses. With the remaining part, we can specify which events to track in Redis.

- We use the '**sleep**' command to keep the container active even if the Redis terminal is closed. With the '**infinity**' option, we indicate that we want to maintain this state indefinitely. Alternatively, the '**tail**' command can be used to view log files. The '**-f /dev/null**' option is often used for real-time viewing, keeping the container continuously running.

We can proceed with the question of what '**KEA**' means in the above command.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m270gf3ilcds353tvb3g.png)

The '**notify-keyspace-events**' we set above is initially disabled by default. To activate it, we can use the characters shown in the image above. With these characters, we can decide which events to log.

The '**KEA**' used above activates all of them.

Now, we can implement it within the **.NET Console App** as follows:

After creating our application, we can install the **_StackExchange.Redis_** package.

Then, we can proceed with the usage using the following code block:

```cs
using StackExchange.Redis;

var configurationOptions = new ConfigurationOptions
{
    EndPoints =
    {
        "localhost:6379"
    }
};

var connectionMultiplexer = await ConnectionMultiplexer.ConnectAsync(configurationOptions);
var subscriber = connectionMultiplexer.GetSubscriber();

await subscriber.SubscribeAsync("__keyspace@0__:*", (channel, type) =>
{
    var key = GetKey(channel);

    switch (type)
    {
        case "set":
            Console.WriteLine($"Set: {key}");
            break;
        case "expire":
            Console.WriteLine($"Expire: {key}");
            break;
        case "expired":
            Console.WriteLine($"Expired: {key}");
            break;
    }
});

static string GetKey(string channel)
{
    var index = channel.IndexOf(':');

    if (index >= 0 && index < channel.Length - 1)
    {
        return channel[(index + 1)..];
    }

    return channel;
}

Console.ReadLine();
```

The above code block will continuously maintain the monitoring process. To conclude the monitoring and disconnect from **Redis**, we can use the following code block.


```cs
await subscriber.UnsubscribeAllAsync();
await connectionMultiplexer.DisposeAsync();
```

Now, if we run this code block;

First, let's apply the 'set' command.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/loealik7hvp6ygglgk10.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8cjnr0gawhys07r81cd9.png)

As seen above, we obtained the key information for the '**set**' operation.

If we apply the '**expire**' command;

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9yux5kt261xt9nkofd7l.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dz45rxnk4tlzkngusy1k.png)

This way, we set up the monitoring mechanism for all events using the '**KEA**' characters. However, scenarios can vary in this context.




As seen above, we obtained the key information for the '**expire**' operation.