目录
SETBIT" >SETBIT
GETBIT" >GETBIT
BITCOUNT" >BITCOUNT
BITPOS" >BITPOS
BITOP" >BITOP
应用场景" >应用场景
用户行为记录器
用户上线统计
首页 数据库 Redis 深入浅析Redis中的位图(bitmap)

深入浅析Redis中的位图(bitmap)

Dec 02, 2021 am 10:17 AM
redis 位图

本篇文章带大家了解一下Redis中的位图(bitmap),希望对大家有所帮助!

深入浅析Redis中的位图(bitmap)

Redis 的位图(bitmap)是由多个二进制位组成的数组,数组中的每个二进制位都有与之对应的偏移量(从 0 开始),通过这些偏移量可以对位图中指定的一个或多个二进制位进行操作。【相关推荐:Redis视频教程

实际上,位图并不是 Redis 提供的一种新的数据类型,它是字符串类型的扩展。所以位图的命令可以直接使用在字符串类型的键上,位图命令操作的键也可以被字符串类型命令操作。

比如,现有一个字符串键 foo:

redis> set foo bar
登录后复制

1 个字节由 8 个二进制位组成,所以 foo 键的二进制形式就是:

1.png

SETBIT

通过 SETBIT 命令,可以为位图指定偏移量上的二进制位设置值,offset 必须大于等于 0,value 只能是 0 或 1。此命令的时间复杂度是 O(1)。

SETBIT key offset value

SETBIT 命令在对二进制位进行设置之后,将返回二进制位被设置之前的旧值作为结果。

假设现在想把 bar 变为 aar,只需如下两步操作:

redis> setbit foo 6 0
(integer) 1
redis> setbit foo 7 1
(integer) 0
redis> get foo"aar"
登录后复制

当执行 SETBIT 命令尝试对一个位图进行设置的时候,如果位图不存在,或者位图当前的大小无法满足,Redis 将对被设置的位图进行扩展,并将所有未被设置的二进制位的值初始化为 0。比如:

redis> setbit far 10 1
登录后复制

由于 far 并不存在,所以 Redis 会将 0~9 的二进制位设置为 0,因为 Redis 对位图的扩展操作是以字节为单位进行的,所以实际上 far 一共有 16 个二进制位,并不是 10 个,且 11~15 的二进制位也是 0。

基于这种情况,当指定的二进制位偏移量过大时,Redis 需要一次性分配完所有内存,这可能会造成 Redis 服务器阻塞。比如存储用户的性别,1 代表男性,0 代表女性,使用 ID 作为二进制偏移量,如果 ID 从 10000000001 开始的,就需要将用户 ID 减去 10000000000 再进行存储,否则会造成内存浪费。

GETBIT

使用 GETBIT 命令可以获取位图指定偏移量上的二进制位的值。此命令的时间复杂度是 O(1)。

GETBIT key offset

如果输入的偏移量超过了位图目前拥有的最大偏移量,将返回 0 作为结果。

BITCOUNT

通过 BITCOUNT 命令可以统计位图中值为 1 的二进制位数量。此命令的时间复杂度是 O(n)。

BITCOUNT key [start end]

在默认情况下,BITCOUNT 命令对位图包含的所有字节中的二进制位进行统计,也可以通过可选的 start 参数和 end 参数,让 BITCOUNT 只对指定字节范围内的二进制位进行统计(不是二进制偏移量)。比如,希望统计 ar 两个字节中值为 1 的二进制数量:

redis> bitcount foo 1 2
(integer) 7
登录后复制

start 和 end 参数也支持使用负数索引,下方的用法与上方的等效:

redis> bitcount foo -2 -1
(integer) 7
登录后复制

BITPOS

通过执行 BITPOS 命令,在位图中查找第一个被设置为指定值的二进制位,并返回这个二进制位的偏移量。

BITPOS key value [start end]

BITPOS 也接受可选的 start 参数和 end 参数,让 BITPOS 命令只在指定字节范围内的二进制位中进行查找。

redis> get foo"aar"redis> bitpos foo 1
(integer) 1
redis> bitpos foo 0
(integer) 0
redis> bitpos foo 0 1 2
(integer) 8
redis> bitpos foo 1 1 2
(integer) 9
redis> bitpos foo 1 -1 -1
(integer) 17
登录后复制

针对边界的处理:

  • 当尝试对一个不存在的位图或者一个所有位都被设置成了 0 的位图中查找值为 1 的二进制位时,BITPOS 命令将返回 -1 作为结果。
  • 如果在一个所有位都被设置成 1 的位图中查找值为 0 的二进制位,那么 BITPOS 命令将返回位图最大偏移量加上 1 作为结果

BITOP

通过 BITOP 命令,对一个或多个位图执行指定的二进制位运算,并将运算结果存储到指定的键中。

BITOP operation destkey key [key ...]

operation 参数的值可以是 AND、OR、XOR、NOT 中的任意一个,这 4 个值分别对应逻辑并、逻辑或、逻辑异或和逻辑非 4 种运算,其中 AND、OR、XOR 这 3 种运算允许用户使用任意数量的位图作为输入,而 NOT 运算只允许使用一个位图作为输入。BITOP 命令在将计算结果存储到指定键中之后,会返回被存储位图的字节长度。

