A bit is used to represent the value or state of an element, where the key is the corresponding element itself. Bitmaps itself is not a data structure; it is actually a string (the value of the key is the last binary in the image above), but it can operate on bits of the string. Bitmaps comes with a separate set of commands, so using Bitmaps in Redis is not the same as using strings. Think of Bitmaps as an array of bits, each cell of which can store only zeros and ones. The subscripts of the array are called offsets in Bitmaps.


The orders of the BitMap

SETBIT

Syntax: SETBIT key offset value

Description:

Sets or clears the bits at the specified offset for the string value held by key.

Bits can be set or cleared depending on the value argument, which can be 0 or 1.

Automatically generates a new string value when key does not exist.

The string is grown to ensure that it can store value at the specified offset. When the string value is stretched, the blank space is filled with 0.

The offset argument must be greater than or equal to 0 and less than 2^32 (the bit mapping is limited to 512 MB).

Use the big onesoffsetSETBITOperationally, memory allocation can cause the Redis server to block.

The return value:

The string value specifies the bits originally stored at the offset.

Example:

# SETBIT returns the value of the previous bit (default is 0). This generates 126 bits
coderknock> SETBIT testBit 125 1
(integer) 0
coderknock> SETBIT testBit 125 0
(integer) 1
coderknock> SETBIT testBit 125 1
(integer) 0
coderknock> GETBIT testBit 125
(integer) 1
coderknock> GETBIT testBit 100
(integer) 0
# SETBIT value can only be 0 or 1 binary value can only be 0 or 1
coderknock> SETBIT testBit 618 2
(error) ERR bit is not an integer or out of rangeCopy the code

Get the value

GETBIT


Syntax: GETBIT key offset
Description:

Gets the bit at the specified offset for the string value stored by key.

Returns 0 if offset is greater than the length of the string value, or the key does not exist.

The return value:

The string value specifies the bit on the offset.

Example:
coderknock> EXISTS bit
(integer) 0
coderknock> SETBIT bit 125 1
(integer) 0
coderknock> GETBIT bit 125
(integer1)The # offset is 0 if it does not exist
coderknock> GETBIT bit 126
(integer) 0
# You can see that bit is itself a string
coderknock> GET bit
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0 0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0 0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 "Copy the code

Gets the number of bits with a range of 1 specified by Bitmaps

BITCOUNT


Syntax: BITCOUNT key start
Description:

Counts the number of bits set to 1 in the given string.

In general, the entire string given will be counted, and by specifying additional start or end arguments, you can make counting happen only on specific bits.

The start and end arguments are set similarly to the GETRANGE command, with negative values: -1 for the last byte, -2 for the penultimate byte, and so on.

Nonexistent keys are treated as empty strings, so BITCOUNT on a nonexistent key results in 0.

The return value:

The number of bits to be set to 1.

Example:
The bit here is based on the command in the GETBIT example
coderknock> BITCOUNT bit
(integer1)# Count the number of bits in bit with the value 1
coderknock> BITCOUNT bit
(integer) 1
coderknock> SETBIT bit 0 1
(integer) 0
coderknock> BITCOUNT bit
(integer2)# Count the number of bits 1 in the specified position bit
coderknock> BITCOUNT bit 10 126
(integer1)Copy the code

Multiple Bitmaps operations

BITOP


BITOP operation destkey key [key…]
Description:

Bitwise operations are performed on one or more string keys that hold binary bits and the result is saved to destkey.

Operation can be either AND, OR, NOT, OR XOR:

  • BITOP AND destkey key [key …] , obtains a logical union for one or more keys, and saves the result to destkey.

  • BITOP OR destkey key [key …] To obtain logical or for one or more keys and save the result to destkey.

  • BITOP XOR destkey key [key …] To obtain logical XOR for one or more keys and save the result to the Destkey.

  • BITOP NOT destKey Key Specifies the logical no of the given key and saves the result to the destkey.

With the exception of the NOT operation, any operation can take one or more keys as input.

Handles strings of different lengths

When BITOP processes strings of different lengths, the missing part of the shorter string is treated as a 0.

An empty key is also considered a sequence of strings containing zeros.

The return value:

The length of the string saved to the destkey is the same as that of the longest string in the input key.

Example:
coderknock> SETBIT bits-1 0 1
(integer) 0
coderknock> SETBIT bits-1 3 1
(integer) 0
# bits - 1 to 1001

coderknock> SETBIT bits-2 0 1
(integer) 0
coderknock> SETBIT bits-2 1 1
(integer) 0
coderknock> SETBIT bits-2 3 1
(integer) 0
# bits - 2 to 1011

