Featured image of post Solution for Low Version Redis bitcount Offset Parameter Not Being Bits

Solution for Low Version Redis bitcount Offset Parameter Not Being Bits

  • Recently, we needed to implement a “check-in for N days to receive gifts” feature in a project. This naturally led us to consider using Redis' bitmap for implementation.
  • Check-in can be done with setbit {key} {offset} 1
  • Cumulative check-in days can be retrieved using bitcount {key} {start} {end}

index.md

  • Initially, we implemented it like this:
# Base date example: 2023-09-12, offset 0 for this day
setbit users:id 0 1
# Binary: 10000000
# Next day, 2023-09-13, offset 1
setbit users:id 1 1
# Binary: 11000000
# Retrieving check-in days from 2023-09-12 to 2023-09-20:
bitcount users:id 0 8
# Output: 2. However, testers reported issues when querying 2023-09-13 to 2023-09-20:
bitcount users:id 1 7
# Output: 0. The command actually checks bits 9-16 (bytes 1-7), which are all 0s.
  • We mistakenly assumed start and end were bit positions, but Redis versions <7.0 treat them as byte indexes.

Workaround for Older Redis Versions

  • Multiply the offset by 8 to avoid overlapping bits within the same byte. Although this consumes 8x more space, it simplifies the logic.
setbit {key} {offset*8} 1
bitcount {key} {start} {end}

Solution for Redis ≥7.0

  • Use the BIT parameter to specify bit-level ranges directly:
bitcount {key} {start} {end} BIT