关于位图Bitmaps的介绍

目录

1、基本概念

1.1、介绍

1.2、关键字

1.3、结构原理

2、常用命令

2.1、SETBIT

2.2、GETBIT

2.3、BITCOUNT

2.4、BITOP

2.5、BITPOS

3、应用场景

4、使用示例


前言

        Redis的Bitmaps是一种基于字符串的数据结构,用于处理位级别的操作。

        Bitmaps在Redis中并不是一种独立的数据类型,而是基于字符串实现的,但它们提供了高效的位操作功能,适用于需要处理大量布尔值或二进制数据的场景。


1、基本概念

1.1、介绍

        Bitmaps(位图) 是一种高效的数据结构,通过二进制位(bit)来表示数据的存在性或状态。每个 bit 可以存储一个二元状态(0 或 1),通常用于表示布尔型数据(如是否在线、是否注册等)。

        其核心优势是空间效率极高,常用于需要处理大规模二元数据的场景。

1.2、关键字

位图(Bitmaps)

        可以将其视为一个以位为单位的数组。

位(Bit)

        Bitmaps中的每个元素都是一个位,值为0或1。

偏移量(Offset)

        每个位都有一个唯一的偏移量(索引),从0开始,并且可以通过命令对这些bit进行设置、清除或者查询等操作。

字符串存储

        Bitmaps实际上是一个字符串,每个字节包含8个位。

1.3、结构原理

如下图所示:


2、常用命令

2.1、SETBIT

setbit:设置指定偏移量的位的值(0或1)。

SETBIT key offset value

setbit mybitmap 0 1  # 设置第0位为1
setbit mybitmap 1 0  # 设置第1位为0

使用:

127.0.0.1:6379> setbit k5 1 1
(integer) 0

127.0.0.1:6379> setbit k5 7 1
(integer) 0

127.0.0.1:6379> setbit k5 9 1
(integer) 0

127.0.0.1:6379> setbit k5 14 1
(integer) 0

127.0.0.1:6379> get k5
"AB"

如下图所示:

2.2、GETBIT

getbit:获取指定偏移量的位的值。

语法:

GETBIT key offset

getbit mybitmap 0  # 获取第0位的值

示例:

127.0.0.1:6379> getbit k5 1
(integer) 1

2.3、BITCOUNT

bitcount:统计指定字节数范围内值为1的位的数量。

语法:

BITCOUNT key [start end]

bitcount mybitmap  # 计算整个位图中1的位数
bitcount mybitmap 0 1  # 计算从第0位到第1位中1的位数

127.0.0.1:6379> bitcount k5 0 1
(integer) 4

127.0.0.1:6379> bitcount k5 0 0
(integer) 2

这里的start和end是指的字节数,而不是二进制位数。

2.4、BITOP

bitop:对多个Bitmaps进行位运算(AND、OR、XOR、NOT),并将结果存储到目标Bitmaps中。

语法:

BITOP operation destkey key [key ...]

127.0.0.1:6379> set k8 A
OK

127.0.0.1:6379> set k9 B
OK

# k8和k9逻辑并,并将结果保存到and89
127.0.0.1:6379> bitop and and89 k8 k9
(integer) 1

127.0.0.1:6379> get and89
"@"

# k8和k9逻辑或,并将结果保存到or89
127.0.0.1:6379> bitop or or89 k8 k9
(integer) 1

127.0.0.1:6379> get or89
"C"

# k8和k9逻辑异或,并将结果保存到xor89
127.0.0.1:6379> bitop xor xor89 k8 k9
(integer) 1

127.0.0.1:6379> get xor89
"\x03"

# 对k8逻辑非,只能接受一个key
127.0.0.1:6379> bitop not not8 k8
(integer) 1

127.0.0.1:6379> get not8
"\xbe"

2.5、BITPOS

bitpos:查找指定范围内第一个值为0或1的位的位置。

语法:

BITPOS key bit [start] [end]


