数据库
Redis位图数据结构
  • By刘立博
  • 2020-03-06 23:46:52
  • 908人已阅读

位图并不是什么特殊的数据结构,而是一个字节数组。我们既可以使用get/set向其设置一个普通的ASCII码字符,也可以通过getbit/setbit按比特位设置高位/低位。

 

设置和读取

 

按比特位设置高位/低位,并按位读取

假定保存某用户本周的签到情况,该用户星期一,星期二,星期天进行了签到操作:

 

星期

星期一

星期二

星期三

星期四

星期五

星期六

星期天

签到情况

签到

签到

未签到

未签到

未签到

未签到

签到

比特值

1

1

0

0

0

0

1

比特位

0

1

2

3

4

5

6

 

设置比特值

通过使用setbit,将0,1,6位置为高位:

 

192.168.3.9:6379> setbit testWeek 0 1
(integer) 0
192.168.3.9:6379> setbit testWeek 1 1
(integer) 0
192.168.3.9:6379> setbit testWeek 6 1
(integer) 0

 

JAVA实现:

 

@SpringBootTest
public class TestRedis {

    @Autowired
    RedisTemplate<String,String> redisTemplate;

    @Test
    public void testRedis()
    {
        redisTemplate.opsForValue().setBit("testWeek",0,true);
        redisTemplate.opsForValue().setBit("testWeek",1,true);
        redisTemplate.opsForValue().setBit("testWeek",6,true);
    }
}

 

PS:为了降低冗余,后续的JAVA代码只包含testRedis方法中的代码

 

读取比特值

通过getbit,便可以获取该用户每日签到明细:

 

192.168.3.9:6379> getbit testWeek 0
(integer) 1
192.168.3.9:6379> getbit testWeek 1
(integer) 1
192.168.3.9:6379> getbit testWeek 2
(integer) 0
192.168.3.9:6379> getbit testWeek 3
(integer) 0
192.168.3.9:6379> getbit testWeek 4
(integer) 0
192.168.3.9:6379> getbit testWeek 5
(integer) 0
192.168.3.9:6379> getbit testWeek 6
(integer) 1

 

JAVA实现
       

for (int i = 0; i < 7 ; i++)
    System.out.println(i+":"+redisTemplate.opsForValue().getBit("testWeek", i));

 

输出:0:true,1:true,2:false,3:false,4:false,5:false,6:true

 

按比特位设置ASCII字符,以字节读取

假定需要把A存放进位图:A的ASCII码为65,转为2进制为:01000001

 

高位 <- 低位

 

0

1

0

0

0

0

0

1

7

6

5

4

3

2

1

0

 

但Redis设置顺序是从低位->高位,所以比特位设置顺序为:

 

1

0

0

0

0

0

1

0

7

6

5

4

3

2

1

0

 

所以,将第1位和第7位设置为1,即可:

 

192.168.3.9:6379> setbit mapA 1 1
(integer) 0
192.168.3.9:6379> setbit mapA 7 1
(integer) 0
192.168.3.9:6379> get mapA
"A"

 

统计

 

高位统计

使用bitcount,可以统计出该位图中高位的数量,比如统计签到天数:

 

192.168.3.9:6379> bitcount testWeek
(integer) 3

 

JAVA实现:

 

        System.out.println(
            redisTemplate.execute(
                (RedisCallback<Long>) rcb -> rcb.bitCount("testWeek".getBytes())
            )
        );

 

输出:3

 

高/低位查找

使用bitpos命令,可以查找出第一个高位/低位的位置,例如需要查找第一次未签到的事件发生于星期几:

 

192.168.3.9:6379> bitpos testWeek 0
(integer) 2

 

JAVA实现

 

        System.out.println(
            redisTemplate.execute(
                (RedisCallback<Long>) rcb -> rcb.bitPos("testWeek".getBytes(),false)
            )
        );

 

输出:2