在计算机里所有的数据都是以二进制的形式存储的,每一个非中文字符占一个字节(Byte),中文字符占两个字节,而一个字节又是占8bit。
先在redis中设置一个k-v(key:foo value:bar)
注意:
这里主要演示一下在代码中使用spring-redis api来操作。
// key是对应的key
// offset偏移量
// true则是值1 false则为0
redisTemplate.opsForValue().setBit(key, offset, true);
// springredis没有提供的api方法
// 需要用到底层提供的execute方法使用connection去统计
long count = (long) redisTemplate.execute((RedisCallback<Object>) conn -> conn.bitCount(signInRedisKey.getBytes()));
/** 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)));
相信很多人刚了解的时候都会有这个疑问,我使用场景只是存储字符串,也不需要去拿其某一位二进制数据啊。
不知道大家有没有思考过,钉钉的群聊 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,所以能够很好的节省空间、提高性能。在了解该特性之前,没想到它能解决那么多场景问题,打卡、群聊等,而仔细了解后发现,用这种方式解决真的很恰当美妙。