Do you know the functions of getbit and setbit in Redis?

There are five commonly used data structures in Redis, String, Hash, List, set, and zset. Getbit and setbit are special methods of obtaining data in String.
The underlying data of String is stored in binary, and the value we obtain is obtained through binary conversion, and getBit directly obtains the binary value corresponding to a certain bit.

1.What is offset

All data in the computer is stored in binary form. Each non-Chinese character occupies one byte (Byte), Chinese characters occupies two bytes, and one byte occupies 8 bits.

First set a kv (key: foo value: bar) in redis.
Insert image description here
The storage form in Redis is converted into binary (one byte 8bit): 01100010 01100001 01110010, and the offset actually refers to counting from left , the offset is the bit, and the offset 0 is the 0th bit.

Insert image description here

Notice:

  1. setbit can only be 0 or 1. If it is other values, an error will be reported.
  2. The maximum offset of setbit is 4294967295. If it exceeds it, an error will be reported.

2. Commonly used methods

Here we mainly demonstrate how to use spring-redis api to operate in the code.

  1. getbit/setbit
    gets the corresponding binary value
// key是对应的key
// offset偏移量
// true则是值1 false则为0
redisTemplate.opsForValue().setBit(key, offset, true);
  1. bitcount
    counts how many bits are 1 in total
// springredis没有提供的api方法
// 需要用到底层提供的execute方法使用connection去统计
long count = (long) redisTemplate.execute((RedisCallback<Object>) conn -> conn.bitCount(signInRedisKey.getBytes()));
  1. bitField
    counts values ​​within the offset range
/** key就是值
   offset是偏移多少,比如10
   from就是从多少开始数 比如 0
   那么就会返回 0-10 一百个数转换成的十进制数
   比如 0000000010 就返回 2 
   注意:返回的是List,集合中只有第一个数有值,如果该key不存在那么就会返回0
**/
List<Long> list = redisTemplate.execute((RedisCallback<List<Long>>) conn ->
                conn.bitField(key.getBytes(), BitFieldSubCommands.create().get(BitFieldSubCommands.BitFieldType.unsigned(offset).valueAt(from)));

3.Use

I believe many people will have this question when they first learn about it. My usage scenario is just to store strings, and there is no need to get any of its binary data.

I don’t know if you have ever thought about how to achieve a group chat on DingTalk where 10 people have not viewed it and 5 people have read it.

If a single piece of information stores a read and an unread, this will cause a large amount of database reading and writing. A group chat with dozens or hundreds of people may contain tens of thousands of messages a day. How can the database handle such high-frequency reading and writing? What's more, how to record who read it and who didn't?

Let’s use setbit to see if it can be achieved. For example, we are currently in group 1 and the 1001st message has a total of 100 people.
Each person corresponds to an ID. Assume 0-99
setbit group:message:1001:1 99 1.
Use bitcount to count the total. How many people have read it.

Now there is a new question, what if a user quits the group? For example, user 2 has left the group

Then record the number of people who have left the group + 1 and the total number of people + 1. If the number of people who have read = the total number of people - the number of people who have left the group, then it means that they have read it, otherwise it is not read.

Then for new users who join the group, we can setbit group:message:1001:1 100 1, which is convenient and fast without the need for expansion, etc., but remember that the maximum value is 4294967295

Summarize

The getbit and setbit features of redis can help solve many practical problems, and because the storage space is small, only one bit is used, so it can save space and improve performance. Before learning about this feature, I didn’t expect it to solve so many scene problems, such as check-in, group chat, etc. But after learning about it carefully, I found that it is really appropriate and wonderful to solve it in this way.

Guess you like

Origin blog.csdn.net/qq_40922616/article/details/123184717