redis的bitset实战
2018-09-06 16:08
417 查看
序
本文主要研究一下redis的bitset数据结构的用场相关命令
SETBIT
时间复杂度为O(1)setbit login.20180906 102400000 0 setbit login.20180905 201400000 1
GETBIT
时间复杂度为O(1)getbit login.20180905 201400000
BITOP
时间复杂度为O(N)bitop or login.9m.week1or login.20180905 login.20180906 getbit login.9m.week1or 201400000
主要做bitset的and、or、xor、not操作,结果存在新的bitset中,注意时间复杂度为O(N)
BITPOS
时间复杂度为O(N)bitpos login.20180905 1
返回指定bitset中在指定起始位置中第一个出现指定值的offset,不传start,end默认估计是0,-1
BITCOUNT
时间复杂度为O(N)bitcount login.20180905
统计bitset中出现1的个数
使用场景
假设有个签到的需求,要实现的功能如下:展示当天是否已经签到,签到了不能再签到了
展示最近一周的或者最近一个月的签到情况/历史(可以只不详细记录到每天的签到时间,只记录每天是否签到)
判断是否连续签到,若本周连续签到,则给予抽奖机会
这里我们就可以使用redis的bitset来实现:
签到
boolean originValue = redisTemplate.opsForValue().setBit(uidYearKey,dayIndx,true);
这里的key由uid,year构成,然后offset采用day的index
每个uid每个year一个key的话,如果用户数过多可能造成redis的key太多
获取签到数据
BitSet bitSet = fromByteArrayReverse(redisTemplate.opsForValue().get(uidYearKey).getBytes()); public static BitSet fromByteArrayReverse(final byte[] bytes) { final BitSet bits = new BitSet(); for (int i = 0; i < bytes.length * 8; i++) { if ((bytes[i / 8] & (1 << (7 - (i % 8)))) != 0) { bits.set(i); } } return bits; }
这里有个注意事项,java读取bytes从小到大是从右往左读(
大端),而redis存储的bytes从小到大是从左往右(
小端),因而这里读取bytes转为BitSet需要逆向一下
BitSet Range
public BitSet get(int fromIndex, int toIndex) { //...... }
BitSet有个方法,可以根据index来进行range,之后就可以用新的BitSet进行相关统计,比如BitSet的cardinality
小结
对于bitset来说,其优点就是节省内存,如果直接把用户id作为offset来存储相应的值,这个相比hash来说,节省了很多空间。类似统计最近N天连续登陆的人的个数这类场景就可以使用bitset来实现。对于bitset的操作要注意,各个操作的时间复杂度,如果是getbit、setbit则都是O(1),bitop、bitcount、bitpos等都是O(N),在N比较大的时候要注意,可能是潜在的慢查询
doc
setbitgetbit
bitop
bitpos
bitcount
Efficient analytics with Redis bitmaps
Be Careful With your Redis BitSets and Java
REDIS BITMAPS – FAST, EASY, REALTIME METRICS
Bitmaps vs. Sets to track Monthly Active Users in Redis
storing-hundreds-of-millions-of-simple-keys-in-282-mb-with-redis
相关文章推荐
- Redis实战之征服 Redis + Jedis + Spring (一)
- redis pub/sub 实战: 微信语音识别
- redis代码实战
- 实战学习NodeJS建站(5)—nodejs 访问 redis
- 项目实战:LAMP环境+Xcache+Redis,另附Memcached配置。
- Redis常见7种使用场景(PHP实战)
- redis 实战系列二:用python操作redis集群
- java架构师、集群、高可扩展、高性能、高并发、性能优化、Spring boot、Dubbo、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式项目实战学习架构师之路
- Redis实战之征服 Redis + Jedis + Spring (一)
- 彻底清除Linux centos minerd木马 实战 跟redis的设置有关
- redis实战读后感(六)-使用Reids构建应用程序组件
- 国内外三个不同领域巨头分享的Redis实战经验及使用场景
- Redis实战应用举例
- Redis实战应用举例
- .NET分布式缓存Redis从入门到实战
- 国内外三个不同领域巨头分享的Redis实战经验及使用场景
- Redis实战之Redis + Jedis
- Tomcat7基于Redis的Session共享实战一
- C# Redis实战(二)
- Redis实战(5)数据类型三Lists