首页 数据库 Redis 如何使用redis的bit位操作

如何使用redis的bit位操作

May 26, 2023 pm 02:14 PM
redis bit

本文redis试验代码基于如下环境:

操作系统:Mac OS 64位

版本:Redis 5.0.7 64 bit

运行模式:standalone mode

redis位操作

reids位操作也叫位数组操作、bitmap,它提供了SETBIT、GETBIT、BITCOUNT、BITTOP四个命令用于操作二进制位数组。

先来看一波基本操作示例

如何使用redis的bit位操作

SETBIT

语法:SETBIT key offset value

即:命令 key 偏移量 0/1

setbit命令用于写入位数组指定偏移量的二进制位设置值,偏移量从0开始计数,且只允许写入1或者0,如果写入非0和1的值则写入失败:

如何使用redis的bit位操作

GETBIT

语法:GETBIT key offset

即:命令 key 偏移量

gitbit命令用于获取位数组指定偏移量上的二进制值:

如何使用redis的bit位操作

BITCOUNT

语法:BITCOUNT key

即:命令 key

bitcount命令用于获取指定key的位数组中值为1的二进制位的数量,之前我们写入了偏移量0的值为1,偏移量10 的值为1,偏移量8的值为0:

如何使用redis的bit位操作

BITOP

语法:BITOP operation destkey key [key...]

即:命令 操作 结果目标key key1 key2 ...

bitop命令可以对多个位数组的key进行and(按位与)、or(按位或)、xor(按位异或)运算,并将运算结果设置到destkey中:

如何使用redis的bit位操作

底层数据结构分析

SDS是redis中的一种数据结构,叫做简单动态字符串(Simple Dynamic String),并且它是一种二进制安全的,在大多数的情况下redis中的字符串都用SDS来存储。

SDS的数据结构:

struct sdshdr {   #记录buff数组中已使用字节的数量   #也是SDS所保存字符串的长度   int len;   #记录buff数组中未使用字节的数量   int free;   #字节数组,字符串就存储在这个数组里   char buff[];  }
登录后复制

数据存储示例:

如何使用redis的bit位操作

图片来源《redis设计与实现》

SDS的优点:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2.  时间复杂度为O(1)

  3.  杜绝缓冲区溢出

  4.  减少修改字符串长度时候所需的内存重分配次数

  5.  二进制安全的API操作

  6.  兼容部分C字符串函数

关于SDS的详细介绍请大家参阅《redis设计与实现》一文。

redis中的位数组采用的是String字符串数据格式来存储,而字符串对象使用的正是上文说的SDS简单动态字符串数据结构。

如何使用redis的bit位操作

图片来源《redis设计与实现》

大家都知道的是一个字节用的是8个二进制位来存储的,也就是8个0或者1,即一个字节可以存储十进制0~127的数字,也即包含了所有的数字、英文大小写字母以及标点符号。

1Byte=8bit

1KB=1024Byte

1MB=1024KB

1GB=1024MB

位数组在redis存储世界里,每一个字节也是8位,初始都是:

0 0 0 0 0 0 0 0
登录后复制

而位操作就是在对应的offset偏移量上设置0或者1,比如将第3位设置为1,即:

0 0 0 0 1 0 0 0  #对应redis操作即:  setbit key 3 1
登录后复制

在此基础上,如果要在偏移量为13的位置设置1,即:

setbit key 13 1  #对应redis中的存储为:  0 0 1 0 | 0 0 0 0 | 0 0 0 0 | 1 0 0 0
登录后复制

时间复杂度

GETBIT命令时间复杂度O(1)

STEBIT命令时间复杂度O(1)

BITCOUNT命令时间复杂度O(n)

BITOP命令时间复杂度O(n)、O(n2)

我们来看GETBIT以及SETBIT命令的时间复杂度为什么是O(1),当我们执行一个SETBIT key 10086 1的值的时候,reids的计算方式如下:

获取到要写入位数组中的哪个字节:10086÷8=1260,需要写入到位数组的下标1260的字节

获取要写入到这个字节的第几位:10086 mod 8 = 6,需要写入到这个字节的下标为6即第7位上去。

通过这两种计算方式大家可以清晰的看到,位操作的GETBIT和SETBIT都是常量计算,因此它的时间复杂度为O(1)。

而BITCOUNT命令需要对整个位数组的所有元素进行遍历算出值为1的有多少个,当然redis对于大数据了的bit执行bitcount命令会有一整套复杂的优化的算法,但是核心思路还是这个意思,无非是减少部分遍历查询次数。如果明确以128位为一次遍历,那么他需要遍历的次数就等于所有位数除以128。

BITTOP命令则是根据不同的操作有不同的执行方式。比如AND操作,则需要查看位值为1的即可。

存储空间计算

根据以上介绍,我们可以知道如何计算使用基于Redis的位数组数据结构存储数据所占用的内存大小。比如有100亿的数据,那么它需要的字节数组:

1000000000÷8÷1024÷1024≈119.21MB

也就是存储10亿的数据只需要119MB左右的内存空间,这对于现在动辄16G、32G集群版的redis,完全没有问题。

需要注意的是,如果你的数据量不大,那就不要把起始偏移量搞的很大,这样也是占空间的,比如我们只需要存储几百条数据,但是其中的偏移量却很大,这就会造成了很大的内存空间浪费。

应用场景

实际项目开发中有很多业务都适合采用redis的bit来实现。

用户签到场景

每天的日期字符串作为一个key,用户Id作为offset,统计每天用户的签到情况,总的用户签到数

活跃用户数统计

用户日活、月活、留存率等均可以用redis位数组来存储,还是以每天的日期作为key,用户活跃了就写入offset为用户id的位值1。

同理月活也是如此。

用户是否在线以及总在线人数统计

使用相同的位数组,将用户ID映射的位偏移量设置为1表示在线,设置为0表示离线。即可实现用户上下线查询和总在线人数的统计

APP内用户的全局消息提示小红点

现在大多数的APP里都有站内信的功能,当有消息的时候,则提示一个小红点,代表用户有新的消息。

以上是如何使用redis的bit位操作的详细内容。更多信息请关注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.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.聊天命令以及如何使用它们
1 个月前 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 10:06 PM

如何清空 Redis 数据:使用 FLUSHALL 命令清除所有键值。使用 FLUSHDB 命令清除当前选定数据库的键值。使用 SELECT 切换数据库,再使用 FLUSHDB 清除多个数据库。使用 DEL 命令删除特定键。使用 redis-cli 工具清空数据。

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

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

redis怎么使用单线程 redis怎么使用单线程 Apr 10, 2025 pm 07:12 PM

Redis 使用单线程架构,以提供高性能、简单性和一致性。它利用 I/O 多路复用、事件循环、非阻塞 I/O 和共享内存来提高并发性,但同时存在并发性受限、单点故障和不适合写密集型工作负载的局限性。

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

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

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

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

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:39 PM

使用Redis进行锁操作需要通过SETNX命令获取锁,然后使用EXPIRE命令设置过期时间。具体步骤为:(1) 使用SETNX命令尝试设置一个键值对;(2) 使用EXPIRE命令为锁设置过期时间;(3) 当不再需要锁时,使用DEL命令删除该锁。

See all articles