当 BITOP 命令在对两个长度不同的位图执行运算时,会将长度较短的那个位图中不存在的二进制位的值看作 0。

redis> set foo1 bar
OK
redis> set foo2 aar
OK
redis> bitop or res foo1 foo2
(integer) 3
redis> get res"car"
登录后复制

2.png

注意:BITOP 可能是一个缓慢的命令,它的时间复杂度是 O(N),在处理长字符串时应注意一下效率问题。

应用场景

用户行为记录器

用用户 ID 作为偏移量,若用户做了某种行为则通过 SETBIT 将二进制位设置为 1,通过 GETBIT 判断用户是否做了某种行为,通过 BITCOUNT 可以知道有多少用户执行了行为。

用户上线统计

可以使用 SETBIT 和 BITCOUNT 来实现,以用户 ID 作为 key ,假设今天是上线统计功能开放的第一天,ID 为 1 的用户上线后就通过 SETBIT 1 0 1。当要计算此用户的总共以来的上线次数时,使用 BITCOUNT 命令就可以得出的结果。

使用这种方式存储数据,即使 10 年后,1个用户就只占用几百字节的内存,它的处理速度依然很快。如果 bitmap 数据比较大,建议将 bitmap 拆分成多个小的 bitmap 分别进行处理。

更多编程相关知识,请访问:编程入门!!

以上是深入浅析Redis中的位图(bitmap)的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

redis集群模式怎么搭建 redis集群模式怎么搭建 Apr 10, 2025 pm 10:15 PM

Redis集群模式通过分片将Redis实例部署到多个服务器,提高可扩展性和可用性。搭建步骤如下:创建奇数个Redis实例,端口不同;创建3个sentinel实例,监控Redis实例并进行故障转移;配置sentinel配置文件,添加监控Redis实例信息和故障转移设置;配置Redis实例配置文件,启用集群模式并指定集群信息文件路径;创建nodes.conf文件,包含各Redis实例的信息;启动集群,执行create命令创建集群并指定副本数量;登录集群执行CLUSTER INFO命令验证集群状态;使

redis底层怎么实现 redis底层怎么实现 Apr 10, 2025 pm 07:21 PM

Redis 使用哈希表存储数据,支持字符串、列表、哈希表、集合和有序集合等数据结构。Redis 通过快照 (RDB) 和追加只写 (AOF) 机制持久化数据。Redis 使用主从复制来提高数据可用性。Redis 使用单线程事件循环处理连接和命令,保证数据原子性和一致性。Redis 为键设置过期时间,并使用 lazy 删除机制删除过期键。

redis怎么查看所有的key redis怎么查看所有的key Apr 10, 2025 pm 07:15 PM

要查看 Redis 中的所有键,共有三种方法:使用 KEYS 命令返回所有匹配指定模式的键;使用 SCAN 命令迭代键并返回一组键;使用 INFO 命令获取键的总数。

redis-server找不到怎么办 redis-server找不到怎么办 Apr 10, 2025 pm 06:54 PM

解决redis-server找不到问题的步骤:检查安装,确保已正确安装Redis;设置环境变量REDIS_HOST和REDIS_PORT;启动Redis服务器redis-server;检查服务器是否运行redis-cli ping。

redis指令怎么用 redis指令怎么用 Apr 10, 2025 pm 08:45 PM

使用 Redis 指令需要以下步骤:打开 Redis 客户端。输入指令(动词 键 值)。提供所需参数(因指令而异)。按 Enter 执行指令。Redis 返回响应,指示操作结果(通常为 OK 或 -ERR)。

redis怎么读取队列 redis怎么读取队列 Apr 10, 2025 pm 10:12 PM

要从 Redis 读取队列,需要获取队列名称、使用 LPOP 命令读取元素,并处理空队列。具体步骤如下:获取队列名称:以 "queue:" 前缀命名,如 "queue:my-queue"。使用 LPOP 命令:从队列头部弹出元素并返回其值,如 LPOP queue:my-queue。处理空队列:如果队列为空,LPOP 返回 nil,可先检查队列是否存在再读取元素。

redis怎么启动服务器 redis怎么启动服务器 Apr 10, 2025 pm 08:12 PM

启动 Redis 服务器的步骤包括:根据操作系统安装 Redis。通过 redis-server(Linux/macOS)或 redis-server.exe(Windows)启动 Redis 服务。使用 redis-cli ping(Linux/macOS)或 redis-cli.exe ping(Windows)命令检查服务状态。使用 Redis 客户端,如 redis-cli、Python 或 Node.js,访问服务器。

redis怎么读源码 redis怎么读源码 Apr 10, 2025 pm 08:27 PM

理解 Redis 源码的最佳方法是逐步进行:熟悉 Redis 基础知识。选择一个特定的模块或功能作为起点。从模块或功能的入口点开始,逐行查看代码。通过函数调用链查看代码。熟悉 Redis 使用的底层数据结构。识别 Redis 使用的算法。

See all articles