Redis 7.x 系列【11】数据类型之位图(Bitmap)

有道无术,术尚可求,有术无道,止于术。

本系列Redis 版本 7.2.5

源码地址:https://gitee.com/pearl-organization/study-redis-demo

文章目录

    • 1. 概述
    • 2. 基本命令
      • 2.1 SETBIT
      • 2.2 GETBIT
      • 2.3 BITCOUNT
      • 2.4 BITPOS
      • 2.5 BITFIELD
      • 2.6 BITFIELD_RO
      • 2.7 BITOP
    • 3. 应用场景
      • 3.1 用户登录状态
      • 3.2 签到打卡

1. 概述

Redis Bitmap 实际不是一个独立的数据类型,而是基于 String 类型实现的。它主要用于存储二值状态(即集合元素的取值只有 01 两种)。由于每个位只能表示两种状态,在需要快速进行大量数据的排序、查找、去重等操作时具有显著优势。

Bitmap 实际上是利用 String 类型的最大容量(512 MB)存储一个连续的二进制序列。每个字节的 8 位可以分别代表 8 个独立的状态,因此可以用一个 Bitmap 来跟踪多达数百万甚至数十亿的状态。

2. 基本命令

所有命令:

命名描述
BITCOUNT统计给定范围内为1的位的数量
BITFIELD对字符串类型的 key 进行基于位的操作
BITFIELD_RO使用 BITFIELD命令进行只读操作
BITOP执行针对多个 Bitmap 的并集、交集、差集等位操作
BITPOS查找指定位值的第一个位置
GETBIT获取指定偏移量处的位状态
SETBIT设置指定偏移量处的位状态

2.1 SETBIT

SETBIT 命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。时间复杂度为 O(1),因为直接在内存中操作字符串的位表示。返回值为存储在指定偏移量处的原始位值(01)。

基本语法:

SETBIT key offset value

参数说明:

  • key:操作的 key
  • offset:指定偏移量,从 0 开始计数。注意,偏移量必须大于或等于 0 ,且小于 2^32
  • value:设置的值,只能是 01

注意事项:

  • 如果key不存在,会自动为其创建一个新的字符串。
  • 如果设置的偏移量超过了字符串的当前长度,会扩展字符串以确保可以在指定的偏移量处设置值。扩展部分会使用 0 填充。
  • 警告操作:当key 不存在,或者是比较小的字符串时,直接设置 2^32-1 位置时,会立即分配所有内存,这有可能会导致服务阻塞

示例:

# 想设置其偏移量为7的位为1
SETBIT mykey 7 1

2.2 GETBIT

GETBIT 命令是用于获取存储在 key 中的字符串值在指定偏移量上的位(bit)值的操作。返回值是一个整数,表示指定偏移量上的位的值。返回值只可能是 01

基本语法:

GETBIT key offset

示例:

# 获取偏移量为7的位的值
GETBIT mykey 7

2.3 BITCOUNT

BITCOUNT 命令用于统计指定 key 所储存的字符串值中,被设置为1的二进制位的数量。

基本语法:

BITCOUNT key [start] [end]

参数说明:

  • key:要统计的 key ,对应的值应该是一个字符串。
  • start(可选):统计二进制位的开始位置,参数类型为整数,默认从0开始统计。
  • end(可选):统计二进制位的结束位置,参数类型为整数,默认统计到整个字符串的末尾。

注意事项:

  • 如果指定的 key 不存在,会将其视为空字符串,因此返回值为 0
  • 时间复杂度为 O(N),其中N是字符串的长度(以字节为单位)。在处理大数据量时,请注意性能问题。

无参示例:

redis> SET mykey "foobar"  
OK  
redis> BITCOUNT mykey  
(integer) 26

带参示例:

redis> SET mykey "\xff\xf0\x00"  
OK  
redis> BITCOUNT mykey 0 7  
(integer) 12  
redis> BITCOUNT mykey 0 0 4  
(integer) 4  
redis> BITCOUNT mykey 1 1 4  
(integer) 6

2.4 BITPOS