bitpos mybitmap 1  # 查找第一个值为1的位的位置
bitpos mybitmap 0  # 查找第一个值为0的位的位置

127.0.0.1:6379> bitpos k5 1
(integer) 1

127.0.0.1:6379> bitpos k5 0
(integer) 0

3、应用场景

用户在线状态:

        使用Bitmaps记录用户的在线状态,每个用户对应一个偏移量,值为1表示在线,值为0表示离线。

活跃用户统计:

        使用Bitmaps记录每天用户的活跃情况,每天对应一个Bitmap,统计一段时间内的活跃用户数量。

布隆过滤器:

        Bitmaps可以用于实现布隆过滤器,用于快速判断一个元素是否存在于集合中。

用户签到系统:

        可以用一个bit来代表一天内用户是否签到,一年只需要365bits即可记录用户的全年签到情况。

权限控制:

        在一个权限管理系统中,不同的权限点可以用不同的bit表示,然后通过检查对应的bit来判断用户是否有相应权限。

日志分析:

        对于一些特定的日志分析需求,如监控某段时间内的访问模式变化,也可以利用Bitmaps来进行有效跟踪。

数据去重:

        虽然直接用于去重可能不是最佳选择,但在某些情况下,如简单的IP地址过滤等小规模应用中,Bitmaps能够提供足够好的性能与资源消耗平衡。

⚠️注意事项:

        内存占用:位图的最大长度为512MB,即2^32个比特位。Bitmaps的内存占用取决于最大偏移量,而不是实际设置的位数。因此,如果偏移量非常大,可能会占用较多内存。

在设计时应考虑实际业务需求及潜在的数据增长趋势,以避免因单个key过大而导致的问题。

性能:Bitmaps 的位操作非常高效,适合处理大规模数据。

总结


4、使用示例


设置用户在线状态

SETBIT online_users 1001 1
SETBIT online_users 1002 0

获取用户在线状态

GETBIT online_users 1001  # 返回 1
GETBIT online_users 1002  # 返回 0

统计在线用户数量

BITCOUNT online_users  # 返回 1

代码示例:

package com.morris.redis.demo.bitmaps;

import org.redisson.Redisson;
import org.redisson.api.RBitSet;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

/**
 * redisson中bitmaps的使用
 */
public class RedissonBitmapsDemo {
    public static void main(String[] args) {
        // 配置Redisson客户端
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");

        // 创建Redisson客户端实例
        RedissonClient redisson = Redisson.create(config);

        // 表示用户2099年01月的签到记录。
        RBitSet bitSet = redisson.getBitSet("user:sign:209901");

        // 设置第5位为true(用户第5天签到)
        bitSet.set(5, true);

        // 设置第10位为false(用户第10天未签到)
        bitSet.set(10, false);

        // 设置多个位的值(第20天到第25天都签到了)
        bitSet.set(20, 25, true);

        // 获取第五天是否签到
        boolean isSigned = bitSet.get(5); // 返回 true
        System.out.println("the five day is sign: " + isSigned);

        // 本月总签到天数
        long signedDays = bitSet.cardinality();
        System.out.println("total sign days: " + signedDays); // 6

        RBitSet andResult = redisson.getBitSet("user:sign:and");
        andResult.and("user:sign:209901", "user:sign:209902");

        RBitSet orResult = redisson.getBitSet("user:sign:or");
        orResult.and("user:sign:209901", "user:sign:209902");

        RBitSet xorResult = redisson.getBitSet("user:sign:and");
        xorResult.and("user:sign:209901", "user:sign:209902");

        redisson.shutdown();
    }
}

总结:

        Bitmaps 是二进制数据处理的核心工具,其高效的空间利用率和快速的位操作使其在大数据、分布式系统等领域不可或缺。选择位图时需权衡场景需求(如是否需要精确性、动态扩展性),并结合压缩技术(如 Roaring Bitmaps)应对大规模数据挑战。


参考文章:

1、【redis】数据类型之bitmaps_redis的bitmaps-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值