Redis位图

简介

在我们平时开发过程中,会有一些bool型数据需要存取,比如用户一年的签到记录,签了是1,没签是0,要记录365天。如果使用普通的key/value,每个用户要记录365个,当用户上亿的时候,需要的存储空间是惊人的。

为了解决这个问题,Redis提供了位图数据结构,这样每天的签到记录只占据一个位,365天就是365个位,46个字节(一个稍长一点的字符串)就可以完全容纳,这就大大节约了存储空间。

位图不是特殊的数据结构,他的内容其实就是普通的字符串,也就是byte数组。我们可以使用普通的get/set直接获取和设置整个位图的内容,也可以使用位图操作getbit/setbit等将byte数组看成【位数组】来处理。

基本使用

Redis的位数组是自动扩展,如果设置了某个偏移位置超出了现有的内容范围,就会自动将位数组进行零扩充。如下图所示位“he”的ASCII码,使用redis-cli设置第一个字符,也就是位数组的前8位,如下图所示,h字符只有1/2/4位需要设置,e字符只有9/10/13/15位需要设置。值的注意的是位数组的顺序和字符的位顺序是相反的。
在这里插入图片描述
redis-cli示例

127.0.0.1:6379> setbit s 1 1 
(integer) 0
127.0.0.1:6379> setbit s 2 1 
(integer) 0
127.0.0.1:6379> setbit s 4 1 
(integer) 0
127.0.0.1:6379> setbit s 9 1 
(integer) 0
127.0.0.1:6379> setbit s 10 1 
(integer) 0
127.0.0.1:6379> setbit s 13 1 
(integer) 0
127.0.0.1:6379> setbit s 15 1 
(integer) 0
127.0.0.1:6379> get s
"he"

上面这个例子可以理解为【零存整取】,同样我们还可以【零存零取】,【整存零取】。【零存】就是使用setbit对位值进行逐个设置,【整存】就是使用字符串一次性填充所有位数组,覆盖掉旧值。

零存零取

127.0.0.1:6379> setbit w 1 1 
(integer) 0
127.0.0.1:6379> setbit w 2 1 
(integer) 0
127.0.0.1:6379> setbit w 4 1 
(integer) 0
127.0.0.1:6379> getbit w 1 
(integer) 1
127.0.0.1:6379> getbit w 2 
(integer) 1 
127.0.0.1:6379> getbit w 4 
(integer) 1 
127.0.0.1:6379> getbit w 5 
(integer) 0

整存零取

127.0.0.1:6379> set w h # 整存 (integer) 0
127.0.0.1:6379> getbit w 1 
(integer) 1
127.0.0.1:6379> getbit w 2 
(integer) 1 
127.0.0.1:6379> getbit w 4 
(integer) 1 
127.0.0.1:6379> getbit w 5 
(integer) 0

如果对应位的字节是不可打印字符,redis-cli会显示该字符的16进制形式。

127.0.0.1:6379> setbit x 0 1 
(integer) 0
127.0.0.1:6379> setbit x 1 1 
(integer) 0
127.0.0.1:6379> get x 
"\xc0"

统计和查找

Redis提供了位图统计指令bitcount和位图查找指令bitpos,bitcount是用来统计指定位置范围内1的个数,bitpos用来查找指定范围内出现的第一个0或1.

比如我们可以通过bitcount统计用户一共签到了多少天,通过bitpos指令查找用户从哪一天开始签到,如果指定了范围参数[start,end],就可以统计在某个时间范围内用户签到了多少天,用户自某天以后的哪天开始签到。

注意,start和end是字节索引,8个bit为一字节,如图中的“he”字符串,对应的ASCII码为 01101000 01100101,其中第0字节为01101000,第一个字节为01100101。因此,如果要计算某个月内用户签到了多少天,无法直接计算得出,而是需要讲这个月所覆盖的字节内容全部取出,然后在内存里进行统计。

示例:

127.0.0.1:6379> set w he 
OK
127.0.0.1:6379> bitcount w 
(integer) 7
127.0.0.1:6379> bitcount w 0 0 # 第一个字节中 1 的位数 
(integer) 3
127.0.0.1:6379> bitcount w 0 1 # 前两个字节中 1 的位数
(integer) 7
127.0.0.1:6379> bitcount w 1 1 # 第二个字节中 1 的位数
(integer) 4
127.0.0.1:6379> bitpos w 0 # 第一个 0 位 
(integer) 0
127.0.0.1:6379> bitpos w 1 # 第一个 1 位 
(integer) 1
127.0.0.1:6379> bitpos w 1 1 1 # 从第二个字符算起,第一个 1 位
(integer) 9