BITPOS 命令用于查找字符串中第一个设置为指定值(01)的 bit 位,并返回该位置。如果没有找到匹配的 bit,则返回-1

基本语法:

BITPOS key bit [start] [end]

参数说明:

  • key:要操作的 key,其值应为一个字符串。
  • bit:要查找的 bit 值,只能是 01
  • start(可选):开始查找的起始位置,默认为 0
  • end(可选):结束查找的位置,默认为 -1 ,表示字符串的最后一个 bit

注意事项:

  • 如果指定的 key 不存在,会将其视为一个空字符串,并查找空字符串中的 bit
  • 如果在指定的范围内没有找到匹配的 bit,则返回 -1
  • 查找范围是基于 bit 的,而不是基于字节的。例如,start=0end=7 表示查找前 8bit,而不是第一个字节。
  • 命令的时间复杂度为 O(N) ,其中 N 是字符串的长度(以 bit 为单位)。在处理大数据量时,请注意性能问题。

假设当前对应的字符串值为"\xff\x00\x00",这是一个二进制字符串的十六进制表示,"\xff"代表8个连续的1"\x00"代表8个连续的0

查找第一个为1bit

BITPOS mykey 1  
(integer) 0

查找第一个为0bit

BITPOS mykey 0 8  
(integer) -1  
BITPOS mykey 0 9  
(integer) 9

2.5 BITFIELD

BITFIELD 允许将 Redis 字符串视为一个位数组,并允许用户对其中的位进行操作,如获取、设置和递增等。对于每个子命令,BITFIELD都会返回一个响应数组,其中每个数组元素都与参数列表中的相应操作相匹配。

基本语法:

BITFIELD key [GET type offset] [SET type offset value] [INCRBY type offset increment] [OVERFLOW wrap|sat|fail]

参数说明:

  • key:要操作的Redis键。
  • GET:用于从字符串中获取指定位置的位域值。
  • SET:用于设置字符串中指定位置的位域值。
  • INCRBY:用于将字符串中指定位置的位域值进行增加。
  • OVERFLOW:用于指定溢出处理方式,可选值有 wrap(回绕)、sat(饱和)和fail(失败)。

子命令GET参数说明:

  • type:指定读取数据的类型,可以是u(无符号整数)或 i(有符号整数)。
  • offset:位字段的起始偏移位置,从0开始计数。

子命令SET参数说明:

  • type:类型标识,可以是u(无符号整数)或 i(有符号整数)。
  • offset:位字段的起始偏移位置。
  • value:要设置的位域值。

子命令INCRBY参数说明:

  • type:指定要递增的数据类型。
  • offset:位字段的起始偏移位置。
  • increment:递增的值。

OVERFLOW用于指定溢出处理方式,参数说明:

  • wrap:使用回绕方法处理溢出,位域超过最大值后再次增加数值则回到最小值。
  • sat:饱和计算,超过最大值再增加则数值仍不变。
  • fail:超过最大值再增加,则命令直接报错,拒绝指定。

注意事项:

  • 可以在同一个命令调用中使用多个子命令,并按照给定的顺序执行它们。
  • 命令的时间复杂度为O(1),用于指定的每个子命令。
  • 使用BITFIELD命令时,请确保对二进制位操作有深入的理解,以避免出现意外的结果。

示例,假设有一个 key 其对应的字符串值为"abcd"(其ASCII码值分别为97, 98, 99, 100)。获取第一个字符的 ASCII 码值(无符号8位整数):

BITFIELD mykey GET u8 0

修改第二个字符的ASCII码值为大写'B'ASCII码值为66):

BITFIELD mykey SET u8 8 66

将第三个字符的ASCII码值增加1'c'变为'd'):

BITFIELD mykey INCRBY u8 16 1

2.6 BITFIELD_RO

BITFIELD_RO 命令作为 BITFIELD 命令的只读变体。这个命令允许用户从二进制位图中安全地读取数据,而不需要担心在只读副本上执行写操作。

基本语法:

BITFIELD_RO key [GET encoding offset [GET encoding offset ...]]

