redis-bitmap

redis-bitmap redis位图

实现原理:

就是字符串,字符数组

优点

1.节省空间,按位存的,比如记录用户登录次数,只需要365/8≈40多byte
2.设置时候时间复杂度O(1)、读取时候时间复杂度O(n),操作是非常快的。只要长度不长,读取是很快的.

注意事项

bitmap有位数限制,512m以内,on的读取复杂度,太长效率太差了.
bitcount key 0 0 这种情况只返回前8位的统计结果.

思考

使用方法(BITPOS 2.8.7可用,代码里面有使用例子)

127.0.0.1:6379> setbit test 100 1
(integer) 0
127.0.0.1:6379> setbit test 99 1
(integer) 0
127.0.0.1:6379> setbit test 98 0
(integer) 0
127.0.0.1:6379> setbit test 97 0
(integer) 0
127.0.0.1:6379> setbit test 96 1
(integer) 0
127.0.0.1:6379> getbit test 96
(integer) 1
127.0.0.1:6379> getbit test 95
(integer) 0
127.0.0.1:6379> getbit test 97
(integer) 0
127.0.0.1:6379> getbit test 98
(integer) 0
127.0.0.1:6379> getbit test 99
(integer) 1
127.0.0.1:6379> getbit test 100
(integer) 1
127.0.0.1:6379> bitcount test 0 -1
(integer) 3

案例:

1.用户签到
用户id作为key,value为签到的情况,1代表签到,0代表未签到.

       //用户uid
        String uid = "1";
        String cacheKey = "sign_" + Integer.valueOf(uid);
        //记录有uid的key
        // $cacheKey = sprintf("sign_%d", $uid);
        
        //开始有签到功能的日期
        String startDate = "2017-01-01";

        //今天的日期
        String todayDate = "2017-01-21";
        
        //计算offset(时间搓)
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        long startTime = format.parse(startDate).getTime();
        long todayTime = format.parse(startDate).getTime();
        long offset = (long) Math.floor((todayTime - startTime) / 86400);

        System.out.println("今天是第" + offset + "天");
        //签到
        //一年一个用户会占用多少空间呢?大约365/8=45.625个字节,好小,有木有被惊呆?
        jedis.setbit(cacheKey, offset, "1");

        //查询签到情况
        boolean bitStatus = jedis.getbit(cacheKey, offset);
        //判断是否已经签到
        //计算总签到次数
        long qdCount = jedis.bitcount(cacheKey);

2.统计活跃用户数:
每天当天的日期作为key,当天的活跃用户作为offset,value设置成1,为bitcount做准备.
通过bitcount 统计value的数量,就可以知道当天活跃用户数了.
如果 是几天的活跃用户数,那么 可以用bittop 命令 合并结果.

  Map<String,List<Integer>>dateActiveuser = new HashMap<>();
        Integer[] temp01 = {1,2,3,4,5,6,7,8,9,10};
        List<Integer>temp01List = new ArrayList<>();
        Collections.addAll(temp01List,temp01);
        dateActiveuser.put("2017-01-10",temp01List);


        Integer[] temp02 = {1,2,3,4,5,6,7,8};
        List<Integer>temp02List = new ArrayList<>();
        Collections.addAll(temp02List,temp02);
        dateActiveuser.put("2017-01-11",temp02List);

        Integer[] temp03 = {1,2,3,4,5,6};
        List<Integer>temp03List = new ArrayList<>();
        Collections.addAll(temp03List,temp03);
        dateActiveuser.put("2017-01-12",temp03List);

        Integer[] temp04 = {1,4,5,6};
        List<Integer>temp04List = new ArrayList<>();
        Collections.addAll(temp04List,temp04);
        dateActiveuser.put("2017-01-13",temp04List);

        Integer[] temp05 = {1,4,5,6};
        List<Integer>temp05List = new ArrayList<>();
        Collections.addAll(temp05List,temp05);
        dateActiveuser.put("2017-01-14",temp05List);

        String date[] = {"2017-01-10","2017-01-11","2017-01-12","2017-01-13","2017-01-14"};

       //测试数据放入redis中
        for (int i=0;i<date.length;i++){
            for (int j=0;j<dateActiveuser.get(date[i]).size();j++){
                jedis.setbit(date[i], dateActiveuser.get(date[i]).get(j), "1");
            }
        }

        //bitOp
        jedis.bitop(BitOP.AND, "stat", "2017-01-10", "2017-01-11","2017-01-12");

        System.out.println("总活跃用户:"+jedis.bitcount("stat"));

        jedis.bitop(BitOP.AND, "stat1", "2017-01-10", "2017-01-11","2017-01-14");
        System.out.println("总活跃用户:"+jedis.bitcount("stat1"));

        jedis.bitop(BitOP.AND, "stat2", "2017-01-10", "2017-01-11");
        System.out.println("总活跃用户:"+jedis.bitcount("stat2"));
        
        System.out.println("总活跃用户:"+jedis.bitcount("2017-01-11"));
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • BitMap是什么通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。Bitmaps 本...
    IT5阅读 2,746评论 1 3
  • 位图 API setbit key offset value 给位图指定索引设置值image.png getbit...
    文刀雨阅读 1,534评论 0 0
  • 1.1 资料 ,最好的入门小册子,可以先于一切文档之前看,免费。 作者Antirez的博客,Antirez维护的R...
    JefferyLcm阅读 17,110评论 1 51
  • Redis key 值是二进制安全的,这意味着可以用任何二进制序列作为key值,从形如”foo”的简单字符串到一个...
    壹点零阅读 1,440评论 0 2
  • 每个人都有自己的优点缺点,在一个团队中也是一样,我们要学会互帮互助,对自己的队友要尊重以及信任,我们要向着一个方向...
    台东一店高悦阅读 158评论 0 0