魔术指令bitfield

前文我们设置(setbit)和获取(getbit)指定位的值都是单个位的,如果要一次操作多个位,就必须使用管道来处理。bitfield有三个子指令,分别是get/set/incrby,他们都可以对指定位片段进行读写,但是最多只能处理64个连续的位,如果超过64位,就需要使用多个子指令,bitfield可以一次执行多个子指令。

仍然使用上面的例子,“he”对应的ASCII码表示
在这里插入图片描述

127.0.0.1:6379> set w hello
OK
127.0.0.1:6379> bitfield w get u4 0 # 从第一个位开始取 4 个位,结果是无符号数 (u)
(integer) 6
127.0.0.1:6379> bitfield w get u3 2 # 从第三个位开始取 3 个位,结果是无符号数 (u)
(integer) 5
127.0.0.1:6379> bitfield w get i4 0  # 从第一个位开始取 4 个位,结果是有符号数 (i) 
(integer) 6
127.0.0.1:6379> bitfield w get i3 2# 从第三个位开始取 3 个位,结果是有符号数 (i)
(integer) -3

所谓有符号数指获取的位数组中第一个位是符号位,剩下的都是值。如果第一位是1,那就是负数。无符号数表示非负数,没有符号位,获取的位数组全部都是值。有符号数最多可以获取64位,无符号数只能获取63位。如果超出位数限制,Redis会提示参数错误。

一次执行多个指令示例

127.0.0.1:6379> bitfield w get u4 0 get u3 2 get i4 0 get i3 2 
1) (integer) 6
2) (integer) 5
3) (integer) 6
4) (integer) -3

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

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

相关文章

本地知识库开源框架Fastgpt、MaxKB产品体验

本地知识库开源框架Fastgpt、MaxKB产品体验 背景fastgpt简介知识库共享部署 MaxKB总结 背景 上一篇体验了Quivr、QAnything两个开源知识库模型框架,这次介绍两款小众但是体验比较好的产品。 fastgpt 简介 FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&am…

kubeedge v1.17.0部署教程

文章目录 前言一、安装k8s平台二、部署kubeedge1.部署MetalLB(可选)2.cloud3.edge4. 部署nginx到edge端 总结参考 前言 本文主要介绍kubeedge v1.17.0的安装过程 主要环境如下表 应用版本centos7.0k8s1.28.2kubeedge1.17.0docker24.0.8centos7.0 一、安装k8s平台 本文主要参…

大数据学习问题记录

问题记录 node1突然无法连接finalshell node1突然无法连接finalshell 今天我打开虚拟机和finalshell的时候,发现我的node1连接不上finalshell,但是node2、node3依旧可以链接,我在网上找了很多方法,但是是关于全部虚拟机连接不上finalshell&a…

跨域请求解决方法----不允许有多个 ‘Access-Control-Allow-Origin‘ CORS 头

