Redis->Redis bitmap(位图) 相关操作 与 用户统计 - Go语言中文社区

Redis->Redis bitmap(位图) 相关操作 与 用户统计


1.分布式缓存Redis之bitmap、setbit

https://blog.csdn.net/u011489043/article/details/78990162

2.Redis的位图bitmap

https://blog.csdn.net/chengqiuming/article/details/79118089

 

 

Redis 中有有一种数据结构,非常便于位图级别的统计方案。

本篇文章将会对 该种结构的 操作与 应用场景进行归纳整理。

 

1.简介

2.相关操作

  2.1.置位/取值

  2.2 计算为1的位数

  2.3 与其他bitmap 进行集合操作

3.java操作bitmap

4.应用场景

 

1.简介

 

位图不是真正的数据类型,它是定义在字符串类型中。

type bitMapKey -> String


一个字符串类型的值最多能存储512M字节的内容。

位上限:2^(9+10+10+3)=2^32b  ,位上限指的是最多能有多少位。

2^32 还是一个很夸张的数字。

 

2.相关操作

bitMap 有一系列操作,下面我们进行分类归纳

 

2.1.置位/取值

置位 :设置某一位上的值  SETBIT

取值 :获取某一位上的值  GETBIT

 

置位:将 key 为 user:20181210   第7,第8位设置为1

该操作的返回值 为 原来该位置的值  0 或 1

VMware_192.168.75.128:6379-redis:0>setbit usercount:20181210 7 1
"0"

 

查看类型:

VMware_192.168.75.128:6379-redis:0>setbit usercount:20181210 7 1
"0"

 

取值 : 获取 key 上某个位上的值,

VMware_192.168.75.128:6379-redis:0>getbit usercount:20181210 7
"1"

 

 

 

 

2.2 计算为1的位数

 

统计为bitmap 中1的个数,使用 命令 bitcount

VMware_192.168.75.128:6379-redis:0>bitcount  usercount:20181210
"1"

 bitcount 统计的是1的个数,

bitcount test 0 -1 就是所有的,

bitcount 0 0 那么就应该是第一个字节中1的数量的,注意是字节 第一个字节也就是 0 1 2 3 4 5 6 7 这八个位置上。

 

见下面的测试样例,setbit单位是bit,bitcount是以byte为间隔统计的,接上面的预设值:

第2个字节中设置为1的数量,由于设置的是第7位为1 ,所以返回 0 


VMware_192.168.75.128:6379-redis:0>bitcount  usercount:20181210 1 1
"0"

第1个字节中为1的数量。

VMware_192.168.75.128:6379-redis:0>bitcount  usercount:20181210 0 0
"1"

 

 

 

2.3 与其他bitmap 进行集合操作

redis 127.0.0.1:6379> bitop operation destkey key [key...]  

//对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上

BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数:

BITOP AND destkey srckey1 … srckeyN ,对一个或多个 key 求逻辑与,并将结果保存到 destkey

BITOP OR destkey srckey1 … srckeyN,对一个或多个 key 求逻辑或,并将结果保存到 destkey

BITOP XOR destkey srckey1 … srckeyN,对一个或多个 key 求逻辑异或,并将结果保存到 destkey

BITOP NOT destkey srckey,对给定 key 求逻辑非,并将结果保存到 destkey
 

除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入,执行结果将始终保持到destkey里面。

  当 BITOP 处理不同长度的字符串时,较短的那个字符串所缺少的部分会被看作 0。返回值是保存到 destkey 的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。
 

 

3.java操作bitmap

这里我们选用的包是市面上主流的Jedis 包,如下:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

 

主要代码如下:

package com.redis.op;

import redis.clients.jedis.Jedis;

/**
 * Created by szh on 2018/12/10.
 */
public class BitCountTest {

    public static void main(String[] args) {

        Jedis jedis = new Jedis("192.168.75.128", 6379);

        String type = jedis.type("play:20181210");
        System.out.println("key type : " + type);

        Long result = jedis.bitcount("play:20181210");
        System.out.println("bitcount key : " + result);

        Long result2 = jedis.bitcount("play:20181210",0,0);
        System.out.println("bitcount key 0 0 : " + result2);

        Long result3 = jedis.bitcount("play:20181210",1,1);
        System.out.println("bitcount key 1 1 : " + result3);

    }

}

 

4.应用场景

setbit 可以理解是一个位数组,至于这个数组有多大,redis中bit映射被限制在512MB之内,所以最大是2^32。

   也就是在这样一个位数组上存0或者是1 ,可以结合bloomFilter的应用场景理解位数组的用法,将字符串使用一种合适哈希函数映射到不同的bit位上(2^32足够的大,可以满足需求)
 

应用场景1:

使用 bitmap 实现用户上线次数统计、统计活跃用户

假设现在我们希望记录自己网站上的用户的上线频率,比如说,计算用户 A 上线了多少天,用户 B 上线了多少天,诸如此类,以此作为数据,从而决定让哪些用户参加 beta 测试等活动 —— 这个模式可以使用 SETBIT 和 BITCOUNT 来实现。

  比如说,通过将一个用户的id对应value上的一位,通过对活跃用户对应的位进行置位,就能够用一个value记录所有活跃用户的信息。如图bitmap有9个位被置为1,表示这9个位上对应的用户是今天的活跃用户。其中第15位表示uid为15的用户,第一位表示uid为0的用户。(如果你的uid不是从1开始的,比如从100000开始,实际上你也可以相应的用uid减去初始值来表示其位数,比如1000000用户对应到bitmap的第一位)

 

  1. 节约空间,统计一亿人每天的登录情况,用一亿bit,约1200WByte,约10M的字符就能表示(因为bitop命令的返回值是保存到 time中的字符串的长度(以字节byte为单位),和输入 key 中最长的字符串长度相等。即1亿除以8bit=1250万Byte)
  2. 计算方便。

 

性能:
  如果你的 bitmap 数据非常大,那么可以考虑使用以下两种方法:

● 将一个大的 bitmap 分散到不同的 key 中,作为小的 bitmap 来处理。使用 Lua 脚本可以很方便地完成这一工作。 
● 使用 BITCOUNT 的 start 和 end 参数,每次只对所需的部分位进行计算,将位的累积工作(accumulating)放到客户端进行,并且对结果进行缓存 (caching)。

何时使用:
  如果活跃用户在百万级别,使用Redis BitMap很划算。

  如果活跃用户很少,而用户id都是10位以上的int。那就很浪费内存了,还不如使用set集合,然后求交集就可以了。
 

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/u010003835/article/details/84940750
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-05-16 02:53:20
  • 阅读 ( 1188 )
  • 分类:Redis

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