#bits-1 bits-2 Perform the parallel operation
coderknock> BITOP AND and-result bits-1 bits-2
(integer) 1
coderknock> GETBIT and-result 0
(integer) 1
coderknock> GETBIT and-result 1
(integer) 0
coderknock> GETBIT and-result 2
(integer) 0
coderknock> GETBIT and-result 3
(integer1)#and-result 1001

#bits-1 bits-2 To do or
coderknock> BITOP OR or-result bits-1 bits-2
(integer) 1
coderknock> GETBIT and-result 0
(integer) 1
coderknock> GETBIT and-result 1
(integer) 0
coderknock> GETBIT and-result 2
(integer) 0
coderknock> GETBIT and-result 3
(integer1)#or-result 1011

No operation can be performed on only one key
coderknock> BITOP NOT not-result bits-1 bits-2
(error) ERR BITOP NOT must be called with a single source key.
coderknock> BITOP NOT not-result bits-1
(integer) 1
coderknock> GETBIT not-result 0
(integer) 0
coderknock> GETBIT not-result 1
(integer) 1
coderknock> GETBIT not-result 2
(integer) 1
coderknock> GETBIT not-result 3
(integer) 0
# not-result 0110

Xor operation
coderknock> BITOP XOR xor-result bits-1 bits-2
(integer) 1
coderknock> GETBIT xor-result 0
(integer) 0
coderknock> GETBIT xor-result 1
(integer) 1
coderknock> GETBIT xor-result 2
(integer) 0
coderknock> GETBIT xor-result 3
(integer) 0
# xor-result 0010Copy the code

BITOPThe complexity of is O(N). When processing large matrices or statistics of large data volume, it is better to assign tasks to slave nodes to avoid blocking the master node.

Calculates the offset in Bitmaps where the first value is bit

BITPOS

Available since 2.8.7.

Time complexity: O(N).

BITPOS key bit [start][end]
Description:

Returns the first bit in the string to be set to 1 or 0.

Return a position, treating the string as an array of bytes from left to right, with the first qualifying byte at position 0, the second qualifying byte at position 8, and so on.

GETBIT and SETBIT are similar commands that manipulate byte bits.

By default, the entire string is retrieved once, only if you specify the start and end arguments (specifying the start and end bits is possible), and the range is interpreted as a range of one byte rather than a series of bits. So start=0 and end=2 refer to the first three bytes.

Note that the position of the returned bit always starts at 0, even if start is used to specify a start byte.

Like the GETRANGE command, start and end can contain negative values, which will be counted from the end of the string, -1 being the last byte of the string, -2 being the penultimate, and so on.

Non-existent keys are treated as empty strings.

The return value:

The command returns the first bit in the string to be set to 1 or 0.

If we look for a bit 1 in an empty string or a string of 0 bytes, the result will be -1.

If we look for a string with a bit of 0 and a string containing only 1, the first rightmost space in the string is returned. If there is a string of three bytes with the value 0xFF, the command BITPOS key 0 will return 24 because bits 0 through 23 are 1’s.

Basically, we can think of a string as having an infinite number of zeros on the right-hand side.

However, if you look for a specified value in the specified start and end ranges and there is no corresponding value in that range, the result will be -1.

Example:
redis> SET mykey "\xff\xf0\x00"
OK
redis> BITPOS mykey 0 # Find the position in the string where bit is 0
(integer) 12
redis> SET mykey "\x00\xff\xf0"
OK
redis> BITPOS mykey 1 0 Find the position in the string where the bit value is 1 starting from the 0th byte
(integer) 8
redis> BITPOS mykey 1 2 Find the position in the string where the bit value is 1 starting from the second byte (12)
(integer) 16
redis> set mykey "\x00\x00\x00"
OK
redis> BITPOS mykey 1 # Find the string where the bit value is 1
                    (integer1) -Copy the code

BITFIELD

Available since 3.2.0.

Time complexity: The complexity of each subcommand is O(1).

Grammar: BITFIELD key [GET type offset] [the SET type offset value] [INCRBY type offset increment] [OVERFLOW WRAP | | SAT FAIL]
Description:

BITFIELD key GET type offset INCRBY type offset increment

The 'BITFIELD' command treats a Redis string as an array of bits and accesses integers of varying lengths stored in the array (stored integers do not need to be aligned). In other words, with this command, the user can perform operations such as "set the 5-bit long signed integer at offset 1234", "Get the 31-bit long unsigned integer at offset 4567", etc. In addition, the 'BITFIELD' command can perform addition and subtraction operations on specified integers, and these operations can be set up to properly handle overflow cases during computation.Copy the code

