Backend Development 12 min read

Implementing Sign‑in and Statistics with Redis BitMap in Spring Boot

This article explains how to use Redis BitMap to build an efficient sign‑in feature and continuous‑sign‑in statistics in a Spring Boot microservice, covering basic BitMap commands, integration steps, core source code, and a cache‑penetration solution using BitMap hashing.

Top Architect
Top Architect
Top Architect
Implementing Sign‑in and Statistics with Redis BitMap in Spring Boot

In many projects a sign‑in and statistics feature is needed; using Redis BitMap can store user sign‑in data with minimal memory. The article first introduces the basic Redis BitMap syntax and commands such as SETBIT , GETBIT , BITCOUNT , BITFIELD , BITOP , and BITPOS .

It then shows how to integrate Redis BitMap into a Spring Boot application. The Redis server version used is 6.2, and the following commands are demonstrated with screenshots: creating a key, setting bits, getting bits, using BITFIELD for unsigned queries, and locating the first 0/1 with BITPOS .

Core source code for the sign‑in API is provided:

@PostMapping("sign")
public Result sign() {
    return userService.sign();
}

The service implementation obtains the logged‑in user ID, builds a key based on year and month, determines the day of month, and writes a 1 to the corresponding bit:

public Result sign() {
    Long userId = UserHolder.getUser().getId();
    LocalDateTime now = LocalDateTime.now();
    String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
    String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
    int dayOfMonth = now.getDayOfMonth();
    stringRedisTemplate.opsForValue().setBit(key, dayOfMonth - 1, true);
    return Result.ok();
}

For statistics, the article explains how to calculate continuous sign‑in days by retrieving the month’s BitMap as a decimal number with BITFIELD and iterating bit‑by‑bit using bitwise operations:

public Result signCount() {
    Long userId = UserHolder.getUser().getId();
    LocalDateTime now = LocalDateTime.now();
    String keySuffix = now.format(DateTimeFormatter.ofPattern(":yyyyMM"));
    String key = RedisConstants.USER_SIGN_KEY + userId + keySuffix;
    int dayOfMonth = now.getDayOfMonth();
    List
result = stringRedisTemplate.opsForValue().bitField(
        key,
        BitFieldSubCommands.create()
            .get(BitFieldSubCommands.BitFieldType.unsigned(dayOfMonth)).valueAt(0));
    if (result == null || result.isEmpty() || result.get(0) == null) {
        return Result.ok(0);
    }
    long num = result.get(0);
    int count = 0;
    while (true) {
        if ((num & 1) == 0) {
            break;
        } else {
            count++;
        }
        num >>>= 1;
    }
    return Result.ok(count);
}

The article also discusses using BitMap to mitigate cache‑penetration attacks by hashing large ID spaces into a bitmap, reducing memory compared to storing IDs in a list, and notes the importance of handling false‑positive rates.

Finally, a brief summary emphasizes that Redis BitMap provides a lightweight, high‑performance solution for sign‑in and statistical features in microservices, improving user engagement while keeping memory usage low.

BackendCacheRedisBitmapSpringBootSign-in
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.