后端配置了代码: spring:application:name: spzx-server-gatewaycloud:nacos:discovery:server-addr: localhost:8848gateway:discovery:locator:enabled: trueglobalcors:cors-configurations:[/**]:allowedOriginPatterns: "*"# 允许请求中携带的头信息…

【Linux系统】进程信号

本篇博客整理了进程信号从产生到处理的过程细节,通过不同过程中的系统调用和其背后的原理,旨在让读者更深入地理解操作系统的设计与软硬件管理手段。 目录 一、信号是什么 1.以生活为鉴 2.默认动作与自定义动作 3.信号的分类、保存、产生 二、产生…

JavaWeb1 Json+BOM+DOM+事件监听

JS对象-Json //Json 字符串转JS对象 var jsObject Json.parse(userStr); //JS对象转JSON字符串 var jsonStr JSON.stringify(jsObject);JS对象-BOM BOM是浏览器对象模型,允许JS与浏览器对话 它包括5个对象:window、document、navigator、screen、hi…

Linux漏洞SSL/TLS协议信息泄露漏洞(CVE-2016-2183) - 非常危险(7.5分) 解决办法!升级openssl

漏洞情况 详细描述 TLS是安全传输层协议,用于在两个通信应用程序之间提供保密性和数据完整性。 TLS, SSH, IPSec协商及其他产品中使用的IDEA、DES及Triple DES密码或者3DES及 Triple 3DES存在大约四十亿块的生日界,这可使远程攻击者通过Sweet32攻击&…

俄罗斯人有哪些常用的口头禅,柯桥零基础俄语培训

Хватит! 够了! -Хватит, не стоит больше шуметь! 够了, 不要再吵了! -Это тебя не касается! 这与你无关! Блин! 靠! Блин这个词绝对是俄罗斯人最爱用的口语表达之一,…

【文档智能】符合人类阅读顺序的文档模型-LayoutReader原理及权重开源

引言 阅读顺序检测旨在捕获人类读者能够自然理解的单词序列。现有的OCR引擎通常按照从上到下、从左到右的方式排列识别到的文本行,但这并不适用于某些文档类型,如多栏模板、表格等。LayoutReader模型使用seq2seq模型捕获文本和布局信息,用于…

Vue——组件数据传递与props校验

文章目录 前言组件数据传递的几种类型简单字符串类型数据专递其他类型数据(数字、数组、对象)传递注意事项 数据传递值校验限定数据类型 type给定默认值 default指定必选项 required 前言 组件与组件之间并不是完全独立的,他们之间可以进行一些数据的传递操作。传递…

HarmonyOS应用开发学习历程(1)初识DevEco Studio

1.create project Bundle name:包名,标识应用程序,默认应用ID也使用该名 Compile SDK:编译时API版本 2.工程目录 AppScope:应用全局所需资源 entry:应用的主模块,含代码、资源 hvigor&#…

产品经理的AI大模型实战指南:驾驭未来,引领创新

前言: 在数字化浪潮席卷全球的今天,AI大模型正以其惊人的潜力和速度,重塑着各行各业的生态。对于产品经理而言,如何在这场变革中站稳脚跟,甚至引领潮流,成为了一个亟待解决的问题。为此,我们特…

使用`War`包部署`Jenkins`(超级详细)

使用War包部署Jenkins(超级详细) 别着急,你看这年复一年,春光不必趁早,冬霜不会迟到。过去的都会过去,该来的都在路上,一切都是刚刚好。 网站说明 https://get.jenkins.io/war-stable/ war包下载地址 https://www.jenk…

云端狂飙:Django项目部署与性能优化的极速之旅

Hello,我是阿佑,这次阿佑将手把手带你亲自踏上Django项目从单机到云端的全过程,以及如何通过Docker实现项目的无缝迁移和扩展。不仅详细介绍了Docker的基本概念和操作,还深入探讨Docker Compose、Swarm和Kubernetes等高级工具的使…

【C语言】文件操作(下卷)

前言 在上一卷中,我们知道了文件指针、文件的打开和关闭(打开其他位置的文件)、文件的顺序读写(其中的fputc()、fgetc()),这一卷中,将继续讲解文件操作未讲到的地方。 内容有点多,…

如何在 Java 中使用 JOptionPane 显示消息对话框

在 Java 开发中,JOptionPane 是一个非常实用的类,可以用来显示各种类型的对话框,例如信息对话框、警告对话框、错误对话框等。今天,我们将深入探讨如何使用 JOptionPane.showMessageDialog 方法来显示消息对话框,以及如…

RPA-UiBot6.0数据采集机器人(海量信息一网打尽)内附RPA师资培训课程

前言 友友们是否曾为海量的数据信息而头疼,不知道如何从中精准抓取你所需的数据?小北的这篇博客将为你揭晓答案,让我们一起学习如何运用RPA数据采集机器人,轻松实现海量信息的快速抓取与整理,助力你的工作效率翻倍&…

OrangePi 安装 CANN 套件及体验 AI 应用

CANN 环境安装(桌面端跳过) CANN 环境存在于下载页面的官方工具中,点击下载即可进入下载页面。 CANN 安装包就在倒数第二项,下载后传到开发板上。 给 CANN 安装包赋予运行权限并运行即可。 chmod x Ascend-cann-toolkit_7.0.0_l…

HTTP相关面试题

1. HTPP基本概念 HTTP是超文本传输协议。本质上就是一个可以传输图片、视频、文字的计算机与计算机之间的协议 1.1. HTTP常见的状态码 2XX状态码: 主要用于表示已经服务器已经成功的处理了请求 [200 ok ]: 是最常见的状态码,表示我们请求成功且响应内容(响应头body)已经收到…

[数据集][目标检测]猫狗检测数据集VOC+YOLO格式8291张2类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):8291 标注数量(xml文件个数):8291 标注数量(txt文件个数):8291 标注…