The BITFIELD command can operate on more than one bit range simultaneously in a single call: it takes a list of operations to be performed as arguments and returns as a reply an array in which each element is the result of the corresponding operation.

For example, the following command shows how to add an 8-bit signed integer at offset 100 and get a 4-bit unsigned integer at offset 0:

coderknock> BITFIELD mykey INCRBY i8 100 1 GET u4 0
1) (integer1) (2)integer) 0Copy the code

Note:

  • Use the GET subcommand to access bits outside the current range of the string (including if the key does not exist). The value of the bits outside the range is treated as 0.

  • Using the SET subcommand or the INCRBY subcommand to access bits beyond the current range of the string causes the string to be enlarged, and the enlarged bits are padded with bits with a value of 0. When extending a string, the command calculates the minimum length required to perform the operation based on the farthest bits of the string that are currently available.

Supported subcommands and numeric types

The following are the subcommands supported by the BITFIELD command:

  • GET


    — returns the specified range of bits.

  • SET



    — Sets the specified binary range and returns its old value.


  • INCRBY



    — Performs addition on the specified range of bits and returns its old value. The user can implement subtraction by passing a negative value to the increment parameter.


In addition to the above three subcommands, there is a subcommand that changes the behavior of subsequent INCRBY subcommands in the event of an overflow:

  • OVERFLOW [WRAP|SAT|FAIL]

When the binary range value is set to an integer, the user can prefix the type parameter with I to indicate a signed integer, or use U to indicate an unsigned integer. For example, we can use u8 for an 8-bit unsigned integer, and i16 for a 16-bit signed integer.

The BITFIELD command supports up to 64 – and 63-bit unsigned integers. The 63-bit limit on unsigned integers is due to the Redis protocol’s inability to return 64 – bit unsigned integers.

Binary and position offsets

In binary range commands, the user has two ways to set offsets:

  • If the user is given a number without any prefix, this number indicates the zero-base offset of the string.

  • On the other hand, if the user is given an offset prefixed with #, the command will use this offset multiplied by the bit length of the number type being set to calculate the true offset.

For example, for this command:

BITFIELD mystring SET i8 #0 100 i8 #1 200
Copy the code

The myString command sets the value of the first i8 bit to 100 and the value of the second i8 bit to 200. When we use a string key as an array that stores integers of equal length, using the # prefix saves us the trouble of manually calculating where the bits are set.

Overflow control

Users can specify the behavior of the BITFIELD command in OVERFLOW or underflow situations with the OVERFLOW command and the three arguments shown below:

  • WRAP: Use the WRAP around method to handle overflows of both signed and unsigned integers. For unsigned integers, wrapping is like performing a modular calculation using the value itself and the largest unsigned integer that can be stored, which is also standard behavior in C. For signed integers, an overflow causes the number to be reevaluated from the smallest negative number, while an underflow causes the number to be reevaluated from the largest positive number. For example, if we add one to an i8 integer with a value of 127, we get -128.

  • SAT: the saturation calculation method is used to handle overflow, that is, the result of underflow calculation is the smallest integer value, and the result of overflow calculation is the largest integer value. For example, if we add 10 to an i8 integer with a value of 120, the result of the command will be 127, the largest integer value that type I8 can store. In contrast, if a calculation of an i8 value causes an underflow, the i8 value is set to -127.

  • FAIL: In this mode, the command rejects computations that would cause overflows or underflows and returns a null value to the user indicating that the computations were not executed.

Note that the OVERFLOW subcommand will only have an effect on the INCRBY command executed immediately after it until the next OVERFLOW command is executed with it. By default, the INCRBY command uses WRAP to handle overflow calculations.

Here is an example of using the OVERFLOW subcommand to control OVERFLOW behavior:

coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer1) (2)integer) 1

coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer() 2, 2)integer) 2

coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer3 (2))integer) 3

coderknock> BITFIELD mykey incrby u2 100 1 OVERFLOW SAT incrby u2 102 1
1) (integer0 -- Use the default WRAP method to handle the overflow.integer) 3 -- Use SAT to handle overflowCopy the code

Here is an example of a subcommand that returns a null value because of OVERFLOW FAIL behavior:

coderknock> BITFIELD mykey OVERFLOW FAIL incrby u2 102 1
1) (nil)Copy the code
role

The BITFIELD command is useful because it can store many small integers into a bitmap of large length, or divide a very large key into smaller keys to store it, thus using memory very efficiently and making Redis available for many different applications — especially in the field of real-time analysis: BITFIELD’s ability to control computational overflow in a specified way makes it useful in this area.

Performance Considerations

BITFIELD is generally a fast command, but it is important to note that accessing the remote bits of a short string will trigger a memory allocation operation that may take longer than the command accessing an existing string.

