A Redis bitmap is an array of bits, each of which has a corresponding offset (starting at 0) that can operate on one or more bits specified in the bitmap.

In fact, bitmaps are not a new data type provided by Redis, but an extension of the string type. So bitmap commands can be used directly on string keys, and keys operated by bitmap commands can be operated by string commands.

For example, we have a string key foo:

redis> set foo bar
Copy the code

A byte consists of eight bits, so the binary form of the foo key is:

SETBIT

Using the SETBIT command, you can specify the value of the binary bit on the offset of the bitmap. Offset must be greater than or equal to 0, and value must be 0 or 1. The time complexity of this command is O(1).

SETBIT key offset value

The SETBIT command, after setting the bits, returns as a result the old value before the bits were set.

Suppose you now want to turn a BAR into an AAR in two steps:

redis> setbit foo 6 0
(integer) 1
redis> setbit foo 7 1
(integer) 0
redis> get foo
"aar"
Copy the code

When using the SETBIT command to try to set a bitmap, if the bitmap does not exist, or if the bitmap’s current size is not sufficient, Redis will extend the bitmap set and initialize all unset bits to 0. Such as:

redis> setbit far 10 1
Copy the code

Since FAR does not exist, Redis will set the binary bits from 0 to 9 to 0. Because Redis expands the bitmap in bytes, there are actually 16 binary bits in FAR, not 10, and the binary bits from 11 to 15 are also 0.

In this case, when the specified binary offset is too large, Redis needs to allocate all the memory at once, which can cause the Redis server to block. For example, 1 indicates male and 0 indicates female. ID is used as the binary offset. If the ID starts from 10000000001, you need to subtract 10000000000 from the user ID before storing the data.

GETBIT

Use the GETBIT command to get the value of the bits at the bitmap’s specified offset. The time complexity of this command is O(1).

GETBIT key offset

If the input offset exceeds the maximum offset the bitmap currently has, 0 is returned as the result.

BITCOUNT

You can use the BITCOUNT command to count the number of bits in the bitmap whose value is 1. The time complexity of this command is O(n).

BITCOUNT key [start end]

By default, the BITCOUNT command counts binary bits in all bytes contained in the bitmap, or it is possible to make BITCOUNT count only binary bits (not binary offsets) in the specified byte range with the optional start and end arguments. For example, if you want to count the number of binary 1 in two bytes of AR:

redis> bitcount foo 1 2
(integer7)Copy the code

The start and end arguments also support the use of negative indexes, with the lower usage equivalent to the upper:

redis> bitcount foo -2 -1
(integer7)Copy the code

BITPOS

By executing the BITPOS command, the bitmap looks for the first bit set to the specified value and returns the offset of this bit.

BITPOS key value [start end]

BITPOS also accepts optional start and end arguments, allowing the BITPOS command to look only in binary bits within the specified byte range.

redis> get foo
"aar"
redis> bitpos foo 1
(integer) 1
redis> bitpos foo 0
(integer) 0
redis> bitpos foo 0 1 2
(integer) 8
redis> bitpos foo 1 1 2
(integer) 9
redis> bitpos foo 1 -1 -1
(integer17)Copy the code

Processing for boundary:

  • When you try to find a binary bit of value 1 in a bitmap that does not exist or in a bitmap where all bits are set to 0, the BITPOS command returns -1 as the result.
  • If you look for a binary bit with a value of 0 in a bitmap where all bits are set to 1, the BITPOS command returns the maximum offset of the bitmap plus 1 as the result

BITOP

To perform a specified bit operation on one or more bitmaps with the BITOP command and store the result of the operation in the specified key.

BITOP operation destkey key [key ...]

The operation parameter can be any one of AND, OR, XOR, OR NOT. These four values correspond to logical union, logical OR, logical XOR, AND logical non operations respectively. AND, OR, AND XOR operations allow users to use any number of bitmaps as input. The NOT operation allows only one bitmap as input. The BITOP command returns the byte length of the stored bitmap after storing the result of the calculation in the specified key.

When the BITOP command performs an operation on two bitmaps of different lengths, it treats the value of the non-existent bits in the shorter bitmap as 0.

redis> set foo1 bar
OK
redis> set foo2 aar
OK
redis> bitop or res foo1 foo2
(integer) 3
redis> get res
"car"
Copy the code

Note: BITOP can be a slow command with O(N) time complexity, and efficiency should be considered when handling long strings.

Application scenarios

User behavior recorder

SETBIT is used to set the binary bit to 1 if the user has performed a certain behavior. GETBIT is used to determine whether the user has performed a certain behavior. BITCOUNT is used to know how many users have performed the behavior.

User Online Statistics

SETBIT and BITCOUNT can be used to achieve this, with the user ID as the key. Assume that today is the first day when the online statistics function is open, and the user with ID 1 will pass SETBIT 1 0 1 after being online. The result of using the BITCOUNT command when counting the total number of times this user has been online.

Storing data this way is still fast, even after 10 years, when each user consumes only a few hundred bytes of memory. If the bitmap data is large, you are advised to divide the bitmap into multiple small bitmaps for processing.