你知道Redis中的getbit、setbit的作用吗?

Redis常用的有五种数据结构,String、Hash、List、set、zset。而getbit和setbit则是String中特殊的获取数据方式。
String底层数据是用二进制来存储的,而我们获取到的值就是通过二进制转换来的,而getBit就是直接获得某一位对应二进制的值。

1.什么是偏移量

在计算机里所有的数据都是以二进制的形式存储的,每一个非中文字符占一个字节(Byte),中文字符占两个字节,而一个字节又是占8bit。

先在redis中设置一个k-v(key:foo value:bar)
在这里插入图片描述
在Redis中的存储形式转换成二进制就是(一个字节8bit):01100010 01100001 01110010,而偏移量实际上指的就是从左往右数,偏移量是几就是第几位,偏移量0就是第0位。

你知道Redis中的getbit、setbit的作用吗?_第1张图片

注意:

  1. setbit 只能是0或者1,如果是其他值会报错。
  2. setbit最大的偏移量为4294967295,超过就会报错。

2.常用的方法

这里主要演示一下在代码中使用spring-redis api来操作。

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

3.用处

相信很多人刚了解的时候都会有这个疑问,我使用场景只是存储字符串,也不需要去拿其某一位二进制数据啊。

不知道大家有没有思考过,钉钉的群聊 10人未查看,5人已读是怎么实现的。

如果单纯一条信息存储一个已读数和未读数,这样会造成大量数据库读写,一个群聊几十上百人,信息一天可能达到几万条,如此高频读写,数据库怎么吃得消?何况要怎么记录是哪个人读了,哪个人没读?

我们用setbit看一看能不能实现,比如我们当前是 群 1 第 1001 条消息 一共有100个人
每个人对应一个id假设 0-99
setbit group:message:1001:1 99 1
使用bitcount就可以统计一共有多少人已读。

现在有新的问题,如果有用户退群了呢?比如用户2退群了

那么记录一下退群数 +1 总人数 +1,如果已读人数=总人数-退群数,那么就说明已读了,否则是未读数。

那么新的进群用户我们就可以 setbit group:message:1001:1 100 1,方便快捷无需扩容等,但切记最大值是4294967295

总结

redis的getbit、setbit特性可以帮助解决很多现实问题,而且因为存储空间小,一位就一个bit,所以能够很好的节省空间、提高性能。在了解该特性之前,没想到它能解决那么多场景问题,打卡、群聊等,而仔细了解后发现,用这种方式解决真的很恰当美妙。

你可能感兴趣的:(Java基础,个人分享,redis,缓存,java,bitmap,后端)