参数说明:

  • key: 要操作的二进制位图的键名。
  • GET: 表示读取操作。
  • encoding: 指定要读取的数据的编码类型(如 u8i8u16i16u32i32u64i64f32f64)。
  • offset: 指示在二进制位图中的起始位置(以位为单位)。

注意事项:

  • 由于原始的 BITFIELD 命令包含 SETINCRBY 等写操作选项,因此它在 Redis 命令表中被标记为写命令。这意味着在 Redis 集群的只读副本上,即使连接处于只读模式,该命令也会被重定向到主实例。
  • 为了在只读副本上允许 BITFIELD 行为而不破坏命令标志的兼容性,Redis 6.2 引入了 BITFIELD_RO 变体。
  • 通过使用 BITFIELD_RO,可以在只读副本上安全地执行读取操作,而无需担心数据的不一致性或其他与写操作相关的问题

示例,假设有一个名为 hello 的二进制位图,并且我们想要从第 16 位开始读取一个 8 位有符号整数(i8):

BITFIELD_RO hello GET i8 16

2.7 BITOP

BITOP 命令用于对多个键(包含字符串值)执行位操作,并将结果存储在目标键中。它支持四种位操作:AND(与)、OR(或)、XOR(异或)和 NOT(非)。NOT 操作是特殊的,因为它只接受一个输入键,因为位反转只作为一元运算符才有意义。

基本语法:

BITOP <AND | OR | XOR | NOT> destkey key [key ...]

参数说明:

  • <AND | OR | XOR | NOT>:要执行的位操作类型。
  • destkey:存储操作结果的目标键。
  • key [key ...]:要参与位操作的键列表。对于 NOT 操作,只需要一个键。

示例:

redis> SET key1 "foobar"  
"OK"  
redis> SET key2 "abcdef"  
"OK"  
redis> BITOP AND dest key1 key2  
(integer) 6  
redis> GET dest  
"`bc`ab"

3. 应用场景

Bitmap 以极小的空间存储大量数据,2^32次方(约40亿)数据只需要约 500MB 内存,并提供了快速的查询和统计功能。Redis Bitmap的应用场景广泛,尤其在处理大量二进制数据或需要快速进行二值状态统计的场合下表现出色。

二值状态统计是指在集合中,元素的取值只有 01 两种状态,在实际开发中,经常会遇到签到/未签到登录/未登录等情况。

常用场景:

  • 签到打卡:每个用户每天的签到情况可以用一个 bit 位表示,签到为1未签到为0
  • 限制IP地址访问频率:每个 IP 地址对应 Bitmap 的一个 bit 位,访问时设置该位为1。判断某个 IP 地址是否已经访问过,并据此限制其访问频率。
  • 用户登录状态:可以使用 bit 位来记录用户的登录状态, 1 表示已登录,0 表示未登录。

3.1 用户登录状态

例如,当天 ID0-3的用户进行了登录:

localhost:0>SETBIT login_status:20240624 0 1
"0"
localhost:0>SETBIT login_status:20240624 1 1
"0"
localhost:0>SETBIT login_status:20240624 2 1
"0"
localhost:0>SETBIT login_status:20240624 3 1
"0"

查看某个用户当天是否登录:

localhost:0>GETBIT login_status:20240624 3
"1"
localhost:0>GETBIT login_status:20240624 4
"0"
localhost:0>

查看当天登录用户总数:

localhost:0>BITCOUNT login_status:20240624
"4"

3.2 签到打卡

在这里插入图片描述
设置 ID123 的用户在 202405 第一天和第六天进行了签到:

localhost:0>SETBIT sign:123:202405 0 1
"0"
localhost:0>SETBIT sign:123:202405 5 1
"0"

查看用户当月某日是否进行了签到:

localhost:0>GETBIT sign:123:202405 10
"0"
localhost:0>GETBIT sign:123:202405 0
"1"

统计当月的签到次数:

localhost:0>BITCOUNT sign:123:202405
"2"

查看当月第一次签到的日期:

localhost:0>BITPOS sign:123:202405 1
"0"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/37499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高端响应式网络科技公司网站源码pbootcms模板

