资讯专栏INFORMATION COLUMN

redis的bitset实战

Hegel_Gu / 1613人阅读

摘要:类似统计最近天连续登陆的人的个数这类场景就可以使用来实现。对于的操作要注意,各个操作的时间复杂度,如果是则都是,等都是,在比较大的时候要注意,可能是潜在的慢查询

本文主要研究一下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

setbit

getbit

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/36825.html

相关文章

  • 聊聊redis数据结构应用

    摘要:应用之分布式会话的实战的实战的实战实战版本之购物车服务实战版本之投票服务聊聊在中的数据结构 序 本文主要研究一下redis的数据结构的应用 string 最常用的就是incr操作,比如可以用来维护用户在某个抽奖活动的剩余抽奖次数 setnx方法可以用来实现分布式锁 hashmap 可以用来存储session,作为分布式session的一个实现方案 可以用来存储用户购物车,valu...

    wudengzan 评论0 收藏0
  • Redis GEO

    摘要:语法说明返回一个或多个位置元素的表示返回值一个数组,数组的每个项都是一个。返回值一个数组,数组中的每个项表示一个范围之内的位置元素。 简介 Redis 3.2 版本提供了GEO(地理信息定位)功能,支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能,对于需要实现这些功能的开发者来说是一大音。GEO功能是 Redis 的另一位作者Matt Stancliff 借...

    Corwien 评论0 收藏0
  • redis系列:通过demo学习string命令

    摘要:前言该文章将通过一个小将讲述中的类型命令。直接根据功能方面进行讲述,穿插命令操作说明。就是对应的命令了,相关联的还有和。需要注意的是在版本提供了参数用于取代和,后续版本可能会移除和命令。通过每天的记录来统计用户连续上线的情况。 前言 该文章将通过一个小demo将讲述Redis中的string类型命令。demo将以springboot为后台框架快速开发,iview前端框架进行简单的页面设...

    pinecone 评论0 收藏0
  • elasticsearch学习笔记高级篇(二)——filter执行原理深度剖析

    摘要:对于小或,不缓存。这样下次如果在有这个条件过来的时候,就不用重新扫描倒排索引,反复生成,可以大幅度提升性能。比好的原因除了不计算相关度分数以外还有这个。 下面详细讲一下为什么filter的性能很高,filter的底层原理究竟是什么? 通过一个搜索的场景来深入剖析一下,当一个filter搜索请求打到Elasticsearch的时候,ES会进行下面的操作: (1)在倒排索引中查找搜索串,获...

    ckllj 评论0 收藏0
  • 简单实用布隆过滤器

    摘要:前言布隆过滤器是年由布隆提出的。布隆过滤器可以用于检索一个元素是否在一个集合中。而在中有个位向量,我们可以基于实现一个简单实用的布隆过滤器。实现代码布隆过滤器将元素加入到过滤器为时,索引为判断元素是否在过滤器中为存在,为不存在为时,索引为 前言 布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。 布隆过滤器可以用于检索一...

    alanoddsoff 评论0 收藏0

发表评论

0条评论

Hegel_Gu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<