Implementing Sign‑In and Statistics with Redis BitMap in Spring Boot
This article explains how to use Redis BitMap to build a memory‑efficient sign‑in feature and continuous‑sign‑in statistics in a Spring Boot microservice, covering basic BitMap commands, key design, core Java code, testing steps, and a bitmap‑based solution for cache‑penetration protection.
1. Redis BitMap Basic Usage
Sign‑in data can be stored efficiently using Redis BitMap where each bit represents a user's daily sign‑in status, reducing memory consumption from dozens of bytes per record to just a few bits.
BitMap Commands
SETBIT : set a bit at a given offset to 0 or 1.
GETBIT : retrieve the bit value at a given offset.
BITCOUNT : count bits set to 1.
BITFIELD : query or modify arbitrary bit fields.
BITFIELD_RO : read bit fields in decimal.
BITOP : perform bitwise operations on multiple bitmaps.
BITPOS : find the first occurrence of 0 or 1 in a range.
Examples of using these commands are shown with screenshots of Redis CLI output.
2. Spring Boot Integration for Sign‑In
Requirement
Implement an API that records the current user's daily sign‑in status in Redis using a BitMap key composed of the user ID and the year‑month.
Core Source Code
UserController
@PostMapping("sign")
public Result sign() {
return userService.sign();
}UserServiceImpl
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();
}Testing is performed with ApiFox and Redis data is verified via screenshots.
3. Sign‑In Statistics (Continuous Days)
Problem 1: What is a continuous sign‑in count?
Starting from the latest sign‑in, count backwards until the first day without a sign‑in; the number of consecutive 1 bits equals the continuous days.
Problem 2: Retrieve all sign‑in bits for the current month
BITFIELD key GET u[dayOfMonth] 0This returns a decimal number representing the first dayOfMonth bits; counting the 1s yields total sign‑ins.
Problem 3: Traverse bits from right to left
Apply bitwise AND with 1 to check the least‑significant bit, then right‑shift the number (>>>) repeatedly until a 0 is encountered.
Implementation:
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);
}Testing confirms correct continuous‑day calculation.
4. Using BitMap to Mitigate Cache Penetration
Cache penetration occurs when requests query non‑existent keys, hitting the database each time. By hashing IDs into a large BitMap, a missing ID maps to a 0 bit, allowing the system to quickly reject invalid requests without DB access. The trade‑off is a false‑positive rate due to hash collisions.
Conclusion
The guide demonstrates a practical, memory‑efficient solution for daily sign‑in tracking and statistics using Redis BitMap within a Spring Boot microservice, and shows how the same technique can help prevent cache‑penetration attacks.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.