模板介绍 这是一款高端响应式网络科技公司网站源码pbootcms模板&#xff0c;适合所有类型的网络公司展示&#xff0c;整站源码下载&#xff0c;为您简化开发过程&#xff0c;可自适应手机端。 模板截图 源码下载 高端响应式网络科技公司网站源码pbootcms模板

OpenAI禁止中国使用API,国内大模型市场何去何从

GPT-5 一年半后发布&#xff1f;对此你有何期待&#xff1f; 前言 前言&#xff1a; 近日&#xff0c;OpenAI宣布禁止中国用户使用其API&#xff0c;这一决策引起了国内大模型市场的广泛关注。面对这一挑战&#xff0c;国内大模型市场的发展路径和前景成为业界热议的焦点。本…

小时候的子弹击中了现在的我-hive进阶:案例解析(第18天)

系列文章目录 一、Hive表操作 二、数据导入和导出 三、分区表 四、官方文档&#xff08;了解&#xff09; 五、分桶表&#xff08;熟悉&#xff09; 六、复杂类型&#xff08;熟悉&#xff09; 七、Hive乱码解决&#xff08;操作。可以不做&#xff0c;不影响&#xff09; 八、…

Vue3学习笔记<->nginx部署vue项目(3)

安装nginx vue项目通常部署到nginx上&#xff0c;所以先安装一个nginx。为了方便安装的是windows版nginx&#xff0c;解压就能用。 项目参考上一篇文章《Vue3学习笔记&#xff1c;-&#xff1e;创建第一个vue项目》《Vue3学习笔记&#xff1c;-&#xff1e;创建第一个vue项目》…

uniapp启动页面鉴权页面闪烁问题

在使用uni-app开发app 打包完成后如果没有token&#xff0c;那么就在onLaunch生命周期里面判断用户是否登录并跳转至登录页。 但是在app中页面会先进入首页然后再跳转至登录页&#xff0c;十分影响体验。 处理方法&#xff1a; 使用plus.navigator.closeSplashscreen() 官网…

SpringBoot学习05-[SpringBoot的嵌入式Servlet容器]

SpringBoot的嵌入式Servlet容器 嵌入式Servlet容器servlet容器-嵌入式servlet容器配置修改通过全局配置文件修改修改添加实现了WebServerFactoryCustomizer接口的bean来进行修改 servlet容器-注册servlet三大组件 嵌入式Servlet容器 SpringBoot包含对嵌入式Tomcat、Jetty、Und…

嵌入式学习——硬件(ARM体系架构)——day51

1. S3C2440基础知识——一条指令四个字节 1.1 定义 S3C2440 是三星&#xff08;Samsung&#xff09;公司设计的一款基于 ARM920T 核心的微处理器&#xff0c;广泛应用于嵌入式系统中&#xff0c;属于三星的 S3C24xx 系列。 1.2 处理器核心 ARM920T&#xff1a;基于 ARM v5T …

某配送平台未授权访问和弱口令(附赠nuclei默认密码验证脚本)

找到一个某src的子站&#xff0c;通过信息收集插件&#xff0c;发现ZABBIX-监控系统&#xff0c;可以日一下 使用谷歌搜索历史漏洞&#xff1a;zabbix漏洞 通过目录扫描扫描到后台&#xff0c;谷歌搜索一下有没有默认弱口令 成功进去了&#xff0c;挖洞就是这么简单 搜索文章还…

探秘Java版ERP管理系统源码:基于Spring Cloud Alibaba与Spring Boot的微服务架构解析

数字化时代的智能ERP管理系统&#xff1a;引领企业高效管理与创新发展 随着数字化浪潮的席卷&#xff0c;现代企业对于高效、稳定、易于扩展的管理系统需求愈发迫切。为了满足这一需求&#xff0c;我们倾力打造了一款基于Java技术的企业级资源规划&#xff08;ERP&#xff09;…

【ONE·Linux || 高级IO(一)】

总言 主要内容&#xff1a;介绍五种IO模型的基本概念、学习IO多路转接&#xff08;select、poll编程模型&#xff09;。       文章目录 总言1、问题引入1.1、网络通信与IO1.2、五种IO模型1.2.1、举例引入1.2.2、IO模型具体含义介绍1.2.2.1、阻塞式IO1.2.2.2、非阻塞轮询检…

