Configuration du projet
À partir d'un projet SpringBoot 2.2.1.RELEASE, ajoutez la dépendance Redis dans votre pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Configurez ensuite la connexion dans application.yml :
spring:
redis:
host: 127.0.0.1
port: 6379
password:
Commandes fondamentales des Bitmaps
Les Bitmaps Redis s'appuient sur trois commandes principales : setbit, getbit et bitcount.
Définition d'un bit
La commande setbit permet d'attribuer la valeur 0 ou 1 à un offset donné au sein d'une clé. En SpringBoot, voici deux approches possibles :
@Autowired
private StringRedisTemplate redisTemplate;
public boolean setFlag(String cacheKey, long position, boolean value) {
return redisTemplate.opsForValue().setBit(cacheKey, position, value);
}
public boolean setFlagAlternative(String cacheKey, long position, boolean value) {
return redisTemplate.execute((RedisCallback<Boolean>) conn ->
conn.setBit(cacheKey.getBytes(), position, value)
);
}
La différence réside dans la sérialisation de la clé : la première méthode utilise le sérialiseur configuré sur le template, tandis que la seconde convertit directement la clé en tableau d'octets.
Vérification d'un bit
La commande getbit retourne la valeur du bit à une position donnée :
public boolean hasFlag(String cacheKey, long position) {
return redisTemplate.opsForValue().getBit(cacheKey, position);
}
Décompte des bits à 1
La commande bitcount compte le nombre de bits positionnés à 1 :
public long countBits(String cacheKey) {
return redisTemplate.execute((RedisCallback<Long>) conn ->
conn.bitCount(cacheKey.getBytes())
);
}
Cas d'usage concrets
Calcul des utilisateurs actifs quotidiens (DAU)
Le suivi des utilisateurs actifs par jour est un besoin fréquent. Avec une structure Hash, on associerait chaque userId à un champ de la clé du jour. Cependant, pour des volumes de l'ordre de plusieurs millions d'utilisateurs, l'empreinte mémoire devient considérable.
Avec un Bitmap, l'approche consiste à utiliser l'userId comme offset :
setbit app_2020_10_13 userId 1à chaque visitebitcount app_2020_10_13pour obtenir le total
Cette méthode est particulièrement efficace lorsque les identifiants utilisateurs sont continus et que le volume est élevé. En revanche, si les userId sont très dispersés (de 1 à plusieurs milliards avec peu d'actifs réels), le Bitmap génère un gaspillage mémoire significatif.
Déduplication de likes
Pour un système de likes où un utilisateur ne peut voter qu'une fois par article, le Bitmap offre une solution élégante :
- Clé Redis :
like_article_1121 - Vérification préalable :
getbit like_article_1121 userId - Enregistrement :
setbit like_article_1121 userId 1
La vérification du bit avant l'action permet de bloquer immédiatement tout doublon.
Filtre de Bloom
Le filtre de Bloom est une structure probabiliste construite sur un Bitmap. Son fonctionnement repose sur plusieurs fonctions de hachage :
- L'élément entrant passe par n fonctions de hachage produisant n valeurs
- Chaque valeur est mappée sur le Bitmap et le bit correspondant est mis à 1
- Lors d'une vérification, si tous les bits associés sont à 1, l'élément est « possiblement présent » ; si au moins un bit est à 0, l'élément est « certainement absent »
Cette propriété — certitude d'absence, incertitude de présence — rend le filtre de Bloom idéal pour résoudre les problèmes de cache穿透 (cache penetration) ou la déduplication d'URLs en crawling.
Redis propose le filtre de Bloom via un module pour les versions ≥ 4.0. Installation via Docker :
docker run -p 6379:6379 --name redis-bloom redislabs/rebloom:latest
Utilisation en ligne de commande :
127.0.0.1:6379> bf.add monFiltre element1
(integer) 1
127.0.0.1:6379> bf.exists monFiltre element1
(integer) 1
127.0.0.1:6379> bf.exists monFiltre elementInconnu
(integer) 0
Le filtre de Bloom ne supporte que l'ajout (bf.add) et la vérification (bf.exists). Il n'existe pas d'opération de suppression native.
Synthèse
Le Bitmap Redis, implémenté au-dessus de la structure String, s'avère particulièrement pertinent dans les scénarios à fort volume avec des identifiants continus. Les trois commandes essentielles — setbit, getbit, bitcount — couvrent l'essentiel des besoins de marquage, vérification et décompte. Pour les calculs de DAU à très grande échelle, HyperLogLog peut toutefios constituer une alternative plus économique en mémoire.