Usando Bloom Filter no Redis (RedisBloom)
Tags: programming, redis, dotnet, dotnetcore
Published: 2023-03-03 12:52:24

O Bloom Filter é uma estrutura de dados probabilística criada por Burton Howard Bloom em 1970, que se mostra muito útil em situações onde é necessário armazenar um grande volume de dados, como CPFs e IPs bloqueados por fraude. Em vez de acessar a base de dados para realizar uma consulta e saber se uma determinada chave existe ou não na tabela, o Bloom Filter permite que se faça essa verificação de forma mais rápida e eficiente, diminuindo o tempo de resposta da operação. Para saber mais leia o ótimo artigo do [Márcio Althmann](https://medium.com/@marcioalthmann/bloom-filters-8dde17bc7ee6).

Ao armazenar informações diretamente no Redis usando uma chave como CPF_BLOQUEIO_{numero do cpf}, a operação pode até ser mais rápida do que a resposta do banco de dados, mas o volume de dados armazenados será grande. Com o Bloom Filter, é possível armazenar gigabytes de dados em megabytes, o que o torna uma excelente opção para otimizar o armazenamento de grandes volumes de dados. O Redis disponibiliza essa estrutura para nós através do RedisBloom.

Para utilizar o Bloom Filter no Redis, é necessário ter uma versão específica do Redis, como a imagem redis/redis-stack-server que pode ser encontrada no Docker Hub. Após obter essa imagem, podemos utilizar a biblioteca do StackExchange.Redis para trabalhar com o Bloom Filter.

O Bloom Filter no Redis pode ser utilizado de duas formas. A primeira é reservando o espaço necessário utilizando o comando BF.RESERVE, que permite especificar com antecedência a quantidade de dados que o Bloom Filter pode esperar e a taxa de erro desejada para esses dados, ou seja, o número de falsos positivos que ele pode relatar. Dessa forma, o Redis já sabe como configurar o Bloom Filter adequadamente.

No entanto, caso você não queira especificar esses valores com antecedência, não é necessário reservar espaço no Redis. Isso porque qualquer chamada ao comando BF.ADD para uma chave inexistente criará automaticamente um Bloom Filter para você. Essa abordagem é útil caso você não saiba com precisão qual será a quantidade de dados ou taxa de erro necessária para o seu Bloom Filter.

Criando um Bloom Filter:

```csharp
using StackExchange.Redis;

var connection = ConnectionMultiplexer.Connect("localhost:6379");
var database = connection.GetDatabase();

// Criando um filtro
await database.ExecuteAsync("BF.RESERVE", "bf_cpf", .01, 10000);
```

Para adicionar um elemento à lista, basta chamar o comando BF.ADD passando a chave criada no momento da reserva e o elemento que se deseja adicionar. O Redis irá realizar o hash do elemento e adicioná-lo ao Bloom Filter de forma otimizada.

É importante lembrar que o Bloom Filter não permite a exclusão de elementos.

Adicionando um elemento ao Bloom Filter:

```csharp
// Adicionando um item na lista
await database.ExecuteAsync("BF.ADD", "bf_cpf", "00000000001");
```

Para verificar se um elemento está presente na lista do Bloom Filter, utilizamos o comando BF.EXISTS, que recebe como parâmetros o nome da chave e o elemento que se deseja verificar a existência.

Ao executar o comando, o Redis realizará novamente o hash do elemento e verificará se os bits correspondentes estão definidos no filtro. Se todos os bits correspondentes estiverem definidos, o comando retornará true, indicando que o elemento provavelmente está na lista. Caso contrário, o comando retornará false, indicando que o elemento definitivamente não está na lista. É importante lembrar que pode haver falsos positivos, já que a probabilidade de colisões no Bloom Filter é maior do que em outras estruturas de dados.

Verificando a existência de um elemento:

```csharp
// Verificando se o item está na lista
var existe = await database.ExecuteAsync("BF.EXISTS", "bf_cpf", "00000000001");
```

O Bloom Filter é uma ferramenta valiosa para lidar com grandes volumes de dados de forma eficiente e otimizar o desempenho das operações. Além disso, o RedisBloom, que é uma lista distribuída baseada na estrutura do Redis, proporciona escalabilidade e alta disponibilidade para os dados armazenados. Sendo possível utilizar recursos de distribuição e replicação do Redis para garantir a disponibilidade dos dados em casos de falhas ou sobrecarga de tráfego, o que torna a solução mais robusta e confiável.

Até a próxima!

Referências:
[Using RedisBloom with .NET](https://developer.redis.com/howtos/redisbloom/with-dotnet/redisbloom-withdotnet)