第三节:如何理解Spring的两个特性IOC和AOP(自学Spring boot 3.x第一天)

大家好&#xff0c;我是网创有方&#xff0c;接下来教大家如何理解Spring的两个特性IOC和AOP。本节有点难&#xff0c;大家多理解。 IOC&#xff08;控制反转&#xff09; 定义与核心思想&#xff1a; IOC&#xff0c;全称Inversion of Control&#xff0c;即控制反转。 其核…

把飞书云文档变成HTML邮件:问题挑战与解决历程

一、背景 云文档转HTML邮件 基于公司内部的飞书办公套件&#xff0c;早在去年6月&#xff0c;我们就建设了将飞书云文档转译成HTML邮件的能力&#xff0c;方便同学们在编写邮件文档和发送邮件时&#xff0c;都能有较好的体验和较高的效率。 当下问题 要被邮件客户端识别&am…

防止跨站脚本攻击XSS之Antisamy

目录 一、什么是跨站脚本攻击&#xff08;XSS&#xff09; 二、通常有哪些解决方案 三、常见的XSS攻击例子有哪些 3.1 存储型XSS攻击&#xff08;黑产恶意截流&#xff0c;跳转不法网站&#xff09; 3.2反射型XSS攻击&#xff1a; 四、什么是跨站请求伪造&#xff1f; 五…

这是我见过的大模型 RAG 优化方案与实践最全总结了

暑期实习基本结束了&#xff0c;校招即将开启。 不同以往的是&#xff0c;当前职场环境已不再是那个双向奔赴时代了。求职者在变多&#xff0c;HC 在变少&#xff0c;岗位要求还更高了。提前准备才是完全之策。 最近&#xff0c;我们又陆续整理了很多大厂的面试题&#xff0c…

软件工程 例题

用例图 1. 某个学生成绩管理系统的部分参与者和用例总结如下。 教务管理人员: 登录系统教师、学生名单管理学期教学计划管理成绩管理。课程分配&#xff0c;每次课程分配时都必须打印任课通知书 学生&#xff1a; 登录系统选课。 教师: 登录系统成绩管理&#xff0c;并…

Query Rewriting for Retrieval-Augmented Large Language Models

文章目录 题目摘要方法实验 题目 检索增强大语言模型的查询重写 论文地址&#xff1a;https://arxiv.org/abs/2305.14283 项目地址&#xff1a;https://github.com/xbmxb/RAG-query-rewriting 摘要 大语言模型&#xff08;LLM&#xff09;在检索--然后阅读&#xff08;retriev…

百度智能云升级:接入33个大模型,Llama 2引领创新,103个Prompt模板上线

大家好&#xff0c;我是herosunly。985院校硕士毕业&#xff0c;现担任算法研究员一职&#xff0c;热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名&#xff0c;CCF比赛第二名&#xff0c;科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的…

鉴源实验室·基于MQTT协议的模糊测试研究

作者 | 张渊策 上海控安可信软件创新研究院工控网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 随着物联网技术的快速发展&#xff0c;越来越多的设备加入到互联网中&#xff0c;形成了庞大的物联网系统。这些设备之间的通信…

2024年每个月有哪些数学建模和数学挖掘竞赛?

文章目录 2024年每个月有哪些竞赛&#xff1f;2024年32个数学建模和数据挖掘竞赛重磅来袭&#xff01;&#xff01;&#xff01;2024年数学建模和数学挖掘竞赛时间目录汇总数学建模助手使用一月二月三月四月五月六月七月八月九月十月十一月十二月 原文&#xff1a;https://blog…

最新!最全!元启发优化算法215个测试函数综述!【免费获取论文】

目录 1.摘要2.主要内容3.参考文献4.文章获取 1.摘要 这篇综述论文旨在利用对不同基准测试函数的研究&#xff0c;评估元启发优化算法(Metaheuristic optimization algorithms, MH)的性能。MH的性能是通过不同的数学基准测试函数和各种实际工程设计问题来评估&#xff0c;这些基…