An arrangement of binary bits

BITFIELD treats the binary bit at offset 0, the first byte of the bitmap, as the most significant bit, and so on. For example, if we set a bitmap that has been pre-set to all zeros and set its value at offset 7 to the 5-bit unsigned integer value 23 (binary 10111), the command will produce the following bitmap representation:

+ + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- + | | 00000001 | 01110000 + + -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- +Copy the code

When offsets and integer lengths are aligned with byte boundaries, bitfields represent bits in the same way as big Endian notation, but it is also important to understand how these bits are arranged in the absence of alignment.

The return value:

Returns 1 if the member element is a member of the collection.

Returns 0 if the member element is not a member of the collection, or the key does not exist.

Example:

coderknock> SISMEMBER saddTest add1
(integer1)The # add7 element does not exist
coderknock> SISMEMBER saddTest add7
(integer) 0
# key does not exist
coderknock> SISMEMBER nonSet a
(integer) 0
The # key type is not a collection
coderknock> SISMEMBER embstrKey a
(error) WRONGTYPE Operation against a key holding the wrong kind of value    Copy the code

case

Scenario 1: User check-in

Jedis redis = new Jedis("192.168.31.89", 6379100, 000); // user uid String UID ="1";
String cacheKey = "sign_"+Integer.valueOf(uid); // Record the uid key //$cacheKey = sprintf("sign_%d".$uid); // The date the check-in function starts String startDate ="2017-01-01"; // Today's date String todayDate ="2017-01-21"; Long startTime = dateParase(startDate,"yyyy-MM-dd").getTime();
long todayTime = dateParase(todayDate,"yyyy-MM-dd").getTime();
long offset = (long) Math.floor((todayTime - startTime) / 86400);

System.out.println("Today is number one."+offset+"Day"); // Check-in // How much space does a user take up in a year? About 365/8=45.625 bytes. How small is that? redis.setbit(cacheKey,offset,"1"); Boolean bitStatus = redis. Getbit (cacheKey, offset); Long qdCount = redis.bitcount(cacheKey);Copy the code

Scenario 2: Collecting statistics on active users

Use time as the cacheKey and set the user ID to offset, set to 1 if the user was active on that day. How do I count active users for a certain day/month/year? BITOP operation destkey [key…] Note: Perform bitwise operations on one or more string keys that store binary bits, and save the result to destkey. Note: The BITOP command supports any of the four operations: AND, OR, NOT, AND XOR

Map<String,List<Integer>>dateActiveuser = new HashMap<>();
Jedis redis = new Jedis("192.168.31.89", 6379100, 000); The Integer [] temp01 =,2,3,4,5,6,7,8,9,10 {1}; List<Integer>temp01List = new ArrayList<>(); Collections.addAll(temp01List,temp01); dateActiveuser.put("2017-01-10",temp01List); The Integer [] temp02 =,2,3,4,5,6,7,8 {1}; List<Integer>temp02List = new ArrayList<>(); Collections.addAll(temp02List,temp02); dateActiveuser.put("2017-01-11",temp02List); The Integer [] temp03 = {6}; List<Integer>temp03List = new ArrayList<>(); Collections.addAll(temp03List,temp03); dateActiveuser.put("2017-01-12",temp03List); The Integer [] temp04 =,4,5,6 {1}; List<Integer>temp04List = new ArrayList<>(); Collections.addAll(temp04List,temp04); dateActiveuser.put("2017-01-13",temp04List); The Integer [] temp05 =,4,5,6 {1}; List<Integer>temp05List = new ArrayList<>(); Collections.addAll(temp05List,temp05); dateActiveuser.put("2017-01-14",temp05List);

String date[] = {"2017-01-10"."2017-01-11"."2017-01-12"."2017-01-13"."2017-01-14"}; // Test data is put into redisfor(int i=0; i<date.length; i++){for(int j=0; j<dateActiveuser.get(date[i]).size(); j++){ redis.setbit(date[i], dateActiveuser.get(date[i]).get(j),"1");
    }
}

//bitOp
redis.bitop(BitOP.AND, "stat"."stat_2017-01-10"."stat_2017-01-11"."stat_2017-01-12");

System.out.println("Total active Users:"+redis.bitcount("stat"));

redis.bitop(BitOP.AND, "stat1"."stat_2017-01-10"."stat_2017-01-11"."stat_2017-01-14");
System.out.println("Total active Users:"+redis.bitcount("stat1"));

redis.bitop(BitOP.AND, "stat2"."stat_2017-01-10"."stat_2017-01-11");
System.out.println("Total active Users:"+redis.bitcount("stat2"));Copy the code