Redis特殊数据类型:Bitmap

Bitmap

一、类型概述

Bitmap(位图),也称为 Bit array(位数组)或 Bitset(位集合),并不是一种单独的数据结构,而是基于 Redis 的 String 类型实现的一种"位级别"的操作方式。

你可以把它想象成一个由 01 组成的数组,数组的每个单元只能存储 01,数组的索引(在 Redis 中称为 offset)从 0 开始。

核心要点:

  • 底层是 String:Bitmap 的本质是一个 String 值,它对应的是一个二进制的字节串。所以,所有针对 Bitmap 的命令,本质上都是对字符串值的二进制位进行操作。
  • 自动扩容:当你设置一个偏移量很大的位时,Redis 会自动分配内存并将中间未设置的位全部初始化为 0。
  • 极其节省空间:通过位来存储信息,一个字节(8 bits)可以存储 8 个独立的状态。例如,存储 1 亿用户的在线状态,只需要大约 12MB 的内存(1亿 / 8 / 1024 / 1024 ≈ 11.92MB)。

二、基本方法

1. 设置位值 SETBIT key offset value

bash 复制代码
127.0.0.1:6379> setbit log 0 1
(integer) 0  #返回指定偏移量原来存储的位,没有默认为0。
127.0.0.1:6379> setbit log 1 1
(integer) 0
127.0.0.1:6379> setbit log 2 1
(integer) 0
127.0.0.1:6379> setbit log 3 0
(integer) 0

2. 获取位值 GETBIT key offset

bash 复制代码
127.0.0.1:6379> getbit log 2
(integer) 1

3. 统计 BITCOUNT key [start end]

startend字节索引,而不是位索引。可以使用负数值,-1 表示最后一个字节,-2 表示倒数第二个字节。

bash 复制代码
127.0.0.1:6379> bitcount log  
(integer) 3  #位值位1的有三个

三、内部实现

正如概述中所说,Bitmap 的底层实现就是 Redis 的 String 数据类型。String 在 Redis 内部是以二进制安全的字节数组形式存储的。

当你执行 SETBIT key 10 1 时:

  1. Redis 会找到或创建一个与 key 关联的字符串值。
  2. 它会计算出第 10 位位于哪个字节(第 10 / 8 = 1 个字节,索引从 0 开始)以及在该字节中的哪一位(第 10 % 8 = 2 位)。
  3. 然后,它通过位运算(如按位或 | 和按位与 &)来设置或清除该特定位的值。
  4. 如果目标偏移量超出了当前字符串的长度,Redis 会扩展字符串,并用零字节填充中间的空隙。

四、应用场景

Bitmap 因其极致的空间效率和快速的位运算,在特定场景下表现非常出色。

1. 用户行为标记

这是最经典的应用场景。

  • 用户签到key 可以设计为 user:sign:202405:{uid},一位代表一天。SETBIT user:sign:202405:1001 20 1 表示用户 1001 在 5 月 21 日签到了。
  • 用户在线状态key 可以设计为 user:online:20240520,一位代表一个用户。SETBIT user:online:20240520 1001 1 表示用户 1001 今天在线。

2. 大数据量下的布尔统计

  • 活跃用户分析 :如上例,可以轻松统计每日活跃用户数(BITCOUNT)。通过 BITOP AND/OR,可以计算:

    • 连续活跃用户BITOP AND
    • 某段时间内的活跃用户BITOP OR
  • 特征标签筛选 :可以为每个特征(如"男性"、"喜欢编程"、"VIP用户")创建一个 Bitmap,每一位表示一个用户是否具有此特征。通过 BITOP AND 可以快速找到同时满足多个特征的用户群。

3. 布隆过滤器

Bitmap 是实现布隆过滤器的核心数据结构。布隆过滤器是一种概率型数据结构,用于高效地判断一个元素是否存在于一个集合中。它可能存在误判(判断一个不存在的元素为存在),但绝不会漏判(判断存在的元素一定存在),并且非常节省空间。

相关推荐
程序员三明治4 小时前
选 Redis Stream 还是传统 MQ?队列选型全攻略(适用场景、优缺点与实践建议)
java·redis·后端·缓存·rocketmq·stream·队列
梦子yumeko10 小时前
第五章Langchain4j之基于内存和redis实现聊天持久化
数据库·redis·缓存
半旧夜夏11 小时前
【分布式缓存】Redis持久化和集群部署攻略
java·运维·redis·分布式·缓存
哦你看看14 小时前
Redis Sentinel哨兵集群
linux·redis·bootstrap·sentinel
陈果然DeepVersion16 小时前
Java大厂面试真题:Spring Boot微服务+Kafka消息队列+AIGC场景实战问答全解析
spring boot·redis·微服务·kafka·消息队列·aigc·java面试
小丁爱养花19 小时前
Redis - set & zset (常用命令/内部编码/应用场景)
数据库·redis·缓存
大G的笔记本20 小时前
用 Redis 的 List 存储库存队列,并通过 LPOP 原子性出队来保证并发安全案例
java·数据库·redis·缓存
緣木求魚21 小时前
redis事务与Lua脚本
数据库·redis·lua
切糕师学AI1 天前
C# 使用 CSRedisCore指南
redis·c#·.net core
代码哈士奇1 天前
Nestjs+nacos+kafka搭建中后台系统-后端(持续更新中)
redis·分布式·微服务·nacos·kafka·nestjs·pgsql